$ 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)}.
+
+Function: component
+Class: basic
+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
+
+Function: concat
+Class: basic
+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)}.
+
+Function: conj
+Class: basic
+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).
+
+Function: conjvec
+Class: basic
+Section: conversions
+C-Name: conjvec
+Prototype: Gp
+Help: conjvec(z): conjugate vector of the algebraic number z.
+Doc:
+ conjugate vector representation of $z$. If $z$ is a
+ polmod, equal to \kbd{Mod}$(a,T)$, this gives a vector of length
+ $\text{degree}(T)$ containing:
+
+ \item the complex embeddings of $z$ if $T$ has rational coefficients,
+ i.e.~the $a(r[i])$ where $r = \kbd{polroots}(T)$;
+
+ \item the conjugates of $z$ if $T$ has some intmod coefficients;
+
+ \noindent if $z$ is a finite field element, the result is the vector of
+ conjugates $[z,z^{p},z^{p^{2}},\ldots,z^{p^{n-1}}]$ where $n=\text{degree}(T)$.
+
+ \noindent If $z$ is an integer or a rational number, the result is~$z$. If
+ $z$ is a (row or column) vector, the result is a matrix whose columns are
+ the conjugate vectors of the individual elements of $z$.
+
+Function: content
+Class: basic
+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
+
+Function: contfrac
+Class: basic
+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}.
+
+Function: contfraceval
+Class: basic
+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}.
+
+Function: contfracinit
+Class: basic
+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)))$.
+
+Function: contfracpnqn
+Class: basic
+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$.
+
+Function: 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)
+
+Function: core
+Class: basic
+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$)
+
+Function: coredisc
+Class: basic
+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$)
+
+Function: cos
+Class: basic
+Section: transcendental
+C-Name: gcos
+Prototype: Gp
+Help: cos(x): cosine of x.
+Description:
+ (real):real mpcos($1)
+ (mp):real:prec gcos($1, $prec)
+ (gen):gen:prec gcos($1, $prec)
+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$.
+
+Function: cosh
+Class: basic
+Section: transcendental
+C-Name: gcosh
+Prototype: Gp
+Help: cosh(x): hyperbolic cosine of x.
+Description:
+ (mp):real:prec gcosh($1, $prec)
+ (gen):gen:prec gcosh($1, $prec)
+Doc: hyperbolic cosine of $x$.
+
+Function: cotan
+Class: basic
+Section: transcendental
+C-Name: gcotan
+Prototype: Gp
+Help: cotan(x): cotangent of x.
+Description:
+ (mp):real:prec gcotan($1, $prec)
+ (gen):gen:prec gcotan($1, $prec)
+Doc: cotangent of $x$.
+
+Function: cotanh
+Class: basic
+Section: transcendental
+C-Name: gcotanh
+Prototype: Gp
+Help: cotanh(x): hyperbolic cotangent of x.
+Description:
+ (mp):real:prec gcotanh($1, $prec)
+ (gen):gen:prec gcotanh($1, $prec)
+Doc: hyperbolic cotangent of $x$.
+
+Function: 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.
+
+Function: 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
+
+Function: 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.
+
+Function: dbg_x
+Class: basic
+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.
+
+Function: default
+Class: basic
+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}.
+
+Function: denominator
+Class: basic
+Section: conversions
+C-Name: denominator
+Prototype: GDG
+Help: denominator(f,{D}): denominator of f.
+Doc:
+ denominator of $f$. The meaning of this is clear when $f$ is a rational number
+ or function. If $f$ is an integer or a polynomial, it is treated as a rational
+ number or function, respectively, and the result is equal to $1$. For
+ polynomials, you probably want to use
+ \bprog
+ denominator( content(f) )
+ @eprog\noindent instead. As for modular objects, \typ{INTMOD} and \typ{PADIC}
+ have denominator $1$, and the denominator of a \typ{POLMOD} is the
+ denominator of its lift.
+
+ If $f$ is a recursive structure, for instance a vector or matrix, the lcm
+ of the denominators of its components (a common denominator) is computed.
+ This also applies for \typ{COMPLEX}s and \typ{QUAD}s.
+
+ \misctitle{Warning} Multivariate objects are created according to variable
+ priorities, with possibly surprising side effects ($x/y$ is a polynomial, but
+ $y/x$ is a rational function). See \secref{se:priority}.
+
+ The optional argument $D$ allows to control over which ring we compute the
+ denominator and get a more predictable behaviour:
+
+ \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;
+ ? denominator(f) \\ a t_POL in x
+ %2 = 1
+ ? denominator(f, 1) \\ Q-denominator
+ %3 = 2
+ ? denominator(f, x) \\ as a t_POL in x, seen above
+ %4 = 1
+ ? denominator(f, y) \\ as a rational function in y
+ %5 = 2*y
+ @eprog
+Variant: Also available are
+ \fun{GEN}{denom}{GEN x} which implements the not very useful default
+ behaviour ($D$ is \kbd{NULL}) and \fun{GEN}{Q_denom}{GEN x} ($D = 1$).
+
+Function: deriv
+Class: basic
+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
+
+Function: derivn
+Class: basic
+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
+
+Function: derivnum
+Class: basic
+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: diffop
+Class: basic
+Section: polynomials
+C-Name: diffop0
+Prototype: GGGD1,L,
+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.
+Description:
+ (gen,gen,gen,?1):gen diffop($1, $2, $3)
+ (gen,gen,gen,small):gen diffop0($1, $2, $3, $4)
+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.
+
+Function: digits
+Class: basic
+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
+
+Function: dilog
+Class: basic
+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}$.
+
+Function: dirdiv
+Class: basic
+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.
+
+Function: direuler
+Class: basic
+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}
+
+Function: dirmul
+Class: basic
+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
+
+Function: dirpowers
+Class: basic
+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{[]}.
+
+Function: dirpowerssum
+Class: basic
+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}.
+
+Function: dirzetak
+Class: basic
+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}.
+
+Function: divisors
+Class: basic
+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.
+
+Function: divisorslenstra
+Class: basic
+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$.)
+
+Function: divrem
+Class: basic
+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.
+
+Function: eint1
+Class: basic
+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}.
+
+Function: ell2cover
+Class: basic
+Section: elliptic_curves
+C-Name: ell2cover
+Prototype: Gp
+Help: 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)).
+Doc: 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$ is a point on $E(k)$, where $k = \Q(x)[y] / (y^{2}-R(x))$.
+ $E$ can also be given as the output of \kbd{ellrankinit(E)},
+ or as 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$.
+ \bprog
+ ? E = ellinit([-25,4]);
+ ? C = ell2cover(E); #C
+ %2 = 2
+ ? [R,P] = C[1]; R
+ %3 = 64*x^4+480*x^2-128*x+100
+ ? P[1]
+ %4 = -320/y^2*x^4 + 256/y^2*x^3 + 800/y^2*x^2 - 320/y^2*x - 436/y^2
+ ? ellisoncurve(E, Mod(P, y^2-R))
+ %5 = 1
+ ? H = hyperellratpoints(R,10)
+ %6 = [[0,10], [0,-10], [1/5,242/25], [1/5,-242/25], [2/5,282/25],
+ [2/5,-282/25]]
+ ? A = substvec(P,[x,y],H[1])
+ %7 = [-109/25, 686/125]
+ @eprog
+
+Function: ellE
+Class: basic
+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
+
+Function: ellK
+Class: basic
+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.
+
+Function: ellL1
+Class: basic
+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}.
+
+Function: elladd
+Class: basic
+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$.
+
+Function: ellak
+Class: basic
+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
+
+Function: ellan
+Class: basic
+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: ellanalyticrank
+Class: basic
+Section: elliptic_curves
+C-Name: ellanalyticrank
+Prototype: GDGb
+Help: ellanalyticrank(E,{eps}): returns the order of vanishing at s=1
+ of the L-function of the elliptic curve E and the value of the first
+ 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.
+Doc: returns the order of vanishing at $s=1$ of the $L$-function of the
+ elliptic curve $E/\Q$ and the value of the first nonzero derivative. To
+ determine this order, it is assumed that any value less than \kbd{eps} is
+ zero. If \kbd{eps} is omitted, $2^{-b/2}$ is used, where $b$
+ is the current bit precision.
+ \bprog
+ ? E = ellinit("11a1"); \\ rank 0
+ ? ellanalyticrank(E)
+ %2 = [0, 0.2538418608559106843377589233]
+ ? E = ellinit("37a1"); \\ rank 1
+ ? ellanalyticrank(E)
+ %4 = [1, 0.3059997738340523018204836835]
+ ? E = ellinit("389a1"); \\ rank 2
+ ? ellanalyticrank(E)
+ %6 = [2, 1.518633000576853540460385214]
+ ? E = ellinit("5077a1"); \\ rank 3
+ ? ellanalyticrank(E)
+ %8 = [3, 10.39109940071580413875185035]
+ @eprog\noindent Analogous and more general functionalities for $E$
+ defined over general number fields are available through \kbd{lfun}
+ and \kbd{lfunorderzero}.
+
+Function: ellap
+Class: basic
+Section: elliptic_curves
+C-Name: ellap
+Prototype: GDG
+Help: 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.
+Doc:
+ Let \kbd{E} be an \kbd{ell} structure as output by \kbd{ellinit}, attached
+ to an elliptic curve $E/K$. If the field $K = \F_{q}$ is finite, return the
+ trace of Frobenius $t$, defined by the equation $\#E(\F_{q}) = q+1 - t$.
+
+ For other fields of definition and $p$ defining a finite residue field
+ $\F_{q}$, return the trace of Frobenius for 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.
+
+ For a number field $K$, the trace of Frobenius is the $a_{p}$
+ coefficient in the Euler product defining the curve $L$-series, whence
+ the function name:
+ $$L(E/K,s) = \prod_{\text{bad}\ p} (1-a_{p} (Np)^{-s})^{-1}
+ \prod_{\text{good}\ p} (1-a_{p} (Np)^{-s} + (Np)^{1-2s})^{-1}. $$
+
+ When the characteristic of the finite field is large, the availability of
+ the \kbd{seadata} package will speed up the computation.
+
+ \bprog
+ ? E = ellinit([0,1]); \\ y^2 = x^3 + 0.x + 1, defined over Q
+ ? ellap(E, 7) \\ 7 necessary here
+ %2 = -4 \\ #E(F_7) = 7+1-(-4) = 12
+ ? ellcard(E, 7)
+ %3 = 12 \\ OK
+
+ ? E = ellinit([0,1], 11); \\ defined over F_11
+ ? ellap(E) \\ no need to repeat 11
+ %4 = 0
+ ? ellap(E, 11) \\ ... but it also works
+ %5 = 0
+ ? ellgroup(E, 13) \\ ouch, inconsistent input!
+ *** at top-level: ellap(E,13)
+ *** ^-----------
+ *** ellap: inconsistent moduli in Rg_to_Fp:
+ 11
+ 13
+ ? a = ffgen(ffinit(11,3), 'a); \\ defines F_q := F_{11^3}
+ ? E = ellinit([a+1,a]); \\ y^2 = x^3 + (a+1)x + a, defined over F_q
+ ? ellap(E)
+ %8 = -3
+ @eprog
+
+ If the curve is defined over a more general number field than $\Q$,
+ the maximal ideal $p$ must be explicitly given in \kbd{idealprimedec}
+ format. There is no assumption of local minimality at $p$.
+ \bprog
+ ? K = nfinit(a^2+1); E = ellinit([1+a,0,1,0,0], K);
+ ? fa = idealfactor(K, E.disc)
+ %2 =
+ [ [5, [-2, 1]~, 1, 1, [2, -1; 1, 2]] 1]
+
+ [[13, [5, 1]~, 1, 1, [-5, -1; 1, -5]] 2]
+ ? ellap(E, fa[1,1])
+ %3 = -1 \\ nonsplit multiplicative reduction
+ ? ellap(E, fa[2,1])
+ %4 = 1 \\ split multiplicative reduction
+ ? P17 = idealprimedec(K,17)[1];
+ ? ellap(E, P17)
+ %6 = 6 \\ good reduction
+ ? E2 = ellchangecurve(E, [17,0,0,0]);
+ ? ellap(E2, P17)
+ %8 = 6 \\ same, starting from a nonminimal model
+
+ ? P3 = idealprimedec(K,3)[1];
+ ? ellap(E, P3) \\ OK: E is minimal at P3
+ %10 = -2
+ ? E3 = ellchangecurve(E, [3,0,0,0]);
+ ? ellap(E3, P3) \\ not integral at P3
+ *** at top-level: ellap(E3,P3)
+ *** ^------------
+ *** ellap: impossible inverse in Rg_to_ff: Mod(0, 3).
+ @eprog
+
+ \misctitle{Algorithms used} If $E/\F_{q}$ has CM by a principal imaginary
+ quadratic order we use a fast explicit formula (involving essentially
+ Kronecker symbols and Cornacchia's algorithm), in $O(\log q)^{2}$ bit
+ operations.
+ Otherwise, we use Shanks-Mestre's baby-step/giant-step method, which runs in
+ time $\tilde{O}(q^{1/4})$ using $\tilde{O}(q^{1/4})$ storage, hence becomes
+ unreasonable when $q$ has about 30~digits. Above this range, the \tet{SEA}
+ algorithm becomes available, heuristically in $\tilde{O}(\log q)^{4}$, and
+ primes of the order of 200~digits become feasible. In small
+ characteristic we use Mestre's (p=2), Kohel's (p=3,5,7,13), Satoh-Harley
+ (all in $\tilde{O}(p^{2}\*n^{2})$) or Kedlaya's (in $\tilde{O}(p\*n^{3})$)
+ algorithms.
+
+Function: ellbil
+Class: basic
+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)}.
+
+Function: ellbsd
+Class: basic
+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
+
+Function: ellcard
+Class: basic
+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}.
+
+Function: ellchangecurve
+Class: basic
+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.
+
+Function: ellchangepoint
+Class: basic
+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.
+
+Function: ellchangepointinv
+Class: basic
+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
+
+Function: ellconvertname
+Class: basic
+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
+
+Function: elldivpol
+Class: basic
+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}$.
+
+Function: elleisnum
+Class: basic
+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
+
+Function: elleta
+Class: basic
+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
+
+Function: ellformaldifferential
+Class: basic
+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
+
+Function: ellformalexp
+Class: basic
+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
+
+Function: ellformallog
+Class: basic
+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
+
+Function: ellformalpoint
+Class: basic
+Section: elliptic_curves
+C-Name: ellformalpoint
+Prototype: GDPDn
+Help: ellformalpoint(E,{n=seriesprecision},{v='x}): E elliptic curve,
+ n integer; return the coordinates [x(t), y(t)] on the elliptic curve as a
+ formal expansion in the formal parameter t = -x/y.
+Doc: If $E$ is an elliptic curve, return the coordinates $x(t), y(t)$ in the
+ formal group of the elliptic curve $E$ in the formal parameter $t = -x/y$
+ at $\infty$:
+ $$ x = t^{-2} -a_{1} t^{-1} - a_{2} - a_{3} t + \dots $$
+ $$ y = - t^{-3} -a_{1} t^{-2} - a_{2}t^{-1} -a_{3} + \dots $$
+ Return $n$ terms (\tet{seriesprecision} by default) of these two power
+ series, whose coefficients are in $\Z[a_{1},a_{2},a_{3},a_{4},a_{6}]$.
+ \bprog
+ ? E = ellinit([0,0,1,-1,0]); [x,y] = ellformalpoint(E,8,'t);
+ ? x
+ %2 = t^-2 - t + t^2 - t^4 + 2*t^5 + O(t^6)
+ ? y
+ %3 = -t^-3 + 1 - t + t^3 - 2*t^4 + O(t^5)
+ ? E = ellinit([0,1/2]); ellformalpoint(E,7)
+ %4 = [x^-2 - 1/2*x^4 + O(x^5), -x^-3 + 1/2*x^3 + O(x^4)]
+ @eprog
+
+Function: ellformalw
+Class: basic
+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
+
+Function: ellfromeqn
+Class: basic
+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
+
+Function: ellfromj
+Class: basic
+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$).
+
+Function: ellgenerators
+Class: basic
+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.
+
+Function: ellglobalred
+Class: basic
+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).
+
+Function: ellgroup
+Class: basic
+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$.
+
+Function: ellheegner
+Class: basic
+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
+
+Function: ellheight
+Class: basic
+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).
+
+Function: ellheightmatrix
+Class: basic
+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.
+
+Function: ellidentify
+Class: basic
+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}.
+
+Function: ellinit
+Class: basic
+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.
+
+Function: ellintegralmodel
+Class: basic
+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
+
+Function: elliscm
+Class: basic
+Section: elliptic_curves
+C-Name: elliscm
+Prototype: lG
+Help: 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.
+Doc:
+ 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
+
+Function: ellisdivisible
+Class: basic
+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$.
+
+Function: ellisisom
+Class: basic
+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
+
+Function: ellisogeny
+Class: basic
+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
+
+Function: ellisogenyapply
+Class: basic
+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
+
+Function: ellisomat
+Class: basic
+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
+
+Function: ellisoncurve
+Class: basic
+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.
+
+Function: ellisotree
+Class: basic
+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
+
+Function: ellissupersingular
+Class: basic
+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.
+
+Function: ellj
+Class: basic
+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.
+
+Function: elllocalred
+Class: basic
+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}$.
+
+Function: elllog
+Class: basic
+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
+
+Function: elllseries
+Class: basic
+Section: elliptic_curves
+C-Name: elllseries
+Prototype: GGDGp
+Obsolete: 2016-08-08
+Help: elllseries(E,s,{A=1}): L-series at s of the elliptic curve E, where A
+ a cut-off point close to 1.
+Doc:
+ 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.
+
+Function: ellmaninconstant
+Class: basic
+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
+
+Function: ellminimaldisc
+Class: basic
+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.
+
+Function: ellminimalmodel
+Class: basic
+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
+
+Function: ellminimaltwist
+Class: basic
+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$.
+
+Function: ellmoddegree
+Class: basic
+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.
+
+Function: ellmodulareqn
+Class: basic
+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
+
+Function: ellmul
+Class: basic
+Section: elliptic_curves
+C-Name: ellmul
+Prototype: GGG
+Help: ellmul(E,z,n): n times the point z on elliptic curve E (n in Z).
+Doc:
+ computes $[n]z$, where $z$ is a point on the elliptic curve $E$. The
+ exponent $n$ is in $\Z$, or may be a complex quadratic integer if the curve $E$
+ has complex multiplication by $n$ (if not, an error message is issued).
+ \bprog
+ ? Ei = ellinit([1,0]); z = [0,0];
+ ? ellmul(Ei, z, 10)
+ %2 = [0] \\ unsurprising: z has order 2
+ ? ellmul(Ei, z, I)
+ %3 = [0, 0] \\ Ei has complex multiplication by Z[i]
+ ? ellmul(Ei, z, quadgen(-4))
+ %4 = [0, 0] \\ an alternative syntax for the same query
+ ? Ej = ellinit([0,1]); z = [-1,0];
+ ? ellmul(Ej, z, I)
+ *** at top-level: ellmul(Ej,z,I)
+ *** ^--------------
+ *** ellmul: not a complex multiplication in ellmul.
+ ? ellmul(Ej, z, 1+quadgen(-3))
+ %6 = [1 - w, 0]
+ @eprog
+ The simple-minded algorithm for the CM case assumes that we are in
+ characteristic $0$, and that the quadratic order to which $n$ belongs has
+ small discriminant.
+
+Function: ellneg
+Class: basic
+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$.
+
+Function: ellnonsingularmultiple
+Class: basic
+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
+
+Function: ellorder
+Class: basic
+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.
+
+Function: ellordinate
+Class: basic
+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.
+
+Function: ellpadicL
+Class: basic
+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.
+
+Function: ellpadicbsd
+Class: basic
+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
+
+Function: ellpadicfrobenius
+Class: basic
+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
+
+Function: ellpadicheight
+Class: basic
+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}.
+
+Function: ellpadicheightmatrix
+Class: basic
+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
+
+Function: ellpadiclambdamu
+Class: basic
+Section: elliptic_curves
+C-Name: ellpadiclambdamu
+Prototype: GLD1,L,D0,L,
+Help: 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.
+Doc: 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.
+
+Function: ellpadiclog
+Class: basic
+Section: elliptic_curves
+C-Name: ellpadiclog
+Prototype: GGLG
+Help: ellpadiclog(E,p,n,P): returns the logarithm of P (in the kernel of
+ reduction) to relative p-adic precision p^n.
+Doc: Given $E$ defined over $K = \Q$ or $\Q_{p}$ and $P = [x,y]$ on $E(K)$ in the
+ kernel of reduction mod $p$, let $t(P) = -x/y$ be the formal group
+ parameter; this function returns $L(t)$ 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
+
+Function: ellpadicregulator
+Class: basic
+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}).$$
+
+Function: ellpadics2
+Class: basic
+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.
+
+Function: ellperiods
+Class: basic
+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
+
+Function: ellpointtoz
+Class: basic
+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
+
+Function: ellpow
+Class: basic
+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}.
+
+Function: ellrank
+Class: basic
+Section: elliptic_curves
+C-Name: ellrank
+Prototype: GD0,L,DGp
+Help: 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).
+Doc: 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.
+
+Function: ellrankinit
+Class: basic
+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
+
+Function: ellratpoints
+Class: basic
+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
+
+Function: ellrootno
+Class: basic
+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.
+
+Function: ellsaturation
+Class: basic
+Section: elliptic_curves
+C-Name: ellsaturation
+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: 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$.
+
+Function: ellsearch
+Class: basic
+Section: elliptic_curves
+C-Name: ellsearch
+Prototype: G
+Help: ellsearch(N): returns all curves in the elldata database matching
+ constraint N: given name (N = "11a1" or [11,0,1]),
+ given isogeny class (N = "11a" or [11,0]), or
+ given conductor (N = 11, "11", or [11]).
+Doc: This function finds all curves in the \tet{elldata} database satisfying
+ the constraint defined by the argument $N$:
+
+ \item if $N$ is a character string, it selects a given curve, e.g.
+ \kbd{"11a1"}, or curves in the given isogeny class, e.g. \kbd{"11a"}, or
+ curves with given conductor, e.g. \kbd{"11"};
+
+ \item if $N$ is a vector of integers, it encodes the same constraints
+ as the character string above, according to the \tet{ellconvertname}
+ correspondance, e.g. \kbd{[11,0,1]} for \kbd{"11a1"}, \kbd{[11,0]} for
+ \kbd{"11a"} and \kbd{[11]} for \kbd{"11"};
+
+ \item if $N$ is an integer, curves with conductor $N$ are selected.
+
+ If $N$ 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
+Variant: Also available is \fun{GEN}{ellsearchcurve}{GEN N} that only
+ accepts complete curve names (as \typ{STR}).
+
+Function: ellsigma
+Class: basic
+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))$.
+
+Function: ellsub
+Class: basic
+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$.
+
+Function: ellsupersingularj
+Class: basic
+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
+
+Function: elltamagawa
+Class: basic
+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
+
+Function: elltaniyama
+Class: basic
+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}$.
+
+Function: elltatepairing
+Class: basic
+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}$.
+
+Function: elltors
+Class: basic
+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]$.
+
+Function: elltrace
+Class: basic
+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
+
+Function: elltwist
+Class: basic
+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
+
+Function: ellweilcurve
+Class: basic
+Section: elliptic_curves
+C-Name: ellweilcurve
+Prototype: GD&
+Help: 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.
+Doc: 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}.
+
+Function: ellweilpairing
+Class: basic
+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.
+
+Function: ellwp
+Class: basic
+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$.
+
+Function: ellxn
+Class: basic
+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
+
+Function: ellzeta
+Class: basic
+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
+
+Function: ellztopoint
+Class: basic
+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
+
+Function: erfc
+Class: basic
+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
+
+Function: errname
+Class: basic
+Section: programming/specific
+C-Name: errname
+Prototype: G
+Help: errname(E): returns the type of the error message E.
+Description:
+ (gen):errtyp err_get_num($1)
+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
+
+Function: error
+Class: basic
+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.
+
+Function: eta
+Class: basic
+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$).
+
+Function: eulerfrac
+Class: basic
+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
+
+Function: eulerianpol
+Class: basic
+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
+
+Function: eulerphi
+Class: basic
+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$.
+
+Function: eulerpol
+Class: basic
+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
+
+Function: eulerreal
+Class: basic
+Section: combinatorics
+C-Name: eulerreal
+Prototype: Lp
+Help: eulerreal(n): Euler number E_n, as a real 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. Return $E_{n}$
+ as a real number (with the current precision).
+ \bprog
+ ? sizedigit(eulerfrac(20000))
+ %1 = 73416
+ ? eulerreal(20000);
+ %2 = 9.2736664576330851823546169139003297830 E73414
+ @eprog
+
+Function: eulervec
+Class: basic
+Section: combinatorics
+C-Name: eulervec
+Prototype: L
+Help: eulervec(n): returns a vector containing
+ the nonzero Euler numbers E_0, E_2, ..., E_{2n}.
+Doc: returns a vector containing the nonzero \idx{Euler numbers} $E_{0}$,
+ $E_{2}$,\dots, $E_{2n}$:
+ \bprog
+ ? eulervec(5) \\ E_0, E_2..., E_10
+ %1 = [1, -1, 5, -61, 1385, -50521]
+ ? eulerfrac(10)
+ %2 = -50521
+ @eprog\noindent This routine uses more memory but is faster than
+ repeated calls to \kbd{eulerfrac}:
+ \bprog
+ ? forstep(n = 2, 8000, 2, eulerfrac(n))
+ time = 27,3801ms.
+ ? eulervec(4000);
+ time = 8,430 ms.
+ @eprog
+ The computed Euler numbers are stored in an incremental
+ cache which makes later calls to \kbd{eulerfrac} and \kbd{eulerreal}
+ instantaneous in the cache range: re-running the same previous \kbd{eulerfrac}s
+ after the \kbd{eulervec} call gives:
+ \bprog
+ ? forstep(n = 2, 10000, 2, eulerfrac(n))
+ time = 0 ms.
+ @eprog
+
+Function: eval
+Class: basic
+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}.
+
+Function: exp
+Class: basic
+Section: transcendental
+C-Name: gexp
+Prototype: Gp
+Help: exp(x): exponential of x.
+Description:
+ (real):real mpexp($1)
+ (mp):real:prec gexp($1, $prec)
+ (gen):gen:prec gexp($1, $prec)
+Doc: exponential of $x$.
+ $p$-adic arguments with positive valuation are accepted.
+Variant: For a \typ{PADIC} $x$, the function
+ \fun{GEN}{Qp_exp}{GEN x} is also available.
+
+Function: expm1
+Class: basic
+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}.
+
+Function: exponent
+Class: basic
+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}.
+
+Function: export
+Class: basic
+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
+
+Function: exportall
+Class: basic
+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
+
+Function: extern
+Class: basic
+Section: programming/specific
+C-Name: gpextern
+Prototype: s
+Help: extern(str): execute shell command str, and feeds the result to GP (as
+ if loading from file).
+Doc: the string \var{str} is the name of an external command (i.e.~one you
+ would type from your UNIX shell prompt). This command is immediately run and
+ its output fed into \kbd{gp}, just as if read from a file.
+
+Function: externstr
+Class: basic
+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.
+
+Function: factor
+Class: basic
+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: factorback
+Class: basic
+Section: number_theoretical
+C-Name: factorback2
+Prototype: GDG
+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].
+Description:
+ (gen):gen factorback($1)
+ (gen,):gen factorback($1)
+ (gen,gen):gen factorback2($1, $2)
+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}$).
+
+Function: factorcantor
+Class: basic
+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.
+
+Function: factorff
+Class: basic
+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.
+
+Function: factorial
+Class: basic
+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}.
+
+Function: factorint
+Class: basic
+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).
+
+Function: factormod
+Class: basic
+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
+
+Function: factormodDDF
+Class: basic
+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
+
+Function: factormodSQF
+Class: basic
+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
+
+Function: factormodcyclo
+Class: basic
+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
+
+Function: factornf
+Class: basic
+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
+
+Function: factorpadic
+Class: basic
+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.
+
+Function: ffcompomap
+Class: basic
+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
+
+Function: ffembed
+Class: basic
+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
+
+Function: ffextend
+Class: basic
+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
+
+Function: fffrobenius
+Class: basic
+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
+
+Function: ffgen
+Class: basic
+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}.
+
+Function: ffinit
+Class: basic
+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}.
+
+Function: ffinvmap
+Class: basic
+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
+
+Function: fflog
+Class: basic
+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: ffmap
+Class: basic
+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
+
+Function: ffmaprel
+Class: basic
+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
+
+Function: ffnbirred
+Class: basic
+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$).
+
+Function: fforder
+Class: basic
+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
+
+Function: ffprimroot
+Class: basic
+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
+
+Function: fft
+Class: basic
+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
+
+Function: fftinv
+Class: basic
+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
+
+Function: fibonacci
+Class: basic
+Section: combinatorics
+C-Name: fibo
+Prototype: L
+Help: fibonacci(x): Fibonacci number of index x.
+Doc: $x^{\text{th}}$ Fibonacci number.
+
+Function: fileclose
+Class: basic
+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
+
+Function: fileextern
+Class: basic
+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.
+
+Function: fileflush
+Class: basic
+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.
+
+Function: fileopen
+Class: basic
+Section: programming/specific
+C-Name: gp_fileopen
+Prototype: lsD"r",s,
+Help: 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).
+Doc: open the file pointed to by 'path' and return a file descriptor which
+ can be used with other file functions.
+
+ The mode can be
+
+ \item \kbd{"r"} (default): open for reading; allow \kbd{fileread} and
+ \kbd{filereadstr}.
+
+ \item \kbd{"w"}: open for writing, discarding existing content; allow
+ \kbd{filewrite}, \kbd{filewrite1}.
+
+ \item \kbd{"a"}: open for writing, appending to existing content; same
+ operations allowed as \kbd{"w"}.
+
+ Eventually, the file should be closed and the descriptor recycled using
+ \kbd{fileclose}.
+
+ \bprog
+ ? n = fileopen("./here"); \\ "r" by default
+ ? while (l = filereadstr(n), print(l)) \\ print successive lines
+ ? fileclose(n) \\ done
+ @eprog\noindent In \emph{read} mode, raise an exception if the file does not
+ exist or the user does not have read permission. In \emph{write} mode, raise
+ an exception if the file cannot be written to. Trying to read or write to a
+ file that was not opend with the right mode raises an exception.
+ \bprog
+ ? n = fileopen("./read", "r");
+ ? filewrite(n, "test") \\ not open for writing
+ *** at top-level: filewrite(n,"test")
+ *** ^-------------------
+ *** filewrite: invalid file descriptor 0
+ @eprog
+
+Function: fileread
+Class: basic
+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
+
+Function: filereadstr
+Class: basic
+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).
+
+Function: filewrite
+Class: basic
+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
+
+Function: filewrite1
+Class: basic
+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}.
+
+Function: floor
+Class: basic
+Section: conversions
+C-Name: gfloor
+Prototype: G
+Help: floor(x): floor of x = largest integer <= x.
+Description:
+ (small):small:parens $1
+ (int):int:copy:parens $1
+ (real):int floorr($1)
+ (mp):int mpfloor($1)
+ (gen):gen gfloor($1)
+Doc:
+ floor of $x$. When $x$ is in $\R$, the result is the
+ largest integer smaller than or equal to $x$. Applied to a rational function,
+ $\kbd{floor}(x)$ returns the Euclidean quotient of the numerator by the
+ denominator.
+
+Function: fold
+Class: basic
+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}.
+
+Function: for
+Class: basic
+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}.
+
+Function: forcomposite
+Class: basic
+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
+
+Function: fordiv
+Class: basic
+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.
+
+Function: fordivfactored
+Class: basic
+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
+
+Function: foreach
+Class: basic
+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)$.
+
+Function: forell
+Class: basic
+Section: programming/control
+C-Name: forell0
+Prototype: vVLLID0,L,
+Help: 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.
+Wrapper: (,,,vG,)
+Description:
+ (,small,small,closure,?small):void forell(${4 cookie}, ${4 wrapper}, $2, $3, $5)
+Doc: evaluates \var{seq}, where the formal variable $E = [\var{name}, M, G]$
+ ranges through all elliptic curves of conductors from $a$ to $b$. In this
+ notation \var{name} is the curve name in Cremona's elliptic curve database,
+ $M$ is the minimal model, $G$ is a $\Z$-basis of the free part of the
+ Mordell-Weil group $E(\Q)$. If $\fl$ is nonzero, select
+ only the first curve in each isogeny class.
+ \bprog
+ ? forell(E, 1, 500, my([name,M,G] = E); \
+ if (#G > 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}.
+
+Function: forfactored
+Class: basic
+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
+
+Function: forpart
+Class: basic
+Section: programming/control
+C-Name: forpart0
+Prototype: vV=GIDGDG
+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).
+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)
+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}.
+
+Function: forperm
+Class: basic
+Section: programming/control
+C-Name: forperm0
+Prototype: vGVI
+Help: forperm(a,p,seq): the sequence is evaluated, p going through permutations of a.
+Iterator:
+ (gen,gen) (forperm, _forperm_init, _forperm_next)
+Wrapper: (,vG,,)
+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
+
+Function: forprime
+Class: basic
+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
+
+Function: forprimestep
+Class: basic
+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
+
+Function: forqfvec
+Class: basic
+Section: linear_algebra
+C-Name: forqfvec0
+Prototype: vVGDGI
+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.
+Wrapper: (,,,vG)
+Description:
+ (,gen,?gen,closure):void forqfvec1(${4 cookie}, ${4 wrapper}, $2, $3)
+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)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
+
+Function: forstep
+Class: basic
+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 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
+
+Function: frac
+Class: basic
+Section: conversions
+C-Name: gfrac
+Prototype: G
+Help: frac(x): fractional part of x = x-floor(x).
+Doc:
+ fractional part of $x$. Identical to
+ $x-\text{floor}(x)$. If $x$ is real, the result is in $[0,1[$.
+
+Function: fromdigits
+Class: basic
+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}$.
+
+Function: galoischardet
+Class: basic
+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
+
+Function: galoischarpoly
+Class: basic
+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
+
+Function: galoischartable
+Class: basic
+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
+
+Function: galoisconjclasses
+Class: basic
+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
+
+Function: galoisexport
+Class: basic
+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
+
+Function: galoisfixedfield
+Class: basic
+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)$
+
+Function: galoisgetgroup
+Class: basic
+Section: number_fields
+C-Name: galoisgetgroup
+Prototype: LD0,L,
+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.
+Description:
+ (small):int galoisnbpol($1)
+ (small,):int galoisnbpol($1)
+ (small,small):vec galoisgetgroup($1, $2)
+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.
+
+Function: galoisgetname
+Class: basic
+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
+
+Function: galoisgetpol
+Class: basic
+Section: number_fields
+C-Name: galoisgetpol
+Prototype: LD0,L,D1,L,
+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.
+Description:
+ (small):int galoisnbpol($1)
+ (small,):int galoisnbpol($1)
+ (small,,):int galoisnbpol($1)
+ (small,small,small):vec galoisgetpol($1, $2 ,$3)
+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.
+
+Function: galoisidentify
+Class: basic
+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.
+
+Function: galoisinit
+Class: basic
+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 $i 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_{j0$.
+
+ \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
+
+Function: gcharduallog
+Class: basic
+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
+
+Function: gchareval
+Class: basic
+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
+
+Function: gcharidentify
+Class: basic
+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
+
+Function: gcharinit
+Class: basic
+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}$.
+
+Function: gcharisalgebraic
+Class: basic
+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
+
+Function: gcharlocal
+Class: basic
+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
+
+Function: gcharlog
+Class: basic
+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
+
+Function: gcharnewprec
+Class: basic
+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.
+
+Function: genus2igusa
+Class: basic
+Section: elliptic_curves
+C-Name: genus2igusa
+Prototype: GD0,L,
+Help: 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.
+Doc: 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
+
+Function: genus2red
+Class: basic
+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)]}.
+
+Function: getabstime
+Class: basic
+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}.
+
+Function: getcache
+Class: basic
+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
+
+Function: getenv
+Class: basic
+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.
+
+Function: getheap
+Class: basic
+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.
+
+Function: getlocalbitprec
+Class: basic
+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}
+
+Function: getlocalprec
+Class: basic
+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}
+
+Function: getrand
+Class: basic
+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}.
+
+Function: getstack
+Class: basic
+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.
+
+Function: gettime
+Class: basic
+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}.
+
+Function: getwalltime
+Class: basic
+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
+
+Function: global
+Class: basic
+Section: programming/specific
+Obsolete: 2007-10-03
+Help: global(list of variables): obsolete. Scheduled for deletion.
+Doc: obsolete. Scheduled for deletion.
+ % \syn{NO}
+
+Function: halfgcd
+Class: basic
+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]$.
+
+Function: hammingweight
+Class: basic
+Section: combinatorics
+C-Name: hammingweight
+Prototype: lG
+Help: hammingweight(x): returns the Hamming weight of x.
+Doc:
+ If $x$ is a \typ{INT}, return the binary Hamming weight of $|x|$. Otherwise
+ $x$ must be of type \typ{POL}, \typ{VEC}, \typ{COL}, \typ{VECSMALL}, or
+ \typ{MAT} and the function returns the number of nonzero coefficients of
+ $x$.
+ \bprog
+ ? hammingweight(15)
+ %1 = 4
+ ? hammingweight(x^100 + 2*x + 1)
+ %2 = 3
+ ? hammingweight([Mod(1,2), 2, Mod(0,3)])
+ %3 = 2
+ ? hammingweight(matid(100))
+ %4 = 100
+ @eprog
+
+Function: harmonic
+Class: basic
+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$.
+
+Function: hgmalpha
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgmalpha
+Prototype: G
+Help: hgmalpha(H): returns the alpha and beta parameters of the hypergeometric
+ motive template H.
+Doc: 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
+
+Function: hgmbydegree
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgmbydegree
+Prototype: L
+Help: 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.
+Doc: 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$.
+
+Function: hgmcoef
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgmcoef
+Prototype: GGG
+Help: hgmcoef(H,t,n): (H,t) being a hypergeometric motive, returns the
+ n-th coefficient of its L-function.
+Doc: $(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$.
+
+Function: hgmcoefs
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgmcoefs
+Prototype: GGL
+Help: 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.
+Doc: $(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.
+
+Function: hgmcyclo
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgmcyclo
+Prototype: G
+Help: hgmcyclo(H): returns the cyclotomic parameters (D,E) of the
+ hypergeometric motive template H.
+Doc: 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
+
+Function: hgmeulerfactor
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgmeulerfactor
+Prototype: GGLD&
+Help: 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.
+Doc: $(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
+
+Function: hgmgamma
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgmgamma
+Prototype: G
+Help: hgmgamma(H): returns the gamma vector of the hypergeometric motive
+ template H.
+Doc: returns the gamma vector of the hypergeometric motive
+ template $H$.
+ \bprog
+ ? H = hgminit([5]);
+ ? hgmgamma(H)
+ %2 = Vecsmall([-5, 0, 0, 0, 1])
+ @eprog
+
+Function: hgminit
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgminit
+Prototype: GDG
+Help: 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.
+Doc: 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
+
+Function: hgmissymmetrical
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgmissymmetrical
+Prototype: lG
+Help: hgmissymmetrical(H): is the hypergeometric motive template H symmetrical
+ at t=1?
+Doc: 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
+
+Function: hgmparams
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgmparams
+Prototype: G
+Help: 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.
+Doc: $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}}$.
+
+Function: hgmtwist
+Class: basic
+Section: hypergeometric_motives
+C-Name: hgmtwist
+Prototype: G
+Help: hgmtwist(H): twist by 1/2 of alpha and beta of the hypergeometric motive
+ template H.
+Doc: 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.
+
+Function: hilbert
+Class: basic
+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.)
+
+Function: hyperellchangecurve
+Class: basic
+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.
+
+Function: hyperellcharpoly
+Class: basic
+Section: elliptic_curves
+C-Name: hyperellcharpoly
+Prototype: G
+Help: 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.
+Doc:
+ $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.
+
+Function: hyperelldisc
+Class: basic
+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
+
+Function: hyperellisoncurve
+Class: basic
+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
+
+Function: hyperellminimaldisc
+Class: basic
+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
+
+Function: hyperellminimalmodel
+Class: basic
+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
+
+Function: hyperellordinate
+Class: basic
+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.
+
+Function: hyperellpadicfrobenius
+Class: basic
+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.
+
+Function: hyperellratpoints
+Class: basic
+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} 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]}
+
+Function: hypergeom
+Class: basic
+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.
+
+Function: hyperu
+Class: basic
+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
+
+Function: idealadd
+Class: basic
+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))}.
+
+Function: idealaddtoone
+Class: basic
+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$.
+
+Function: idealappr
+Class: basic
+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.
+
+Function: idealchinese
+Class: basic
+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}$.
+
+Function: idealcoprime
+Class: basic
+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$.
+
+Function: idealdiv
+Class: basic
+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$).
+
+Function: idealdown
+Class: basic
+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
+
+Function: idealfactor
+Class: basic
+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}.
+
+Function: idealfactorback
+Class: basic
+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.
+
+Function: idealfrobenius
+Class: basic
+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}$.
+
+Function: idealhnf
+Class: basic
+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.
+
+Function: idealintersect
+Class: basic
+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
+
+Function: idealinv
+Class: basic
+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]$.
+
+Function: idealismaximal
+Class: basic
+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.
+
+Function: idealispower
+Class: basic
+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
+
+Function: ideallist
+Class: basic
+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.
+
+Function: ideallistarch
+Class: basic
+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
+
+Function: ideallog
+Class: basic
+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}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
+
+Function: idealprincipalunits
+Class: basic
+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
+
+Function: idealramgroups
+Class: basic
+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$.
+
+Function: idealred
+Class: basic
+Section: number_fields
+C-Name: idealred0
+Prototype: GGDG
+Help: idealred(nf,I,{v=0}): LLL reduction of the ideal I in the number
+ field nf along direction v, in HNF.
+Doc: \idx{LLL} reduction of
+ the ideal $I$ in the number field $K$ attached to \var{nf}, along the
+ direction $v$. The $v$ parameter is best left omitted, but if it is present,
+ it must be an $\kbd{nf.r1} + \kbd{nf.r2}$-component vector of
+ \emph{nonnegative} integers. (What counts is the relative magnitude of the
+ entries: if all entries are equal, the effect is the same as if the vector
+ had been omitted.)
+
+ This function finds an $a\in K^{*}$ such that $J = (a)I$ is
+ ``small'' and integral (see the end for technical details).
+ The result is the Hermite normal form of
+ the ``reduced'' ideal $J$.
+ \bprog
+ ? K = nfinit(y^2+1);
+ ? P = idealprimedec(K,5)[1];
+ ? idealred(K, P)
+ %3 =
+ [1 0]
+
+ [0 1]
+ @eprog\noindent More often than not, a \idx{principal ideal} yields the unit
+ ideal as above. This is a quick and dirty way to check if ideals are principal,
+ but it is not a necessary condition: a nontrivial result does not prove that
+ the ideal is nonprincipal. For guaranteed results, see \kbd{bnfisprincipal},
+ which requires the computation of a full \kbd{bnf} structure.
+
+ If the input is an extended ideal $[I,s]$, the output is $[J, sa]$; in
+ this way, one keeps track of the principal ideal part:
+ \bprog
+ ? idealred(K, [P, 1])
+ %5 = [[1, 0; 0, 1], [2, -1]~]
+ @eprog\noindent
+ meaning that $P$ is generated by $[2, -1]~$. The number field element in the
+ extended part is an algebraic number in any form \emph{or} a factorization
+ matrix (in terms of number field elements, not ideals!). In the latter case,
+ elements stay in factored form, which is a convenient way to avoid
+ coefficient explosion; see also \tet{idealpow}.
+
+ \misctitle{Technical note} The routine computes an LLL-reduced
+ basis for the lattice $I^{-1}$ equipped with the quadratic
+ form
+ $$|| x ||_{v}^{2} = \sum_{i=1}^{r_{1}+r_{2}}
+ 2^{v_{i}}\varepsilon_{i}|\sigma_{i}(x)|^{2},$$
+ where as usual the $\sigma_{i}$ are the (real and) complex embeddings and
+ $\varepsilon_{i} = 1$, resp.~$2$, for a real, resp.~complex place. The element
+ $a$ is simply the first vector in the LLL basis. The only reason you may want
+ to try to change some directions and set some $v_{i}\neq 0$ is to randomize
+ the elements found for a fixed ideal, which is heuristically useful in index
+ calculus algorithms like \tet{bnfinit} and \tet{bnfisprincipal}.
+
+ \misctitle{Even more technical note} In fact, the above is a white lie.
+ We do not use $||\cdot||_{v}$ exactly but a rescaled rounded variant which
+ gets us faster and simpler LLLs. There's no harm since we are not using any
+ theoretical property of $a$ after all, except that it belongs to $I^{-1}$
+ and that $a I$ is ``expected to be small''.
+
+Function: idealredmodpower
+Class: basic
+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
+
+Function: idealstar
+Class: basic
+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.
+
+Function: idealtwoelt
+Class: basic
+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}.
+
+Function: idealval
+Class: basic
+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.
+
+Function: if
+Class: basic
+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: iferr
+Class: basic
+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$.
+
+Function: imag
+Class: basic
+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
+
+Function: incgam
+Class: basic
+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}.
+
+Function: incgamc
+Class: basic
+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$.
+
+Function: inline
+Class: basic
+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}.
+
+Function: input
+Class: basic
+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).
+
+Function: install
+Class: basic
+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.
+
+Function: intcirc
+Class: basic
+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}.
+
+Function: intformal
+Class: basic
+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
+
+Function: intfuncinit
+Class: basic
+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}.
+
+Function: intnum
+Class: basic
+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}.
+
+Function: intnumgauss
+Class: basic
+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
+
+Function: intnumgaussinit
+Class: basic
+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}.
+
+Function: intnuminit
+Class: basic
+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$.
+
+Function: intnumosc
+Class: basic
+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
+
+Function: intnumromb
+Class: basic
+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}.
+
+Function: isfundamental
+Class: basic
+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
+
+Function: ispolygonal
+Class: basic
+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
+
+Function: ispower
+Class: basic
+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).
+
+Function: ispowerful
+Class: basic
+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
+
+Function: isprime
+Class: basic
+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: isprimepower
+Class: basic
+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$.
+
+Function: ispseudoprime
+Class: basic
+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$).
+
+Function: ispseudoprimepower
+Class: basic
+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.
+
+Function: issquare
+Class: basic
+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.
+
+Function: issquarefree
+Class: basic
+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
+
+Function: istotient
+Class: basic
+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
+
+Function: kill
+Class: basic
+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
+
+Function: kronecker
+Class: basic
+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$.
+
+Function: lambertw
+Class: basic
+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))$.
+
+Function: laurentseries
+Class: basic
+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}.
+
+Function: lcm
+Class: basic
+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
+
+Function: length
+Class: basic
+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.
+
+Function: lerchphi
+Class: basic
+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.
+
+Function: lerchzeta
+Class: basic
+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: lex
+Class: basic
+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
+
+Function: lfun
+Class: basic
+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
+
+Function: lfunan
+Class: basic
+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
+
+Function: lfunartin
+Class: basic
+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: lfuncheckfeq
+Class: basic
+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
+
+Function: lfunconductor
+Class: basic
+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
+
+Function: lfuncost
+Class: basic
+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.
+
+Function: lfuncreate
+Class: basic
+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
+
+Function: lfundiv
+Class: basic
+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.
+
+Function: lfundual
+Class: basic
+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
+
+Function: lfunetaquo
+Class: basic
+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
+
+Function: lfuneuler
+Class: basic
+Section: l_functions
+C-Name: lfuneuler
+Prototype: GGp
+Help: 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.
+Doc: 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
+
+Function: lfungenus2
+Class: basic
+Section: l_functions
+C-Name: lfungenus2
+Prototype: G
+Help: 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.
+Doc: 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).
+
+Function: lfunhardy
+Class: basic
+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
+
+Function: lfunthetainit
+Class: basic
+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
+
+Function: lfuntwist
+Class: basic
+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$.
+
+Function: lfunzeros
+Class: basic
+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.
+
+Function: lift
+Class: basic
+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)}.
+
+Function: liftall
+Class: basic
+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
+
+Function: liftint
+Class: basic
+Section: conversions
+C-Name: liftint
+Prototype: G
+Help: liftint(x): lifts every element of Z/nZ to Z and of Qp to Q.
+Description:
+ (pol):pol liftint($1)
+ (vec):vec liftint($1)
+ (gen):gen liftint($1)
+Doc: recursively lift all components of $x$ from $\Z/n\Z$ to $\Z$ and
+ from $\Q_{p}$ to $\Q$ (as \tet{truncate}).
+ \typ{FFELT} are not lifted, nor are List elements: you may
+ convert the latter to vectors first, or use \kbd{apply(liftint,L)}. More
+ generally, components for which such lifts are meaningless (e.g. character
+ strings) are copied verbatim.
+ \bprog
+ ? liftint(x * (1 + O(3)) + Mod(2,3))
+ %1 = x + 2
+ ? liftint(x * Mod(y,y^2+1) + Mod(2,3)*Mod(z,z^2))
+ %2 = Mod(y, y^2 + 1)*x + Mod(Mod(2*z, z^2), y^2 + 1)
+ @eprog
+
+Function: liftpol
+Class: basic
+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
+
+Function: limitnum
+Class: basic
+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.
+
+Function: lindep
+Class: basic
+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
+
+Function: listcreate
+Class: basic
+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}
+
+Function: listinsert
+Class: basic
+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.
+
+Function: listkill
+Class: basic
+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.
+
+Function: listpop
+Class: basic
+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.
+
+Function: listput
+Class: basic
+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.
+
+Function: listsort
+Class: basic
+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
+
+Function: lngamma
+Class: basic
+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
+
+Function: local
+Class: basic
+Section: programming/specific
+Help: local(x,...,z): declare x,...,z as (dynamically scoped) local variables.
+
+Function: localbitprec
+Class: basic
+Section: programming/specific
+C-Name: localbitprec
+Prototype: vG
+Help: localbitprec(p): set the real precision to p bits in the dynamic scope.
+Doc: set the real precision to $p$ bits in the dynamic scope.
+ All computations are performed as if \tet{realbitprecision} was $p$:
+ transcendental constants (e.g.~\kbd{Pi}) and
+ conversions from exact to floating point inexact data use $p$ bits, as well as
+ iterative routines implicitly using a floating point
+ accuracy as a termination criterion (e.g.~\tet{solve} or \tet{intnum}).
+ But \kbd{realbitprecision} itself is unaffected
+ and is ``unmasked'' when we exit the dynamic (\emph{not} lexical) scope.
+ In effect, this is similar to
+ \bprog
+ my(bit = default(realbitprecision));
+ default(realbitprecision,p);
+ ...
+ default(realbitprecision, bit);
+ @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{realbitprecision} will not be restored as intended.
+
+ Such \kbd{localbitprec} statements can be nested, the innermost one taking
+ precedence as expected. Beware that \kbd{localbitprec} follows the semantic of
+ \tet{local}, not \tet{my}: a subroutine called from \kbd{localbitprec} scope
+ uses the local accuracy:
+ \bprog
+ ? f()=bitprecision(1.0);
+ ? f()
+ %2 = 128
+ ? localbitprec(1000); f()
+ %3 = 1024
+ @eprog\noindent Note that the bit precision of \emph{data} (\kbd{1.0} in the
+ above example) increases by steps of 64 (32 on a 32-bit machine) so we get
+ $1024$ instead of the expected $1000$; \kbd{localbitprec} bounds the
+ relative error exactly as specified in functions that support that
+ granularity (e.g.~\kbd{lfun}), and rounded to the next multiple of 64
+ (resp.~32) everywhere else.
+
+ \misctitle{Warning} Changing \kbd{realbitprecision} or \kbd{realprecision}
+ in programs is deprecated in favor of \kbd{localbitprec} and
+ \kbd{localprec}. Think about the \kbd{realprecision} and
+ \kbd{realbitprecision} defaults as interactive commands 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,1000); Pi
+ %1 = 3.141592653589793239
+ ? \p
+ realprecision = 1001 significant digits (1000 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 the \kbd{localprec} scope, \kbd{realprecision} only regains precedence,
+ it is not ``restored'' to the original value.
+ %\syn{NO}
+
+Function: localprec
+Class: basic
+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}
+
+Function: log
+Class: basic
+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.
+
+Function: log1p
+Class: basic
+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
+
+Function: logint
+Class: basic
+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.
+
+Function: mapapply
+Class: basic
+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
+
+Function: mapdelete
+Class: basic
+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
+
+Function: mapget
+Class: basic
+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
+
+Function: mapisdefined
+Class: basic
+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
+
+Function: mapput
+Class: basic
+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
+
+Function: matadjoint
+Class: basic
+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$).
+
+Function: matalgtobasis
+Class: basic
+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$.
+
+Function: matbasistoalg
+Class: basic
+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$.
+
+Function: matcompanion
+Class: basic
+Section: linear_algebra
+C-Name: matcompanion
+Prototype: G
+Help: matcompanion(x): companion matrix to polynomial x.
+Doc:
+ the left companion matrix to the nonzero polynomial $x$.
+
+Function: matconcat
+Class: basic
+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
+
+Function: matdet
+Class: basic
+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: matdetint
+Class: basic
+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.
+
+Function: matdetmod
+Class: basic
+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
+
+Function: matdiagonal
+Class: basic
+Section: linear_algebra
+C-Name: diagonal
+Prototype: G
+Help: matdiagonal(x): creates the diagonal matrix whose diagonal entries are
+ the entries of the vector x.
+Doc: $x$ being a vector, creates the diagonal matrix
+ whose diagonal entries are those of $x$.
+ \bprog
+ ? matdiagonal([1,2,3]);
+ %1 =
+ [1 0 0]
+
+ [0 2 0]
+
+ [0 0 3]
+ @eprog\noindent Block diagonal matrices are easily created using
+ \tet{matconcat}:
+ \bprog
+ ? U=[1,2;3,4]; V=[1,2,3;4,5,6;7,8,9];
+ ? matconcat(matdiagonal([U, V]))
+ %1 =
+ [1 2 0 0 0]
+
+ [3 4 0 0 0]
+
+ [0 0 1 2 3]
+
+ [0 0 4 5 6]
+
+ [0 0 7 8 9]
+ @eprog
+
+Function: mateigen
+Class: basic
+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$)
+
+Function: matfrobenius
+Class: basic
+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$.
+
+Function: mathess
+Class: basic
+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).
+
+Function: mathilbert
+Class: basic
+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.
+
+Function: mathnf
+Class: basic
+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}.
+
+Function: mathnfmod
+Class: basic
+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.
+
+Function: mathnfmodid
+Class: basic
+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
+
+Function: mathouseholder
+Class: basic
+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$.
+
+Function: matid
+Class: basic
+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.
+
+Function: matimage
+Class: basic
+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$).
+
+Function: matimagecompl
+Class: basic
+Section: linear_algebra
+C-Name: imagecompl
+Prototype: G
+Help: matimagecompl(x): vector of column indices not corresponding to the
+ indices given by the function matimage.
+Description:
+ (gen):vecsmall imagecompl($1)
+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$.
+
+Function: matimagemod
+Class: basic
+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
+
+Function: matindexrank
+Class: basic
+Section: linear_algebra
+C-Name: indexrank
+Prototype: G
+Help: matindexrank(M): gives two extraction vectors (rows and columns) for
+ the matrix M such that the extracted matrix is square of maximal rank.
+Description:
+ (gen):vecvecsmall indexrank($1)
+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.
+
+Function: matintersect
+Class: basic
+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.
+
+Function: matinverseimage
+Class: basic
+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
+
+Function: matinvmod
+Class: basic
+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
+
+Function: matisdiagonal
+Class: basic
+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.
+
+Function: matker
+Class: basic
+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: matkerint
+Class: basic
+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.
+
+Function: matkermod
+Class: basic
+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
+
+Function: matmuldiagonal
+Class: basic
+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)$.
+
+Function: matmultodiagonal
+Class: basic
+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.
+
+Function: matpascal
+Class: basic
+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}.
+
+Function: matpermanent
+Class: basic
+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.
+
+Function: matqr
+Class: basic
+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.
+
+Function: matrank
+Class: basic
+Section: linear_algebra
+C-Name: rank
+Prototype: lG
+Help: matrank(x): rank of the matrix x.
+Doc: rank of the matrix $x$.
+
+Function: matreduce
+Class: basic
+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
+
+Function: matrix
+Class: basic
+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}
+
+Function: matrixqz
+Class: basic
+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
+
+Function: matsize
+Class: basic
+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).
+
+Function: matsnf
+Class: basic
+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
+
+Function: matsolve
+Class: basic
+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: matsolvemod
+Class: basic
+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$).
+
+Function: matsupplement
+Class: basic
+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
+
+Function: mattranspose
+Class: basic
+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.
+
+Function: max
+Class: basic
+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.
+
+Function: mfDelta
+Class: basic
+Section: modular_forms
+C-Name: mfDelta
+Prototype:
+Help: mfDelta(): mf corresponding to the Ramanujan Delta function.
+Doc: mf structure corresponding to the Ramanujan Delta function $\Delta$.
+ \bprog
+ ? mfcoefs(mfDelta(),4)
+ %1 = [0, 1, -24, 252, -1472]
+ @eprog
+
+Function: mfEH
+Class: basic
+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
+
+Function: mfEk
+Class: basic
+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
+
+Function: mfTheta
+Class: basic
+Section: modular_forms
+C-Name: mfTheta
+Prototype: DG
+Help: 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.
+Doc: 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
+
+Function: mfatkin
+Class: basic
+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
+
+Function: mfatkineigenvalues
+Class: basic
+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}$.
+
+Function: mfatkininit
+Class: basic
+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
+
+Function: mfbasis
+Class: basic
+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
+
+Function: mfbd
+Class: basic
+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
+
+Function: mfbracket
+Class: basic
+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
+
+Function: mfcoef
+Class: basic
+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
+
+Function: mfcoefs
+Class: basic
+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
+
+Function: mfconductor
+Class: basic
+Section: modular_forms
+C-Name: mfconductor
+Prototype: lGG
+Help: mfconductor(mf,F): mf being output by mfinit and F a modular form,
+ gives the smallest level at which F is defined.
+Doc: \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
+
+Function: mfcosets
+Class: basic
+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.
+
+Function: mfcuspisregular
+Class: basic
+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
+
+Function: mfcusps
+Class: basic
+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
+
+Function: mfcuspval
+Class: basic
+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
+
+Function: mfcuspwidth
+Class: basic
+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
+
+Function: mfderiv
+Class: basic
+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
+
+Function: mfderivE2
+Class: basic
+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
+
+Function: mfdescribe
+Class: basic
+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
+
+Function: mfdim
+Class: basic
+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.
+
+Function: mfdiv
+Class: basic
+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
+
+Function: mfeigenbasis
+Class: basic
+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
+
+Function: mfeigensearch
+Class: basic
+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
+
+Function: mfeisenstein
+Class: basic
+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.
+
+Function: mfembed
+Class: basic
+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
+
+Function: mfeval
+Class: basic
+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
+
+Function: mffields
+Class: basic
+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)$.
+
+Function: mffromell
+Class: basic
+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
+
+Function: mffrometaquo
+Class: basic
+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
+
+Function: mffromlfun
+Class: basic
+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
+
+Function: mffromqf
+Class: basic
+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
+
+Function: mfgaloisprojrep
+Class: basic
+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
+
+Function: mfgaloistype
+Class: basic
+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$.
+
+Function: mfhecke
+Class: basic
+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= 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.
+
+Function: mfkohnenbijection
+Class: basic
+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.
+
+Function: mfkohneneigenbasis
+Class: basic
+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
+
+Function: mflinear
+Class: basic
+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
+
+Function: mfmanin
+Class: basic
+Section: modular_forms
+C-Name: mfmanin
+Prototype: Gb
+Help: 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.
+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
+
+Function: mfmul
+Class: basic
+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
+
+Function: mfnumcusps
+Class: basic
+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
+
+Function: mfparams
+Class: basic
+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
+
+Function: mfperiodpol
+Class: basic
+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
+
+Function: mfperiodpolbasis
+Class: basic
+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
+
+Function: mfpetersson
+Class: basic
+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
+
+Function: mfpow
+Class: basic
+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
+
+Function: mfsearch
+Class: basic
+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
+
+Function: mfshift
+Class: basic
+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
+
+Function: mfshimura
+Class: basic
+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
+
+Function: mfslashexpansion
+Class: basic
+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'$.
+
+Function: mfspace
+Class: basic
+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
+
+Function: mfsplit
+Class: basic
+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
+
+Function: mfsturm
+Class: basic
+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
+
+Function: mfsymbol
+Class: basic
+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)}:
+
+Function: mfsymboleval
+Class: basic
+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.
+
+Function: mftaylor
+Class: basic
+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
+
+Function: mftobasis
+Class: basic
+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
+
+Function: mftocoset
+Class: basic
+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
+
+Function: mftonew
+Class: basic
+Section: modular_forms
+C-Name: mftonew
+Prototype: GG
+Help: 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.
+Doc: \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
+
+Function: mftraceform
+Class: basic
+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
+
+Function: mftwist
+Class: basic
+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
+
+Function: min
+Class: basic
+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.
+
+Function: minpoly
+Class: basic
+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: modreverse
+Class: basic
+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
+
+Function: moebius
+Class: basic
+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.
+
+Function: msatkinlehner
+Class: basic
+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
+
+Function: mscosets
+Class: basic
+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)}
+
+Function: mscuspidal
+Class: basic
+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: msdim
+Class: basic
+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.
+
+Function: mseisenstein
+Class: basic
+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
+
+Function: mseval
+Class: basic
+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.
+
+Function: msfarey
+Class: basic
+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}.
+
+Function: msfromcusp
+Class: basic
+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
+
+Function: msfromell
+Class: basic
+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.
+
+Function: msfromhecke
+Class: basic
+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
+
+Function: msgetlevel
+Class: basic
+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$.
+
+Function: msgetsign
+Class: basic
+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
+
+Function: msgetweight
+Class: basic
+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
+
+Function: mshecke
+Class: basic
+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
+
+Function: msinit
+Class: basic
+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
+
+Function: msissymbol
+Class: basic
+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
+
+Function: mslattice
+Class: basic
+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
+
+Function: msnew
+Class: basic
+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
+
+Function: msomseval
+Class: basic
+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
+
+Function: mspadicL
+Class: basic
+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
+
+Function: mspadicinit
+Class: basic
+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$.
+
+Function: mspadicmoments
+Class: basic
+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
+
+Function: mspadicseries
+Class: basic
+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
+
+Function: mspathgens
+Class: basic
+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$.
+
+Function: mspathlog
+Class: basic
+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$.
+
+Function: mspetersson
+Class: basic
+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.
+
+Function: mspolygon
+Class: basic
+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
+
+Function: msqexpansion
+Class: basic
+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
+
+Function: mssplit
+Class: basic
+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.
+
+Function: msstar
+Class: basic
+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
+
+Function: mstooms
+Class: basic
+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
+
+Function: my
+Class: basic
+Section: programming/specific
+Help: my(x,...,z): declare x,...,z as lexically-scoped local variables.
+
+Function: newtonpoly
+Class: basic
+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}.
+
+Function: next
+Class: basic
+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.
+
+Function: nextprime
+Class: basic
+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}.
+
+Function: nfalgtobasis
+Class: basic
+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}.
+
+Function: nfbasis
+Class: basic
+Section: number_fields
+C-Name: nfbasis
+Prototype: GD&
+Help: 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.
+Doc:
+ Let $T(X)$ be an irreducible polynomial with integral coefficients. This
+ function returns an \idx{integral basis} of the number field defined by $T$,
+ that is a $\Z$-basis of its maximal order. If present, \kbd{dK} is set
+ to the discriminant of the returned order. The basis elements are given as
+ elements in $K = \Q[X]/(T)$, in Hermite normal form with respect to the
+ $\Q$-basis $(1,X,\dots,X^{\deg T-1})$ of $K$, lifted to $\Q[X]$.
+ In particular its first element is always $1$ and its $i$-th element is a
+ polynomial of degree $i-1$ whose leading coefficient is the inverse of an
+ integer: the product of those integers is the index of $\Z[X]/(T)$ in the
+ maximal order $\Z_{K}$:
+ \bprog
+ ? nfbasis(x^2 + 4) \\ Z[X]/(T) has index 2 in Z_K
+ %1 = [1, x/2]
+ ? nfbasis(x^2 + 4, &D)
+ %2 = [1, x/2]
+ ? D
+ %3 = -4
+ @eprog
+ This function uses a modified version of the \idx{round 4} algorithm,
+ due to David \idx{Ford}, Sebastian \idx{Pauli} and Xavier \idx{Roblot}.
+
+ \misctitle{Local basis, orders maximal at certain primes}
+
+ Obtaining the maximal order is hard: it requires factoring the discriminant
+ $D$ of $T$. Obtaining an order which is maximal at a finite explicit set of
+ primes is easy, but it may then be a strict suborder of the maximal order. To
+ specify that we are interested in a given set of places only, we can replace
+ the argument $T$ by an argument $[T,\var{listP}]$, where \var{listP} encodes
+ the primes we are interested in: it must be a factorization matrix, a vector
+ of integers or a single integer.
+
+ \item Vector: we assume that it contains distinct \emph{prime} numbers.
+
+ \item Matrix: we assume that it is a two-column matrix of a
+ (partial) factorization of $D$; namely the first column contains
+ distinct \emph{primes} and the second one the valuation of $D$ at each of
+ these primes.
+
+ \item Integer $B$: this is replaced by the vector of primes up to $B$. Note
+ that the function will use at least $O(B)$ time: a small value, about
+ $10^{5}$, should be enough for most applications. Values larger than $2^{32}$
+ are not supported.
+
+ In all these cases, the primes may or may not divide the discriminant $D$
+ of $T$. The function then returns a $\Z$-basis of an order whose index is
+ not divisible by any of these prime numbers. The result may actually be
+ a global integral basis, in particular if all the prime divisors of the
+ \emph{field} discriminant are included, but this is not guaranteed!
+ Note that \kbd{nfinit} has built-in support for such a check:
+ \bprog
+ ? K = nfinit([T, listP]);
+ ? nfcertify(K) \\ we computed an actual maximal order
+ %2 = [];
+ @eprog\noindent The first line initializes a number field structure
+ incorporating \kbd{nfbasis([T, listP]} in place of a proven integral basis.
+ The second line certifies that the resulting structure is correct. This
+ allows to create an \kbd{nf} structure attached to the number field $K =
+ \Q[X]/(T)$, when the discriminant of $T$ cannot be factored completely,
+ whereas the prime divisors of $\disc K$ are known. If present, the argument
+ \kbd{dK} is set to the discriminant of the returned order, and is
+ equal to the field discriminant if and only if the order is maximal.
+
+ Of course, if \var{listP} contains a single prime number $p$,
+ the function returns a local integral basis for $\Z_{p}[X]/(T)$:
+ \bprog
+ ? nfbasis(x^2+x-1001)
+ %1 = [1, 1/3*x - 1/3]
+ ? nfbasis( [x^2+x-1001, [2]] )
+ %2 = [1, x]
+ @eprog\noindent The following function computes the index $i_{T}$
+ of $\Z[X]/(T)$ in the order generated by the $\Z$-basis $B$:
+ \bprog
+ nfbasisindex(T, B) = vecprod([denominator(pollead(Q)) | Q <- B]);
+ @eprog\noindent In particular, $B$ is a basis of the maximal order
+ if and only if $\kbd{poldisc}(T) / i_{T}^{2}$ is equal to the field
+ discriminant. More generally, this formula gives the square of index of the
+ order given by $B$ in $\Z_{K}$. For instance, assume that $P$ is a vector
+ of prime numbers containing (at least) all prime divisors of the field
+ discriminant, then the following construct allows to provably compute the
+ field discriminant and to check whether the returned basis is actually
+ a basis of the maximal order
+ \bprog
+ ? B = nfbasis([T, P], &D);
+ ? dK = sign(D) * vecprod([p^valuation(D,p) | p<-P]);
+ ? dK * nfbasisindex(T, B)^2 == poldisc(T)
+ @eprog\noindent The variable \kbd{dK} contains the field discriminant and
+ the last command returns $1$ if and only if $B$ is a $\Z$-basis of the
+ maximal order. Of course, the \kbd{nfinit} / \kbd{nfcertify} approach is
+ simpler, but it is also more costly.
+
+ \misctitle{The Buchmann-Lenstra algorithm}
+
+ We now complicate the picture: it is in fact allowed to include
+ \emph{composite} numbers instead of primes
+ in \kbd{listP} (Vector or Matrix case), provided they are pairwise coprime.
+ The result may still be a correct integral basis if
+ the field discriminant factors completely over the actual primes in the
+ list; again, this is not guaranteed. Adding a composite $C$ such that $C^{2}$
+ \emph{divides} $D$ may help because when we consider $C$ as a prime and run
+ the algorithm, two good things can happen: either we succeed in proving that
+ no prime dividing $C$ can divide the index (without actually needing to find
+ those primes), or the computation exhibits a nontrivial zero divisor,
+ thereby factoring $C$ and we go on with the refined factorization. (Note that
+ including a $C$ such that $C^{2}$ does not divide $D$ is useless.) If neither
+ happen, then the computed basis need not generate the maximal order. Here is
+ an example:
+ \bprog
+ ? B = 10^5;
+ ? listP = factor(poldisc(T), B); \\ primes <= B dividing D + cofactor
+ ? basis = nfbasis([T, listP], &D)
+ @eprog\noindent If the computed discriminant $D$ factors completely
+ over the primes less than $B$ (together with the primes contained in the
+ \tet{addprimes} table), then everything is certified: $D$ is the field
+ discriminant and \kbd{basis} generates the maximal order.
+ This can be tested as follows:
+ \bprog
+ F = factor(D, B); P = F[,1]; E = F[,2];
+ for (i = 1, #P,
+ if (P[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
+
+Function: nfbasistoalg
+Class: basic
+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}.
+
+Function: nfcertify
+Class: basic
+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}.
+
+Function: nfcompositum
+Class: basic
+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}).
+
+Function: nfdetint
+Class: basic
+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}.
+
+Function: nfdisc
+Class: basic
+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.
+
+Function: nfdiscfactors
+Class: basic
+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
+
+Function: nfeltadd
+Class: basic
+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
+
+Function: nfeltdiv
+Class: basic
+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}$.
+
+Function: nfeltdiveuc
+Class: basic
+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))}.
+
+Function: nfeltdivmodpr
+Class: basic
+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.
+
+Function: nfeltdivrem
+Class: basic
+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.
+
+Function: nfeltembed
+Class: basic
+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
+
+Function: nfeltispower
+Class: basic
+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
+
+Function: nfeltissquare
+Class: basic
+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
+
+Function: nfeltmod
+Class: basic
+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)}.$$
+
+Function: nfeltmul
+Class: basic
+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}$.
+
+Function: nfeltmulmodpr
+Class: basic
+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.
+
+Function: nfeltnorm
+Class: basic
+Section: number_fields
+C-Name: nfnorm
+Prototype: GG
+Help: nfeltnorm(nf,x): norm of x.
+Doc: returns the absolute norm of $x$.
+
+Function: nfeltpow
+Class: basic
+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$.
+
+Function: nfeltpowmodpr
+Class: basic
+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.
+
+Function: nfeltreduce
+Class: basic
+Section: number_fields
+C-Name: nfreduce
+Prototype: GGG
+Help: nfeltreduce(nf,a,id): gives r such that a-r is in the ideal id and r
+ is small.
+Doc: given an ideal \var{id} in
+ Hermite normal form and an element $a$ of the number field $\var{nf}$,
+ finds an element $r$ in $\var{nf}$ such that $a-r$ belongs to the ideal
+ and $r$ is small.
+
+Function: nfeltreducemodpr
+Class: basic
+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.
+
+Function: nfeltsign
+Class: basic
+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
+
+Function: nfelttrace
+Class: basic
+Section: number_fields
+C-Name: nftrace
+Prototype: GG
+Help: nfelttrace(nf,x): trace of x.
+Doc: returns the absolute trace of $x$.
+
+Function: nfeltval
+Class: basic
+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}$).
+
+Function: nffactor
+Class: basic
+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.
+
+Function: nffactorback
+Class: basic
+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
+
+Function: nffactormod
+Class: basic
+Section: number_fields
+C-Name: nffactormod
+Prototype: GGG
+Obsolete: 2016-09-18
+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.
+
+Function: nfgaloisapply
+Class: basic
+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
+
+Function: nfgaloisconj
+Class: basic
+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.
+
+Function: nfgrunwaldwang
+Class: basic
+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
+
+Function: nfhilbert
+Class: basic
+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.
+
+Function: nfhnf
+Class: basic
+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.
+
+Function: nfhnfmod
+Class: basic
+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}.
+
+Function: nfinit
+Class: basic
+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.
+
+Function: nfisideal
+Class: basic
+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.
+
+Function: nfisincl
+Class: basic
+Section: number_fields
+C-Name: nfisincl0
+Prototype: GGD0,L,
+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).
+Description:
+ (gen, gen, ?0):gen nfisincl($1, $2)
+ (gen, gen, small):gen nfisincl0($1, $2, $3)
+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: nfisisom
+Class: basic
+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
+
+Function: nfislocalpower
+Class: basic
+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
+
+Function: nfkermodpr
+Class: basic
+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.
+
+Function: nflist
+Class: basic
+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: nfmodpr
+Class: basic
+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$.
+
+Function: nfmodprinit
+Class: basic
+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$.
+
+Function: nfmodprlift
+Class: basic
+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
+
+Function: nfnewprec
+Class: basic
+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}.
+
+Function: nfpolsturm
+Class: basic
+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
+
+Function: nfresolvent
+Class: basic
+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
+
+Function: nfroots
+Class: basic
+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}$.
+
+Function: nfrootsof1
+Class: basic
+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.
+
+Function: nfsnf
+Class: basic
+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$).
+
+Function: nfsolvemodpr
+Class: basic
+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.
+
+Function: nfsplitting
+Class: basic
+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$.
+
+Function: nfsubfields
+Class: basic
+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$.
+
+Function: nfsubfieldscm
+Class: basic
+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
+
+Function: nfsubfieldsmax
+Class: basic
+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.
+
+Function: nfweilheight
+Class: basic
+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
+
+Function: norm
+Class: basic
+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.
+
+Function: norml2
+Class: basic
+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
+
+Function: normlp
+Class: basic
+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
+
+Function: numbpart
+Class: basic
+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}.
+
+Function: numdiv
+Class: basic
+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.
+
+Function: numerator
+Class: basic
+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}).
+
+Function: numtoperm
+Class: basic
+Section: combinatorics
+C-Name: numtoperm
+Prototype: LG
+Help: numtoperm(n,k): permutation number k (mod n!) of n letters (n
+ C-integer).
+Description:
+ (small,int):vecsmall Z_to_perm($1, $2)
+ (small,gen):vecsmall numtoperm($1, $2)
+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$.
+
+Function: omega
+Class: basic
+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
+
+Function: oo
+Class: basic
+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.
+
+Function: padicappr
+Class: basic
+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}.
+
+Function: padicfields
+Class: basic
+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}$.
+
+Function: padicprec
+Class: basic
+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.
+
+Function: parapply
+Class: basic
+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: pareval
+Class: basic
+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: parfor
+Class: basic
+Section: programming/parallel
+C-Name: parfor0
+Prototype: vV=GDGJDVDI
+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.
+Iterator:
+ (gen,gen,?gen,closure,?notype) (parfor, _parfor_init, _parfor_next, _parfor_stop)
+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 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$.
+
+Function: polgraeffe
+Class: basic
+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)$.
+
+Function: polhensellift
+Class: basic
+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
+
+Function: polhermite
+Class: basic
+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}.
+
+Function: polinterpolate
+Class: basic
+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.
+
+Function: polisclass
+Class: basic
+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
+
+Function: poliscyclo
+Class: basic
+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
+
+Function: poliscycloprod
+Class: basic
+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
+
+Function: polisirreducible
+Class: basic
+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.
+
+Function: pollaguerre
+Class: basic
+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}.
+
+Function: pollead
+Class: basic
+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.
+
+Function: pollegendre
+Class: basic
+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}.
+
+Function: polmodular
+Class: basic
+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: polrecip
+Class: basic
+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
+
+Function: polred
+Class: basic
+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.
+
+Function: polredabs
+Class: basic
+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.
+
+Function: polredbest
+Class: basic
+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).
+
+Function: polredord
+Class: basic
+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.
+
+Function: polresultant
+Class: basic
+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: polresultantext
+Class: basic
+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}.
+
+Function: polroots
+Class: basic
+Section: polynomials
+C-Name: roots
+Prototype: Gp
+Help: polroots(T): complex roots of the polynomial T using
+ Schonhage's method, as modified by Gourdon.
+Description:
+ (gen):vec:prec roots($1, $prec)
+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.
+
+Function: polrootsbound
+Class: basic
+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
+
+Function: polrootsff
+Class: basic
+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.
+
+Function: polrootsmod
+Class: basic
+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
+
+Function: polrootspadic
+Class: basic
+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.
+
+Function: polrootsreal
+Class: basic
+Section: polynomials
+C-Name: realroots
+Prototype: GDGp
+Help: polrootsreal(T,{ab}): real roots of the polynomial T with real
+ coefficients, using Uspensky's method. In interval ab = [a,b] if present.
+Description:
+ (gen,?gen):vec:prec realroots($1, $2, $prec)
+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.
+
+Function: polsturm
+Class: basic
+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.
+
+Function: polsubcyclo
+Class: basic
+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$.
+
+Function: polsubcyclofast
+Class: basic
+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
+
+Function: polsylvestermatrix
+Class: basic
+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.
+
+Function: polsym
+Class: basic
+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.
+
+Function: poltchebi
+Class: basic
+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}
+
+Function: polteichmuller
+Class: basic
+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$.
+
+Function: poltomonic
+Class: basic
+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.
+
+Function: poltschirnhaus
+Class: basic
+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.
+
+Function: polylog
+Class: basic
+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$).
+
+Function: polylogmult
+Class: basic
+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}).
+
+Function: polzagier
+Class: basic
+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},
+ %}
+
+Function: powers
+Class: basic
+Section: linear_algebra
+C-Name: gpowers0
+Prototype: GLDG
+Help: powers(x,n,{x0}): return the vector [1,x,...,x^n] if x0 is omitted,
+ and [x0, x0*x, ..., x0*x^n] otherwise.
+Description:
+ (gen, small):vec gpowers($1, $2)
+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}.
+
+Function: precision
+Class: basic
+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).
+
+Function: precprime
+Class: basic
+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}.
+
+Function: prime
+Class: basic
+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.
+
+Function: primecert
+Class: basic
+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$).
+
+Function: primecertexport
+Class: basic
+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
+
+Function: primecertisvalid
+Class: basic
+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: primepi
+Class: basic
+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}$.
+
+Function: primes
+Class: basic
+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
+
+Function: print
+Class: basic
+Section: programming/specific
+C-Name: print
+Prototype: vs*
+Help: print({str}*): outputs its string arguments (in raw format) ending with
+ a newline.
+Description:
+ (?gen,...):void pari_printf("${2 format_string}\n"${2 format_args})
+Doc: outputs its arguments in raw 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
+
+Function: print1
+Class: basic
+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}.
+
+Function: printf
+Class: basic
+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.
+
+Function: printp
+Class: basic
+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
+
+Function: printsep
+Class: basic
+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
+
+Function: printsep1
+Class: basic
+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
+
+Function: printtex
+Class: basic
+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
+
+Function: prod
+Class: basic
+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}.
+
+Function: prodeuler
+Class: basic
+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}.
+
+Function: prodeulerrat
+Class: basic
+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
+
+Function: prodinf
+Class: basic
+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$).
+
+Function: prodnumrat
+Class: basic
+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
+
+Function: psdraw
+Class: basic
+Section: graphic
+C-Name: psdraw
+Prototype: vGD0,L,
+Obsolete: 2018-02-01
+Help: psdraw(list,{flag=0}): obsolete function.
+Doc: This function is obsolete, use plotexport and write the result to file.
+
+Function: psi
+Class: basic
+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.
+
+Function: psploth
+Class: basic
+Section: graphic
+C-Name: psploth0
+Prototype: 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
+Obsolete: 2018-02-01
+Help: psploth(X=a,b,expr,{flags=0},{n=0}): obsolete function.
+Wrapper: (,,G)
+Description:
+ (gen,gen,gen,?small,?small):gen:prec psploth(${3 cookie}, ${3 wrapper}, $1, $2, $4, $5, $prec)
+Doc: This function is obsolete, use plothexport and write the result to file.
+
+Function: psplothraw
+Class: basic
+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.
+
+Function: qfauto
+Class: basic
+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.
+
+Function: qfautoexport
+Class: basic
+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
+
+Function: qfbclassno
+Class: basic
+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}.
+
+Function: qfbcomp
+Class: basic
+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
+
+Function: qfbcompraw
+Class: basic
+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
+
+Function: qfbcornacchia
+Class: basic
+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.
+
+Function: qfbhclassno
+Class: basic
+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
+
+Function: qfbil
+Class: basic
+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}.
+
+Function: qfbnucomp
+Class: basic
+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$.
+
+Function: qfbnupow
+Class: basic
+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}$.
+
+Function: qfbpow
+Class: basic
+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}).
+
+Function: qfbpowraw
+Class: basic
+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}$.
+
+Function: qfbprimeform
+Class: basic
+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.)
+
+Function: qfbred
+Class: basic
+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})
+
+Function: qfbredsl2
+Class: basic
+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
+
+Function: qfbsolve
+Class: basic
+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.
+
+Function: qfcholesky
+Class: basic
+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.
+
+Function: qfcvp
+Class: basic
+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
+
+Function: qfeval
+Class: basic
+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
+
+Function: qfgaussred
+Class: basic
+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).
+
+Function: qfisom
+Class: basic
+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}.
+
+Function: qfisominit
+Class: basic
+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}.
+
+Function: qfjacobi
+Class: basic
+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
+
+Function: qflll
+Class: basic
+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$).
+
+Function: qflllgram
+Class: basic
+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$).
+
+Function: qfminim
+Class: basic
+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)
+
+Function: qfminimize
+Class: basic
+Section: linear_algebra
+C-Name: qfminimize
+Prototype: G
+Help: 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.
+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
+
+Function: qfnorm
+Class: basic
+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}.
+
+Function: qforbits
+Class: basic
+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
+
+Function: qfparam
+Class: basic
+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
+
+Function: qfperfection
+Class: basic
+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$.
+
+Function: qfrep
+Class: basic
+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}$).
+
+Function: qfsign
+Class: basic
+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.
+
+Function: qfsolve
+Class: basic
+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
+
+Function: quadclassunit
+Class: basic
+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}.
+
+Function: quaddisc
+Class: basic
+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
+
+Function: quadgen
+Class: basic
+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.
+
+Function: quadhilbert
+Class: basic
+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.
+
+Function: quadpoly
+Class: basic
+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
+
+Function: quadray
+Class: basic
+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.
+
+Function: quadregulator
+Class: basic
+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.
+
+Function: quadunit
+Class: basic
+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.
+
+Function: quadunitindex
+Class: basic
+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
+
+Function: quadunitnorm
+Class: basic
+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.
+
+Function: 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)}).
+
+Function: ramanujantau
+Class: basic
+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: random
+Class: basic
+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}.
+
+Function: randomprime
+Class: basic
+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}.
+
+Function: read
+Class: basic
+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.
+
+Function: readstr
+Class: basic
+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}.
+
+Function: readvec
+Class: basic
+Section: programming/specific
+C-Name: gp_readvec_file
+Prototype: D"",s,
+Help: readvec({filename}): create a vector whose components are the evaluation
+ of all the expressions found in the input file filename.
+Description:
+ (str):gen gp_readvec_file($1)
+Doc: reads in the file
+ \var{filename} (subject to string expansion). If \var{filename} is
+ omitted, re-reads the last file that was fed into \kbd{gp}. The return
+ value is a vector whose components are the evaluation of all sequences
+ of instructions contained in the file. For instance, if \var{file} contains
+ \bprog
+ 1
+ 2
+ 3
+ @eprog\noindent
+ then we will get:
+ \bprog
+ ? \r a
+ %1 = 1
+ %2 = 2
+ %3 = 3
+ ? read(a)
+ %4 = 3
+ ? readvec(a)
+ %5 = [1, 2, 3]
+ @eprog
+ In general a sequence is just a single line, but as usual braces and
+ \kbd{\bs} may be used to enter multiline sequences.
+Variant: The underlying library function
+ \fun{GEN}{gp_readvec_stream}{FILE *f} is usually more flexible.
+
+Function: real
+Class: basic
+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
+
+Function: removeprimes
+Class: basic
+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.
+
+Function: return
+Class: basic
+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}).
+
+Function: rnfalgtobasis
+Class: basic
+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.
+
+Function: rnfbasis
+Class: basic
+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.
+
+Function: rnfbasistoalg
+Class: basic
+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.
+
+Function: rnfcharpoly
+Class: basic
+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
+
+Function: rnfconductor
+Class: basic
+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$.
+
+Function: rnfdedekind
+Class: basic
+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).
+
+Function: rnfdet
+Class: basic
+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.
+
+Function: rnfdisc
+Class: basic
+Section: number_fields
+C-Name: rnfdiscf
+Prototype: GG
+Help: 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.
+Doc: given an \var{nf} structure attached to a number field $K$, as output
+ by \kbd{nfinit}, and a monic irreducible polynomial $T\in K[x]$ defining a
+ relative extension $L = K[x]/(T)$, compute the relative discriminant of $L$.
+ This is a vector $[D,d]$, where $D$ is the relative ideal discriminant and
+ $d$ is the relative discriminant considered as an element of
+ $K^{*}/{K^{*}}^{2}$.
+ The main variable of $\var{nf}$ \emph{must} be of lower priority than that of
+ $T$, see \secref{se:priority}.
+
+ \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.
+
+Function: rnfeltabstorel
+Class: basic
+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
+
+Function: rnfeltdown
+Class: basic
+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$).
+
+Function: rnfeltnorm
+Class: basic
+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
+
+Function: rnfeltreltoabs
+Class: basic
+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
+
+Function: rnfelttrace
+Class: basic
+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
+
+Function: rnfeltup
+Class: basic
+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$).
+
+Function: rnfequation
+Class: basic
+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$).
+
+Function: rnfhnfbasis
+Class: basic
+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}.
+
+Function: rnfidealabstorel
+Class: basic
+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
+
+Function: rnfidealdown
+Class: basic
+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$.
+
+Function: rnfidealfactor
+Class: basic
+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.
+
+Function: rnfidealhnf
+Class: basic
+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.
+
+Function: rnfidealmul
+Class: basic
+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.
+
+Function: rnfidealnormabs
+Class: basic
+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.
+
+Function: rnfidealnormrel
+Class: basic
+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.
+
+Function: rnfidealprimedec
+Class: basic
+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
+
+Function: rnfidealreltoabs
+Class: basic
+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$).
+
+Function: rnfidealtwoelt
+Class: basic
+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.
+
+Function: rnfidealup
+Class: basic
+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$).
+
+Function: rnfinit
+Class: basic
+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$).
+
+Function: rnfisabelian
+Class: basic
+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
+
+Function: rnfisfree
+Class: basic
+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}.
+
+Function: rnfislocalcyclo
+Class: basic
+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
+
+Function: rnfisnorm
+Class: basic
+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).
+
+Function: rnfisnorminit
+Class: basic
+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.
+
+Function: rnfkummer
+Class: basic
+Section: number_fields
+C-Name: rnfkummer
+Prototype: GDGp
+Obsolete: 2020-05-22
+Help: rnfkummer(bnr,{subgp}): this function is deprecated. Use bnrclassfield.
+Doc: This function is deprecated, use \kbd{bnrclassfield}.
+
+Function: rnflllgram
+Class: basic
+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.
+
+Function: rnfnormgroup
+Class: basic
+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.
+
+Function: rnfpolred
+Class: basic
+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.
+
+Function: rnfpolredabs
+Class: basic
+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.
+
+Function: rnfpolredbest
+Class: basic
+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
+
+Function: rnfpseudobasis
+Class: basic
+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$.
+
+Function: rnfsteinitz
+Class: basic
+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})$).
+
+Function: rootsof1
+Class: basic
+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
+
+Function: round
+Class: basic
+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}.
+
+Function: select
+Class: basic
+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$.
+
+Function: self
+Class: basic
+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
+
+Function: seralgdep
+Class: basic
+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$.
+
+Function: serchop
+Class: basic
+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
+
+Function: serconvol
+Class: basic
+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}$.
+
+Function: serdiffdep
+Class: basic
+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$.
+
+Function: serlaplace
+Class: basic
+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}$.
+
+Function: serprec
+Class: basic
+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.
+
+Function: serreverse
+Class: basic
+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
+
+Function: setbinop
+Class: basic
+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
+
+Function: setdebug
+Class: basic
+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}.
+
+Function: setdelta
+Class: basic
+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
+
+Function: setintersect
+Class: basic
+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.
+
+Function: setisset
+Class: basic
+Section: linear_algebra
+C-Name: setisset
+Prototype: lG
+Help: setisset(x): true(1) if x is a set (row vector with strictly
+ increasing entries), false(0) if not.
+Doc:
+ returns true (1) if $x$ is a set, false (0) if
+ not. In PARI, a set is a row vector whose entries are strictly
+ increasing with respect to a (somewhat arbitrary) universal comparison
+ function. To convert any object into a set (this is most useful for
+ vectors, of course), use the function \kbd{Set}.
+ \bprog
+ ? a = [3, 1, 1, 2];
+ ? setisset(a)
+ %2 = 0
+ ? Set(a)
+ %3 = [1, 2, 3]
+ @eprog
+
+Function: setminus
+Class: basic
+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.
+
+Function: setrand
+Class: basic
+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
+
+Function: setsearch
+Class: basic
+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
+
+Function: setunion
+Class: basic
+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.
+
+Function: shift
+Class: basic
+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}$.
+
+Function: shiftmul
+Class: basic
+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.
+
+Function: sigma
+Class: basic
+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$.
+
+Function: sign
+Class: basic
+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.
+
+Function: simplify
+Class: basic
+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
+
+Function: sin
+Class: basic
+Section: transcendental
+C-Name: gsin
+Prototype: Gp
+Help: sin(x): sine of x.
+Description:
+ (real):real mpsin($1)
+ (mp):real:prec gsin($1, $prec)
+ (gen):gen:prec gsin($1, $prec)
+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$.
+
+Function: sinc
+Class: basic
+Section: transcendental
+C-Name: gsinc
+Prototype: Gp
+Help: sinc(x): sinc function of x.
+Description:
+ (mp):real:prec gsinc($1, $prec)
+ (gen):gen:prec gsinc($1, $prec)
+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$.
+
+Function: sinh
+Class: basic
+Section: transcendental
+C-Name: gsinh
+Prototype: Gp
+Help: sinh(x): hyperbolic sine of x.
+Description:
+ (mp):real:prec gsinh($1, $prec)
+ (gen):gen:prec gsinh($1, $prec)
+Doc: hyperbolic sine of $x$.
+
+Function: sizebyte
+Class: basic
+Section: conversions
+C-Name: gsizebyte
+Prototype: lG
+Help: sizebyte(x): number of bytes occupied by the complete tree of the
+ object x.
+Doc: outputs the total number of bytes occupied by the tree representing the
+ PARI object $x$.
+Variant: Also available is \fun{long}{gsizeword}{GEN x} returning a
+ number of \emph{words}.
+
+Function: sizedigit
+Class: basic
+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)}.
+
+Function: snfrank
+Class: basic
+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).
+
+Function: solve
+Class: basic
+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}.
+
+Function: solvestep
+Class: basic
+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}.
+
+Function: sqr
+Class: basic
+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: sqrt
+Class: basic
+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.
+
+Function: sqrtint
+Class: basic
+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}.
+
+Function: sqrtn
+Class: basic
+Section: transcendental
+C-Name: gsqrtn
+Prototype: GGD&p
+Help: sqrtn(x,n,{&z}): nth-root of x, n must be integer. If present, z is
+ set to a suitable root of unity to recover all solutions. If it was not
+ possible, z is set to zero.
+Doc: principal branch of the $n$th root of $x$,
+ i.e.~such that $\text{Arg}(\text{sqrtn}(x))\in{} ]-\pi/n, \pi/n]$. Intmod
+ a prime and $p$-adics are allowed as arguments.
+
+ If $z$ is present, it is set to a suitable root of unity allowing to
+ recover all the other roots. If it was not possible, z is
+ set to zero. In the case this argument is present and no $n$th root exist,
+ $0$ is returned instead of raising an error.
+ \bprog
+ ? sqrtn(Mod(2,7), 2)
+ %1 = Mod(3, 7)
+ ? sqrtn(Mod(2,7), 2, &z); z
+ %2 = Mod(6, 7)
+ ? sqrtn(Mod(2,7), 3)
+ *** at top-level: sqrtn(Mod(2,7),3)
+ *** ^-----------------
+ *** sqrtn: nth-root does not exist in gsqrtn.
+ ? sqrtn(Mod(2,7), 3, &z)
+ %2 = 0
+ ? z
+ %3 = 0
+ @eprog
+
+ The following script computes all roots in all possible cases:
+ \bprog
+ sqrtnall(x,n)=
+ { my(V,r,z,r2);
+ r = sqrtn(x,n, &z);
+ if (!z, error("Impossible case in sqrtn"));
+ if (type(x) == "t_INTMOD" || type(x)=="t_PADIC",
+ r2 = r*z; n = 1;
+ while (r2!=r, r2*=z;n++));
+ V = vector(n); V[1] = r;
+ for(i=2, n, V[i] = V[i-1]*z);
+ V
+ }
+ addhelp(sqrtnall,"sqrtnall(x,n):compute the vector of nth-roots of x");
+ @eprog\noindent
+Variant: If $x$ is a \typ{PADIC}, the function
+ \fun{GEN}{Qp_sqrtn}{GEN x, GEN n, GEN *z} is also available.
+
+Function: sqrtnint
+Class: basic
+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}
+
+Function: stirling
+Class: basic
+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$).
+
+Function: strchr
+Class: basic
+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: strexpand
+Class: basic
+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: strjoin
+Class: basic
+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
+
+Function: strprintf
+Class: basic
+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: strsplit
+Class: basic
+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
+
+Function: strtex
+Class: basic
+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: strtime
+Class: basic
+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
+
+Function: subcyclohminus
+Class: basic
+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
+
+Function: subcycloiwasawa
+Class: basic
+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).
+
+Function: subcyclopclgp
+Class: basic
+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.)
+
+Function: subgrouplist
+Class: basic
+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.
+
+Function: subst
+Class: basic
+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.
+
+Function: substpol
+Class: basic
+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).
+
+Function: substvec
+Class: basic
+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
+
+Function: sum
+Class: basic
+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}
+
+Function: sumalt
+Class: basic
+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$).
+
+Function: sumdedekind
+Class: basic
+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
+
+Function: sumdigits
+Class: basic
+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$.
+
+Function: sumdiv
+Class: basic
+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}
+
+Function: sumdivmult
+Class: basic
+Section: sums
+C-Name: sumdivmultexpr0
+Prototype: GVE
+Help: sumdivmult(n,d,expr): sum of multiplicative function expr,
+ d running over the divisors of n.
+Wrapper: (,,G)
+Description:
+ (gen,,gen):gen sumdivmultexpr(${3 cookie}, ${3 wrapper}, $1)
+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}
+
+Function: sumeulerrat
+Class: basic
+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
+
+Function: sumformal
+Class: basic
+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
+
+Function: suminf
+Class: basic
+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}.
+
+Function: sumnum
+Class: basic
+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}.
+
+Function: sumnumap
+Class: basic
+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}.
+
+Function: sumnumapinit
+Class: basic
+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
+
+Function: sumnuminit
+Class: basic
+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
+
+Function: sumnumlagrange
+Class: basic
+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}.
+
+Function: sumnumlagrangeinit
+Class: basic
+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$.
+
+Function: sumnummonien
+Class: basic
+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}.
+
+Function: sumnummonieninit
+Class: basic
+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
+
+Function: sumnumrat
+Class: basic
+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
+
+Function: sumnumsidi
+Class: basic
+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.
+
+Function: sumpos
+Class: basic
+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$).
+
+Function: system
+Class: basic
+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
+
+Function: tan
+Class: basic
+Section: transcendental
+C-Name: gtan
+Prototype: Gp
+Help: tan(x): tangent of x.
+Description:
+ (mp):real:prec gtan($1, $prec)
+ (gen):gen:prec gtan($1, $prec)
+Doc: tangent of $x$.
+
+Function: tanh
+Class: basic
+Section: transcendental
+C-Name: gtanh
+Prototype: Gp
+Help: tanh(x): hyperbolic tangent of x.
+Description:
+ (mp):real:prec gtanh($1, $prec)
+ (gen):gen:prec gtanh($1, $prec)
+Doc: hyperbolic tangent of $x$.
+
+Function: taylor
+Class: basic
+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
+
+Function: teichmuller
+Class: basic
+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}.
+
+Function: theta
+Class: basic
+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).$$
+
+Function: thetanullk
+Class: basic
+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})$.
+
+Function: thue
+Class: basic
+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.
+
+Function: thueinit
+Class: basic
+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.
+
+Function: trace
+Class: basic
+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.
+
+Function: trap
+Class: basic
+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)
+
+Function: truncate
+Class: basic
+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}.
+
+Function: type
+Class: basic
+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.
+
+Function: unclone
+Class: gp2c
+Description:
+ (small):void (void)0 /*unclone*/
+ (gen):void gunclone($1)
+
+Function: unexport
+Class: basic
+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}.
+
+Function: unexportall
+Class: basic
+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.
+
+Function: uninline
+Class: basic
+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}.
+
+Function: until
+Class: basic
+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}).
+
+Function: valuation
+Class: basic
+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.
+
+Function: varhigher
+Class: basic
+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
+
+Function: variable
+Class: basic
+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.
+
+Function: variables
+Class: basic
+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.
+
+Function: varlower
+Class: basic
+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
+
+Function: vecextract
+Class: basic
+Section: linear_algebra
+C-Name: extract0
+Prototype: GGDG
+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.).
+Description:
+ (vec,gen,?gen):vec extract0($1, $2, $3)
+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$}.
+
+Function: vecmax
+Class: basic
+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.
+
+Function: vecmin
+Class: basic
+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.
+
+Function: vecprod
+Class: basic
+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
+
+Function: vecsearch
+Class: basic
+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
+
+Function: vecsort
+Class: basic
+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
+
+Function: vecsum
+Class: basic
+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
+
+Function: vector
+Class: basic
+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}
+
+Function: vectorsmall
+Class: basic
+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}
+
+Function: vectorv
+Class: basic
+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}
+
+Function: version
+Class: basic
+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})!
+
+Function: warning
+Class: basic
+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
+
+Function: weber
+Class: basic
+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}.
+
+Function: 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}.)
+
+Function: while
+Class: basic
+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.
+
+Function: write
+Class: basic
+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.
+
+Function: write1
+Class: basic
+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}).
+
+Function: writebin
+Class: basic
+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).
+
+Function: writetex
+Class: basic
+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.
+
+Function: zeta
+Class: basic
+Section: transcendental
+C-Name: gzeta
+Prototype: Gp
+Help: zeta(s): Riemann zeta function at s with s a complex or a p-adic number.
+Doc: For $s \neq 1$ a complex number, Riemann's zeta
+ function \sidx{Riemann zeta-function} $\zeta(s)=\sum_{n\ge1}n^{-s}$,
+ computed using the \idx{Euler-Maclaurin} summation formula, except
+ when $s$ is of type integer, in which case it is computed using
+ Bernoulli numbers\sidx{Bernoulli numbers} for $s\le0$ or $s>0$ and
+ even, and using modular forms for $s>0$ and odd. 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
+
+Function: zetahurwitz
+Class: basic
+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
+
+Function: zetamult
+Class: basic
+Section: transcendental
+C-Name: zetamult_interpolate
+Prototype: GDGp
+Help: 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).
+Doc: For $s$ a vector of positive integers such that $s[1] \geq 2$,
+ returns the multiple zeta value (MZV)
+ $$\zeta(s_{1},\dots, s_{k}) = \sum_{n_{1}>\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$.
+
+Function: zetamultall
+Class: basic
+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
+
+Function: zetamultconvert
+Class: basic
+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
+
+Function: zetamultdual
+Class: basic
+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
+
+Function: znchar
+Class: basic
+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
+
+Function: zncharconductor
+Class: basic
+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
+
+Function: znchardecompose
+Class: basic
+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
+
+Function: znchargauss
+Class: basic
+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
+
+Function: zncharinduce
+Class: basic
+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
+
+Function: zncharisodd
+Class: basic
+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
+
+Function: znchartokronecker
+Class: basic
+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
+
+Function: znchartoprimitive
+Class: basic
+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}$.
+
+Function: znconreychar
+Class: basic
+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
+
+Function: znconreyconductor
+Class: basic
+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.
+
+Function: znconreyexp
+Class: basic
+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
+
+Function: znconreylog
+Class: basic
+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
+
+Function: zncoppersmith
+Class: basic
+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.
+
+Function: znlog
+Class: basic
+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
+
+Function: znorder
+Class: basic
+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.
+
+Function: znprimroot
+Class: basic
+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.
+
+Function: znstar
+Class: basic
+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.
+
+Function: znsubgroupgenerators
+Class: basic
+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$.
+
diff --git a/tests/rundoctest.py b/tests/rundoctest.py
index cde35b69..a584c634 100755
--- a/tests/rundoctest.py
+++ b/tests/rundoctest.py
@@ -2,15 +2,16 @@
import os
import sys
+import traceback
# Autogen tests must be run in the root dir, and with the proper module path
path = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))
os.chdir(path)
sys.path.append(path)
-import autogen
-import cypari2
import doctest
+import cypari2
+
# The doctests assume utf-8 encoding
cypari2.string_utils.encoding = "utf-8"
@@ -24,20 +25,29 @@
pari = cypari2.Pari()
pari.default("debugmem", 0)
+modules = [cypari2.closure, cypari2.convert, cypari2.gen,
+ cypari2.handle_error, cypari2.pari_instance, cypari2.stack,
+ cypari2.string_utils]
+try:
+ import autogen
+ modules.extend([
+ autogen.doc, autogen.generator, autogen.parser])
+except ImportError:
+ print("Skipping autogen tests")
failed = 0
attempted = 0
-for mod in [cypari2.closure, cypari2.convert, cypari2.gen,
- cypari2.handle_error, cypari2.pari_instance, cypari2.stack,
- cypari2.string_utils,
- autogen.doc, autogen.generator, autogen.parser,
- autogen.paths]:
-
+for mod in modules:
print("="*80)
print("Testing {}".format(mod.__name__))
- test = doctest.testmod(mod, optionflags=doctest.ELLIPSIS|doctest.REPORT_NDIFF, verbose=False)
- failed += test.failed
- attempted += test.attempted
+ try:
+ test = doctest.testmod(mod, optionflags=doctest.ELLIPSIS|doctest.REPORT_NDIFF, verbose=False)
+ failed += test.failed
+ attempted += test.attempted
+ except Exception:
+ traceback.print_exc()
+ failed += 1
+ attempted += 1
print("="*80)
print("Summary result for cypari2:")
diff --git a/tests/test.c b/tests/test.c
new file mode 100644
index 00000000..8a583626
--- /dev/null
+++ b/tests/test.c
@@ -0,0 +1,33 @@
+// Simple test program using the PARI library
+// to compute zeta(2) and factor a polynomial over a finite field, as in the README.
+// compile with: gcc -v test.c -o test -I/usr/local/include -L/usr/local/bin -lpari -lgmp
+
+#include
+
+int main() {
+ pari_init(100000000,2);
+
+ // Compute zeta(2)
+ GEN z2 = szeta(2, DEFAULTPREC);
+ pari_printf("zeta(2) = %Ps\n", z2);
+
+ // p = x^3 + x^2 + x - 1
+ GEN gen_3 = stoi(3);
+ GEN x = pol_x(0);
+ GEN p = gadd(gadd(gadd(gpow(x, gen_3, DEFAULTPREC), gpow(x, gen_2, DEFAULTPREC)), x), gen_m1);
+ pari_printf("p = %Ps\n", p);
+
+ // modulus = y^3 + y^2 + y - 1
+ GEN y = pol_x(1);
+ GEN modulus = gadd(gadd(gadd(gpow(y, gen_3, DEFAULTPREC), gpow(y, gen_2, DEFAULTPREC)), y), gen_m1);
+ setvarn(modulus, 1);
+ pari_printf("modulus = %Ps\n", modulus);
+
+ // Factor p over F_3[y]/(modulus)
+ GEN fq = factorff(p, gen_3, modulus);
+ GEN centered = centerlift(lift(fq));
+ pari_printf("centerlift(lift(fq)) = %Ps\n", centered);
+
+ pari_close();
+ return 0;
+}
diff --git a/tests/test.pyx b/tests/test.pyx
new file mode 100644
index 00000000..ac37b838
--- /dev/null
+++ b/tests/test.pyx
@@ -0,0 +1,36 @@
+# Simple test program using the PARI library in Cython
+# to compute zeta(2) and factor a polynomial over a finite field, as in the README.
+
+from cypari2.paridecl cimport pari_printf, pari_init, pari_close, DEFAULTPREC, szeta, stoi, pol_x, gpow, gadd, factorff, lift, centerlift, setvarn, gen_2, gen_m1, gen_0, INIT_DFTm, pari_init_opts, pari_mainstack
+from cypari2.types cimport GEN
+from cypari2.closure cimport _pari_init_closure
+from cypari2.stack cimport (new_gen, new_gen_noclear, clear_stack,
+ set_pari_stack_size, before_resize, after_resize)
+from libc.stdio cimport printf
+
+def main():
+
+ pari_init(100000000, 2)
+
+ # Compute zeta(2)
+ cdef GEN z2 = szeta(2, DEFAULTPREC)
+ pari_printf(b"zeta(2) = %Ps\n", z2)
+
+ # p = x^3 + x^2 + x - 1
+ cdef GEN gen_3 = stoi(3)
+ cdef GEN x = pol_x(0)
+ cdef GEN p = gadd(gadd(gadd(gpow(x, gen_3, DEFAULTPREC), gpow(x, gen_2, DEFAULTPREC)), x), gen_m1)
+ pari_printf(b"p = %Ps\n", p)
+
+ # modulus = y^3 + y^2 + y - 1
+ cdef GEN y = pol_x(1)
+ cdef GEN modulus = gadd(gadd(gadd(gpow(y, gen_3, DEFAULTPREC), gpow(y, gen_2, DEFAULTPREC)), y), gen_m1)
+ setvarn(modulus, 1)
+ pari_printf(b"modulus = %Ps\n", modulus)
+
+ # Factor p over F_3[y]/(modulus)
+ cdef GEN fq = factorff(p, gen_3, modulus)
+ cdef GEN centered = centerlift(lift(fq))
+ pari_printf(b"centerlift(lift(fq)) = %Ps\n", centered)
+
+ pari_close()
diff --git a/uv.lock b/uv.lock
new file mode 100644
index 00000000..856d6814
--- /dev/null
+++ b/uv.lock
@@ -0,0 +1,684 @@
+version = 1
+revision = 3
+requires-python = ">=3.12"
+
+[[package]]
+name = "alabaster"
+version = "1.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" },
+]
+
+[[package]]
+name = "babel"
+version = "2.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" },
+]
+
+[[package]]
+name = "bashlex"
+version = "0.18"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/60/aae0bb54f9af5e0128ba90eb83d8d0d506ee8f0475c4fdda3deeda20b1d2/bashlex-0.18.tar.gz", hash = "sha256:5bb03a01c6d5676338c36fd1028009c8ad07e7d61d8a1ce3f513b7fff52796ee", size = 68742, upload-time = "2023-01-18T15:21:26.402Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/be/6985abb1011fda8a523cfe21ed9629e397d6e06fb5bae99750402b25c95b/bashlex-0.18-py2.py3-none-any.whl", hash = "sha256:91d73a23a3e51711919c1c899083890cdecffc91d8c088942725ac13e9dcfffa", size = 69539, upload-time = "2023-01-18T15:21:24.167Z" },
+]
+
+[[package]]
+name = "bracex"
+version = "2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/63/9a/fec38644694abfaaeca2798b58e276a8e61de49e2e37494ace423395febc/bracex-2.6.tar.gz", hash = "sha256:98f1347cd77e22ee8d967a30ad4e310b233f7754dbf31ff3fceb76145ba47dc7", size = 26642, upload-time = "2025-06-22T19:12:31.254Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl", hash = "sha256:0b0049264e7340b3ec782b5cb99beb325f36c3782a32e36e876452fd49a09952", size = 11508, upload-time = "2025-06-22T19:12:29.781Z" },
+]
+
+[[package]]
+name = "build"
+version = "1.3.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "os_name == 'nt'" },
+ { name = "packaging" },
+ { name = "pyproject-hooks" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/25/1c/23e33405a7c9eac261dff640926b8b5adaed6a6eb3e1767d441ed611d0c0/build-1.3.0.tar.gz", hash = "sha256:698edd0ea270bde950f53aed21f3a0135672206f3911e0176261a31e0e07b397", size = 48544, upload-time = "2025-08-01T21:27:09.268Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl", hash = "sha256:7145f0b5061ba90a1500d60bd1b13ca0a8a4cebdd0cc16ed8adf1c0e739f43b4", size = 23382, upload-time = "2025-08-01T21:27:07.844Z" },
+]
+
+[[package]]
+name = "certifi"
+version = "2025.8.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" },
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.4.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", size = 205655, upload-time = "2025-08-09T07:56:08.475Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/a8/c6ec5d389672521f644505a257f50544c074cf5fc292d5390331cd6fc9c3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", size = 146223, upload-time = "2025-08-09T07:56:09.708Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/eb/a2ffb08547f4e1e5415fb69eb7db25932c52a52bed371429648db4d84fb1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", size = 159366, upload-time = "2025-08-09T07:56:11.326Z" },
+ { url = "https://files.pythonhosted.org/packages/82/10/0fd19f20c624b278dddaf83b8464dcddc2456cb4b02bb902a6da126b87a1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", size = 157104, upload-time = "2025-08-09T07:56:13.014Z" },
+ { url = "https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", size = 151830, upload-time = "2025-08-09T07:56:14.428Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/02/e29e22b4e02839a0e4a06557b1999d0a47db3567e82989b5bb21f3fbbd9f/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", size = 148854, upload-time = "2025-08-09T07:56:16.051Z" },
+ { url = "https://files.pythonhosted.org/packages/05/6b/e2539a0a4be302b481e8cafb5af8792da8093b486885a1ae4d15d452bcec/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", size = 160670, upload-time = "2025-08-09T07:56:17.314Z" },
+ { url = "https://files.pythonhosted.org/packages/31/e7/883ee5676a2ef217a40ce0bffcc3d0dfbf9e64cbcfbdf822c52981c3304b/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", size = 158501, upload-time = "2025-08-09T07:56:18.641Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/35/6525b21aa0db614cf8b5792d232021dca3df7f90a1944db934efa5d20bb1/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", size = 153173, upload-time = "2025-08-09T07:56:20.289Z" },
+ { url = "https://files.pythonhosted.org/packages/50/ee/f4704bad8201de513fdc8aac1cabc87e38c5818c93857140e06e772b5892/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", size = 99822, upload-time = "2025-08-09T07:56:21.551Z" },
+ { url = "https://files.pythonhosted.org/packages/39/f5/3b3836ca6064d0992c58c7561c6b6eee1b3892e9665d650c803bd5614522/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", size = 107543, upload-time = "2025-08-09T07:56:23.115Z" },
+ { url = "https://files.pythonhosted.org/packages/65/ca/2135ac97709b400c7654b4b764daf5c5567c2da45a30cdd20f9eefe2d658/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", size = 205326, upload-time = "2025-08-09T07:56:24.721Z" },
+ { url = "https://files.pythonhosted.org/packages/71/11/98a04c3c97dd34e49c7d247083af03645ca3730809a5509443f3c37f7c99/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", size = 146008, upload-time = "2025-08-09T07:56:26.004Z" },
+ { url = "https://files.pythonhosted.org/packages/60/f5/4659a4cb3c4ec146bec80c32d8bb16033752574c20b1252ee842a95d1a1e/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", size = 159196, upload-time = "2025-08-09T07:56:27.25Z" },
+ { url = "https://files.pythonhosted.org/packages/86/9e/f552f7a00611f168b9a5865a1414179b2c6de8235a4fa40189f6f79a1753/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", size = 156819, upload-time = "2025-08-09T07:56:28.515Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", size = 151350, upload-time = "2025-08-09T07:56:29.716Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/a9/3865b02c56f300a6f94fc631ef54f0a8a29da74fb45a773dfd3dcd380af7/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", size = 148644, upload-time = "2025-08-09T07:56:30.984Z" },
+ { url = "https://files.pythonhosted.org/packages/77/d9/cbcf1a2a5c7d7856f11e7ac2d782aec12bdfea60d104e60e0aa1c97849dc/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9", size = 160468, upload-time = "2025-08-09T07:56:32.252Z" },
+ { url = "https://files.pythonhosted.org/packages/f6/42/6f45efee8697b89fda4d50580f292b8f7f9306cb2971d4b53f8914e4d890/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", size = 158187, upload-time = "2025-08-09T07:56:33.481Z" },
+ { url = "https://files.pythonhosted.org/packages/70/99/f1c3bdcfaa9c45b3ce96f70b14f070411366fa19549c1d4832c935d8e2c3/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", size = 152699, upload-time = "2025-08-09T07:56:34.739Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/ad/b0081f2f99a4b194bcbb1934ef3b12aa4d9702ced80a37026b7607c72e58/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", size = 99580, upload-time = "2025-08-09T07:56:35.981Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", size = 107366, upload-time = "2025-08-09T07:56:37.339Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/91/b5a06ad970ddc7a0e513112d40113e834638f4ca1120eb727a249fb2715e/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", size = 204342, upload-time = "2025-08-09T07:56:38.687Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/ec/1edc30a377f0a02689342f214455c3f6c2fbedd896a1d2f856c002fc3062/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", size = 145995, upload-time = "2025-08-09T07:56:40.048Z" },
+ { url = "https://files.pythonhosted.org/packages/17/e5/5e67ab85e6d22b04641acb5399c8684f4d37caf7558a53859f0283a650e9/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", size = 158640, upload-time = "2025-08-09T07:56:41.311Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/e5/38421987f6c697ee3722981289d554957c4be652f963d71c5e46a262e135/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", size = 156636, upload-time = "2025-08-09T07:56:43.195Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/e4/5a075de8daa3ec0745a9a3b54467e0c2967daaaf2cec04c845f73493e9a1/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", size = 150939, upload-time = "2025-08-09T07:56:44.819Z" },
+ { url = "https://files.pythonhosted.org/packages/02/f7/3611b32318b30974131db62b4043f335861d4d9b49adc6d57c1149cc49d4/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", size = 148580, upload-time = "2025-08-09T07:56:46.684Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/61/19b36f4bd67f2793ab6a99b979b4e4f3d8fc754cbdffb805335df4337126/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", size = 159870, upload-time = "2025-08-09T07:56:47.941Z" },
+ { url = "https://files.pythonhosted.org/packages/06/57/84722eefdd338c04cf3030ada66889298eaedf3e7a30a624201e0cbe424a/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", size = 157797, upload-time = "2025-08-09T07:56:49.756Z" },
+ { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224, upload-time = "2025-08-09T07:56:51.369Z" },
+ { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086, upload-time = "2025-08-09T07:56:52.722Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400, upload-time = "2025-08-09T07:56:55.172Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" },
+]
+
+[[package]]
+name = "cibuildwheel"
+version = "3.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "bashlex" },
+ { name = "bracex" },
+ { name = "build" },
+ { name = "certifi" },
+ { name = "dependency-groups" },
+ { name = "filelock" },
+ { name = "humanize" },
+ { name = "packaging" },
+ { name = "patchelf", marker = "(platform_machine == 'aarch64' and sys_platform == 'darwin') or (platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'x86_64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'arm64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" },
+ { name = "platformdirs" },
+ { name = "pyelftools" },
+ { name = "wheel" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/42/33/c3e5884a4f996d9138ace03464d0396752ec8c81adada549421bc68d185f/cibuildwheel-3.2.0.tar.gz", hash = "sha256:03ceab277255dc6c6451b25aad78844f4c07b03e410ee7411e9045b20ef6466f", size = 354877, upload-time = "2025-09-22T20:46:24.522Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/52/b0/cbf2260b9cc2fea23abd2fac607b4d3692dfd250062fba3523b8008847bd/cibuildwheel-3.2.0-py3-none-any.whl", hash = "sha256:5349f85b89ed63d53bf79315996adb9d4e507c4b69dacb480c1eef7fddde21e1", size = 126344, upload-time = "2025-09-22T20:46:22.157Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "cypari2"
+source = { editable = "." }
+dependencies = [
+ { name = "cysignals" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "build" },
+ { name = "cibuildwheel" },
+ { name = "cython" },
+ { name = "meson" },
+ { name = "meson-python" },
+ { name = "ninja" },
+ { name = "pkgconf" },
+ { name = "pytest" },
+]
+doc = [
+ { name = "sphinx" },
+]
+
+[package.metadata]
+requires-dist = [{ name = "cysignals", specifier = ">=1.11.3" }]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "build", specifier = ">=1.3.0" },
+ { name = "cibuildwheel", specifier = ">=2.23.3" },
+ { name = "cython", specifier = ">=3.1.4" },
+ { name = "meson", specifier = ">=1.9.0" },
+ { name = "meson-python", specifier = ">=0.18.0" },
+ { name = "ninja", specifier = ">=1.13.0" },
+ { name = "pkgconf", specifier = ">=2.4.3.post2" },
+ { name = "pytest", specifier = ">=8.4.2" },
+]
+doc = [{ name = "sphinx" }]
+
+[[package]]
+name = "cysignals"
+version = "1.12.5"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ba/be/3dd297fb25113abf40dd5de66088ce6883b62c417caa6b5fc2a84b9d48bf/cysignals-1.12.5.tar.gz", hash = "sha256:8f8ed409043d028b59d063dc4c069cbf12a750534757ce06f38eeac5ff368700", size = 86022, upload-time = "2025-09-24T02:47:35.065Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ff/7f/4ac0871dfea1e5723db6a8765e340660c6bf789d9d538c10e773c08ab2e0/cysignals-1.12.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7c4074c9a9ae1294abf6a7de224174c2797e3b8f0c86881a04557224ad766bd", size = 220817, upload-time = "2025-09-24T02:47:09.319Z" },
+ { url = "https://files.pythonhosted.org/packages/ba/0c/17b2236fb780081cd95a6609747377c9f5d0bd85fb0d7aa31ee9f5dc531f/cysignals-1.12.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:08dc79fd7470f828d7ae2f70b534a2710d39c1f194ffeb9649fbdff6e6f0bfff", size = 219943, upload-time = "2025-09-24T02:47:10.347Z" },
+ { url = "https://files.pythonhosted.org/packages/60/fd/9d84bcd8c0d743b41f22e2ef54125e4e787c401e1ffe569b15a433d089ac/cysignals-1.12.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c8011f72efc59fda3cf72096e7cdfc00f415629252c161c29eb721427a666a8", size = 262680, upload-time = "2025-09-24T02:47:11.35Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/e5/6954b9b5d8c843292a58cb091fb52c4a93305681d63e5b48c01d9ff0dead/cysignals-1.12.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eccbcfd762de37daf4a01a0a77ef653561a153c48c2db9104916d36ebbd3cf24", size = 270195, upload-time = "2025-09-24T02:47:12.424Z" },
+ { url = "https://files.pythonhosted.org/packages/76/04/cea6ac568ec4c2c9a5d003629346438ec8ceb991a627edc91fa8d24028de/cysignals-1.12.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:741c9bed4ef802c5892f62c6c8ad96390610bcfb617a0250a86c595eecdd13a9", size = 263724, upload-time = "2025-09-24T02:47:13.789Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/06/16111451a159266a9b03946498137645cd1fd334331b751b00c55fdc2bd4/cysignals-1.12.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:10e57664e3a2c3e7cdd270b7fa041859b552c2813c195b1247e3c116bf40226b", size = 273469, upload-time = "2025-09-24T02:47:14.785Z" },
+ { url = "https://files.pythonhosted.org/packages/63/8a/a50f6df7d3e49f056727b9140521e8588222a904b97d8bca6a81b25b138e/cysignals-1.12.5-cp312-cp312-win_amd64.whl", hash = "sha256:8824990cdf09891ccdd8f5d0f839762948c90535b56d476fcf8c0dddd27ca53b", size = 53672, upload-time = "2025-09-24T02:47:16.127Z" },
+ { url = "https://files.pythonhosted.org/packages/20/51/abe5fc0b929c798c7e67f36ea1f0f279e3d3e9549bde8c7e48f272cc48d4/cysignals-1.12.5-cp312-cp312-win_arm64.whl", hash = "sha256:f8e27a442aea569e824b12cd4b8c8599d94e44272e3dfaa56d4ac98215aef7c1", size = 50737, upload-time = "2025-09-24T02:47:16.951Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/3e/9873294ae69ab6620a19e225b65b2aaf79b42a0e5c50e55ccda129d493ac/cysignals-1.12.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c2131f0a724d3f5c0d6ae11c100641a491b223b075d03aa83c69b1d44736a099", size = 217212, upload-time = "2025-09-24T02:47:18.409Z" },
+ { url = "https://files.pythonhosted.org/packages/77/9c/208ba3bad103ed0218d6a225705f2ebc9a886167e0fae5d761c891779057/cysignals-1.12.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:03cb462edcc1ee7b63f2108bbeb89ce04ddca3baeb4d490f26c997ec23f392f1", size = 217008, upload-time = "2025-09-24T02:47:19.495Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/ab/ebc8dc495251630832a2572ef9a350ac0d2b7d9608531fbbb65fc61ad6e4/cysignals-1.12.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64895f286cb6e0f070db6ea8c808039fda21b2c3c9876e3486e6f36aa956b557", size = 260584, upload-time = "2025-09-24T02:47:20.564Z" },
+ { url = "https://files.pythonhosted.org/packages/95/bc/4aaf0032b7c5c7d3c62e42ce6ffda431778f08ac8f52d701af77ed5db3c1/cysignals-1.12.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0008a7e53f4889f75c5132c06b42723e80ec40f1035be1cbe4d909896e8f55dc", size = 268999, upload-time = "2025-09-24T02:47:21.579Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/7d/ef2e2d6a08f3821fd157fe69ecdf921c763645ea6259f557a7712f42b7ee/cysignals-1.12.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800b6b7ad6c45590a2a30d05889378beee9948d8828bc8aafd79694825b595b6", size = 262547, upload-time = "2025-09-24T02:47:22.598Z" },
+ { url = "https://files.pythonhosted.org/packages/22/51/0a564cfefe9853ddcfb4b76ab845398471dd4106da29e829be31705db2c1/cysignals-1.12.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c09035afcd3017250e796247f3eaf5e79a9a7090b1e104a962b8eb4c87bf9ebe", size = 271757, upload-time = "2025-09-24T02:47:23.637Z" },
+ { url = "https://files.pythonhosted.org/packages/a8/8d/164781b362dca2216916896d2ede197f2496c97fa961ccb6265382e6ad24/cysignals-1.12.5-cp313-cp313-win_amd64.whl", hash = "sha256:7392bbc6a46ee9b1eb973ec994f95f7421257a474c071c56def37c7ce0ea8d87", size = 53494, upload-time = "2025-09-24T02:47:24.922Z" },
+ { url = "https://files.pythonhosted.org/packages/53/c8/6e5bb6f96405c41cffef037540a6eb031657e92cb7f2213cf532191f9484/cysignals-1.12.5-cp313-cp313-win_arm64.whl", hash = "sha256:1a2ebb66883be5e493741c5db787d509b2c1f860d32829a184dbc912b33a9f4e", size = 50469, upload-time = "2025-09-24T02:47:25.745Z" },
+]
+
+[[package]]
+name = "cython"
+version = "3.1.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a7/f6/d762df1f436a0618455d37f4e4c4872a7cd0dcfc8dec3022ee99e4389c69/cython-3.1.4.tar.gz", hash = "sha256:9aefefe831331e2d66ab31799814eae4d0f8a2d246cbaaaa14d1be29ef777683", size = 3190778, upload-time = "2025-09-16T07:20:33.531Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f0/51/2939c739cfdc67ab94935a2c4fcc75638afd15e1954552655503a4112e92/cython-3.1.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0d26af46505d0e54fe0f05e7ad089fd0eed8fa04f385f3ab88796f554467bcb9", size = 3062976, upload-time = "2025-09-16T07:22:20.517Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/bd/a84de57fd01017bf5dba84a49aeee826db21112282bf8d76ab97567ee15d/cython-3.1.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66ac8bb5068156c92359e3f0eefa138c177d59d1a2e8a89467881fa7d06aba3b", size = 2970701, upload-time = "2025-09-16T07:22:22.644Z" },
+ { url = "https://files.pythonhosted.org/packages/71/79/a09004c8e42f5be188c7636b1be479cdb244a6d8837e1878d062e4e20139/cython-3.1.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2e42714faec723d2305607a04bafb49a48a8d8f25dd39368d884c058dbcfbc", size = 3387730, upload-time = "2025-09-16T07:22:24.271Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/bd/979f8c59e247f562642f3eb98a1b453530e1f7954ef071835c08ed2bf6ba/cython-3.1.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0fd655b27997a209a574873304ded9629de588f021154009e8f923475e2c677", size = 3167289, upload-time = "2025-09-16T07:22:26.35Z" },
+ { url = "https://files.pythonhosted.org/packages/34/f8/0b98537f0b4e8c01f76d2a6cf75389987538e4d4ac9faf25836fd18c9689/cython-3.1.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9def7c41f4dc339003b1e6875f84edf059989b9c7f5e9a245d3ce12c190742d9", size = 3321099, upload-time = "2025-09-16T07:22:27.957Z" },
+ { url = "https://files.pythonhosted.org/packages/f3/39/437968a2e7c7f57eb6e1144f6aca968aa15fbbf169b2d4da5d1ff6c21442/cython-3.1.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:196555584a8716bf7e017e23ca53e9f632ed493f9faa327d0718e7551588f55d", size = 3179897, upload-time = "2025-09-16T07:22:30.014Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/04/b3f42915f034d133f1a34e74a2270bc2def02786f9b40dc9028fbb968814/cython-3.1.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7fff0e739e07a20726484b8898b8628a7b87acb960d0fc5486013c6b77b7bb97", size = 3400936, upload-time = "2025-09-16T07:22:31.705Z" },
+ { url = "https://files.pythonhosted.org/packages/21/eb/2ad9fa0896ab6cf29875a09a9f4aaea37c28b79b869a013bf9b58e4e652e/cython-3.1.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c2754034fa10f95052949cd6b07eb2f61d654c1b9cfa0b17ea53a269389422e8", size = 3332131, upload-time = "2025-09-16T07:22:33.32Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/bf/f19283f8405e7e564c3353302a8665ea2c589be63a8e1be1b503043366a9/cython-3.1.4-cp312-cp312-win32.whl", hash = "sha256:2e0808ff3614a1dbfd1adfcbff9b2b8119292f1824b3535b4a173205109509f8", size = 2487672, upload-time = "2025-09-16T07:22:35.227Z" },
+ { url = "https://files.pythonhosted.org/packages/30/bf/32150a2e6c7b50b81c5dc9e942d41969400223a9c49d04e2ed955709894c/cython-3.1.4-cp312-cp312-win_amd64.whl", hash = "sha256:f262b32327b6bce340cce5d45bbfe3972cb62543a4930460d8564a489f3aea12", size = 2705348, upload-time = "2025-09-16T07:22:37.922Z" },
+ { url = "https://files.pythonhosted.org/packages/24/10/1acc34f4d2d14de38e2d3ab4795ad1c8f547cebc2d9e7477a49a063ba607/cython-3.1.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ab549d0fc187804e0f14fc4759e4b5ad6485ffc01554b2f8b720cc44aeb929cd", size = 3051524, upload-time = "2025-09-16T07:22:40.607Z" },
+ { url = "https://files.pythonhosted.org/packages/04/85/8457a78e9b9017a4fb0289464066ff2e73c5885f1edb9c1b9faaa2877fe2/cython-3.1.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:52eae5d9bcc515441a436dcae2cbadfd00c5063d4d7809bd0178931690c06a76", size = 2958862, upload-time = "2025-09-16T07:22:42.646Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/a8/42989748b63ec56c5b950fd26ec01fc77f9cf72dc318eb2eee257a6b652c/cython-3.1.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6f06345cfa583dd17fff1beedb237853689b85aa400ea9e0db7e5265f3322d15", size = 3364296, upload-time = "2025-09-16T07:22:44.444Z" },
+ { url = "https://files.pythonhosted.org/packages/98/9d/b27d5d402552932875f2b8f795385dabd27525a8a6645010c876fe84a0f9/cython-3.1.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f5d915556c757212cb8ddd4e48c16f2ab481dbb9a76f5153ab26f418c3537eb5", size = 3154391, upload-time = "2025-09-16T07:22:46.852Z" },
+ { url = "https://files.pythonhosted.org/packages/65/55/742737e40f7a3f1963440d66322b5fa93844762dd7a3a23d9b5b1d0d594e/cython-3.1.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c3f3bb603f28b3c1df66baaa5cdbf6029578552b458f1d321bae23b87f6c3199", size = 3305883, upload-time = "2025-09-16T07:22:48.55Z" },
+ { url = "https://files.pythonhosted.org/packages/98/3f/0baecd7ac0fac2dbb47acd7f0970c298f38d0504774c5552cf6224bdf3e6/cython-3.1.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7aff230893ee1044e7bc98d313c034ead70a3dd54d4d22e89ca1734540d94084", size = 3170437, upload-time = "2025-09-16T07:22:50.213Z" },
+ { url = "https://files.pythonhosted.org/packages/74/18/1ec53e2cf10a8064c7faa305b105b9c45af619ee30a6f1f7eb91efbb304b/cython-3.1.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8e83f114c04f72f85591ddb0b28f08ab2e40d250c26686d6509c0f70a9e2ca34", size = 3377458, upload-time = "2025-09-16T07:22:52.192Z" },
+ { url = "https://files.pythonhosted.org/packages/bd/8c/3d0839cf0b315157974bf283d4bd658f5c30277091ad34c093f286c59e0f/cython-3.1.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8096394960d38b793545753b73781bc0ec695f0b8c22454431704b297e296045", size = 3318723, upload-time = "2025-09-16T07:22:54.322Z" },
+ { url = "https://files.pythonhosted.org/packages/c6/05/67b4de710a3109030d868e23d5dccf35559afa4c089b4c0aa9e22ffda1f1/cython-3.1.4-cp313-cp313-win32.whl", hash = "sha256:4e7c726ac753ca1a5aa30286cbadcd10ed4b4312ea710a8a16bb908d41e9c059", size = 2481433, upload-time = "2025-09-16T07:22:56.409Z" },
+ { url = "https://files.pythonhosted.org/packages/89/ef/f179b5a46185bc5550c07b328d687ee32251963a3a93e869b75fbf97181c/cython-3.1.4-cp313-cp313-win_amd64.whl", hash = "sha256:f2ee2bb77943044f301cec04d0b51d8e3810507c9c250d6cd079a3e2d6ba88f2", size = 2703057, upload-time = "2025-09-16T07:22:57.994Z" },
+ { url = "https://files.pythonhosted.org/packages/38/85/f1380e8370b470b218e452ba3995555524e3652f026333e6bad6c68770b5/cython-3.1.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c7258739d5560918741cb040bd85ba7cc2f09d868de9116a637e06714fec1f69", size = 3045864, upload-time = "2025-09-16T07:22:59.854Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/31/54c7bc78df1e55ac311054cb2fd33908f23b8a6f350c30defeca416d8077/cython-3.1.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b2d522ee8d3528035e247ee721fb40abe92e9ea852dc9e48802cec080d5de859", size = 2967105, upload-time = "2025-09-16T07:23:01.666Z" },
+ { url = "https://files.pythonhosted.org/packages/02/02/89f70e71972f796863429b159c8e8e858b85bedbc9c747d167a5c6f6417e/cython-3.1.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a4e0560baeb56c29d7d8d693a050dd4d2ed922d8d7c66f5c5715c6f2be84e903", size = 3363386, upload-time = "2025-09-16T07:23:03.39Z" },
+ { url = "https://files.pythonhosted.org/packages/2a/34/eda836ae260013d4dd1c7aaa8dd6f7d7862206ba3354db5d8f55a8f6ef67/cython-3.1.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4223cacc81cba0df0f06f79657c5d6286e153b9a9b989dad1cdf4666f618c073", size = 3192314, upload-time = "2025-09-16T07:23:05.354Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/fa/db8224f7fe7ec1ebdab0b5e71b5a8269c112645c4eac2464ef0735bb395e/cython-3.1.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ff4d1f159edee6af38572318681388fbd6448b0d08b9a47494aaf0b698e93394", size = 3312222, upload-time = "2025-09-16T07:23:07.066Z" },
+ { url = "https://files.pythonhosted.org/packages/62/09/419262657800dee7202a76956cd52896a6e8793bbbecc2592a4ebba2e034/cython-3.1.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2537c53071a9a124e0bc502a716e1930d9bb101e94c26673016cf1820e4fdbd1", size = 3208798, upload-time = "2025-09-16T07:23:08.758Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/d8/f140c7b9356a29660dc05591272e33062df964b9d1a072d09e89ade41087/cython-3.1.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:85416717c529fb5ccf908464657a5187753e76d7b6ffec9b1c2d91544f6c3628", size = 3379662, upload-time = "2025-09-16T07:23:10.511Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/e8/83cf9a9cf64cbfe4eaf3987a633be08243f838b7d12e5739831297b77311/cython-3.1.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:18882e2f5c0e0c25f9c44f16f2fb9c48f33988885c5f9eae2856f10c6f089ffa", size = 3324255, upload-time = "2025-09-16T07:23:12.267Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/f8/f2033044687cf6296275fa71cdf63a247d3646a3e276aa002e65bf505f46/cython-3.1.4-cp314-cp314-win32.whl", hash = "sha256:8ef8deadc888eaf95e5328fc176fb6c37bccee1213f07517c6ea55b5f817c457", size = 2503665, upload-time = "2025-09-16T07:23:14.372Z" },
+ { url = "https://files.pythonhosted.org/packages/04/57/7af75a803d55610d570d7b7a0fdc2bfd82fae030c728089cc628562d67f9/cython-3.1.4-cp314-cp314-win_amd64.whl", hash = "sha256:acb99ddec62ba1ea5de0e0087760fa834ec42c94f0488065a4f1995584e8e94e", size = 2734608, upload-time = "2025-09-16T07:23:16.025Z" },
+ { url = "https://files.pythonhosted.org/packages/7c/24/f7351052cf9db771fe4f32fca47fd66e6d9b53d8613b17faf7d130a9d553/cython-3.1.4-py3-none-any.whl", hash = "sha256:d194d95e4fa029a3f6c7d46bdd16d973808c7ea4797586911fdb67cb98b1a2c6", size = 1227541, upload-time = "2025-09-16T07:20:29.595Z" },
+]
+
+[[package]]
+name = "dependency-groups"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "packaging" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/62/55/f054de99871e7beb81935dea8a10b90cd5ce42122b1c3081d5282fdb3621/dependency_groups-1.3.1.tar.gz", hash = "sha256:78078301090517fd938c19f64a53ce98c32834dfe0dee6b88004a569a6adfefd", size = 10093, upload-time = "2025-05-02T00:34:29.452Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/99/c7/d1ec24fb280caa5a79b6b950db565dab30210a66259d17d5bb2b3a9f878d/dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030", size = 8664, upload-time = "2025-05-02T00:34:27.085Z" },
+]
+
+[[package]]
+name = "docutils"
+version = "0.21.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" },
+]
+
+[[package]]
+name = "filelock"
+version = "3.19.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" },
+]
+
+[[package]]
+name = "humanize"
+version = "4.13.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/98/1d/3062fcc89ee05a715c0b9bfe6490c00c576314f27ffee3a704122c6fd259/humanize-4.13.0.tar.gz", hash = "sha256:78f79e68f76f0b04d711c4e55d32bebef5be387148862cb1ef83d2b58e7935a0", size = 81884, upload-time = "2025-08-25T09:39:20.04Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/c7/316e7ca04d26695ef0635dc81683d628350810eb8e9b2299fc08ba49f366/humanize-4.13.0-py3-none-any.whl", hash = "sha256:b810820b31891813b1673e8fec7f1ed3312061eab2f26e3fa192c393d11ed25f", size = 128869, upload-time = "2025-08-25T09:39:18.54Z" },
+]
+
+[[package]]
+name = "idna"
+version = "3.10"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
+]
+
+[[package]]
+name = "imagesize"
+version = "1.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026, upload-time = "2022-07-01T12:21:05.687Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" },
+]
+
+[[package]]
+name = "jinja2"
+version = "3.1.6"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markupsafe" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
+]
+
+[[package]]
+name = "markupsafe"
+version = "3.0.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" },
+ { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" },
+ { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" },
+ { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" },
+ { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" },
+ { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" },
+ { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" },
+ { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" },
+ { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" },
+ { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" },
+ { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" },
+ { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" },
+ { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" },
+ { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" },
+ { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" },
+ { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" },
+ { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" },
+ { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" },
+ { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" },
+ { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" },
+ { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" },
+ { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" },
+ { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" },
+ { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" },
+ { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" },
+]
+
+[[package]]
+name = "meson"
+version = "1.9.1"
+source = { registry = "https://pypi.org/simple" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9c/07/b48592d325cb86682829f05216e4efb2dc881762b8f1bafb48b57442307a/meson-1.9.1-py3-none-any.whl", hash = "sha256:f824ab770c041a202f532f69e114c971918ed2daff7ea56583d80642564598d0", size = 1030356, upload-time = "2025-09-22T18:39:37.458Z" },
+]
+
+[[package]]
+name = "meson-python"
+version = "0.18.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "meson" },
+ { name = "packaging" },
+ { name = "pyproject-metadata" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/26/bd/fdb26366443620f1a8a4d4ec7bfa37d1fbbe7bf737b257c205bbcf95ba95/meson_python-0.18.0.tar.gz", hash = "sha256:c56a99ec9df669a40662fe46960321af6e4b14106c14db228709c1628e23848d", size = 95630, upload-time = "2025-05-05T10:13:56.889Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/28/58/66db620a8a7ccb32633de9f403fe49f1b63c68ca94e5c340ec5cceeb9821/meson_python-0.18.0-py3-none-any.whl", hash = "sha256:3b0fe051551cc238f5febb873247c0949cd60ded556efa130aa57021804868e2", size = 28420, upload-time = "2025-05-05T10:13:55.218Z" },
+]
+
+[[package]]
+name = "ninja"
+version = "1.13.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/43/73/79a0b22fc731989c708068427579e840a6cf4e937fe7ae5c5d0b7356ac22/ninja-1.13.0.tar.gz", hash = "sha256:4a40ce995ded54d9dc24f8ea37ff3bf62ad192b547f6c7126e7e25045e76f978", size = 242558, upload-time = "2025-08-11T15:10:19.421Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3c/74/d02409ed2aa865e051b7edda22ad416a39d81a84980f544f8de717cab133/ninja-1.13.0-py3-none-macosx_10_9_universal2.whl", hash = "sha256:fa2a8bfc62e31b08f83127d1613d10821775a0eb334197154c4d6067b7068ff1", size = 310125, upload-time = "2025-08-11T15:09:50.971Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/de/6e1cd6b84b412ac1ef327b76f0641aeb5dcc01e9d3f9eee0286d0c34fd93/ninja-1.13.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3d00c692fb717fd511abeb44b8c5d00340c36938c12d6538ba989fe764e79630", size = 177467, upload-time = "2025-08-11T15:09:52.767Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/83/49320fb6e58ae3c079381e333575fdbcf1cca3506ee160a2dcce775046fa/ninja-1.13.0-py3-none-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:be7f478ff9f96a128b599a964fc60a6a87b9fa332ee1bd44fa243ac88d50291c", size = 187834, upload-time = "2025-08-11T15:09:54.115Z" },
+ { url = "https://files.pythonhosted.org/packages/56/c7/ba22748fb59f7f896b609cd3e568d28a0a367a6d953c24c461fe04fc4433/ninja-1.13.0-py3-none-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:60056592cf495e9a6a4bea3cd178903056ecb0943e4de45a2ea825edb6dc8d3e", size = 202736, upload-time = "2025-08-11T15:09:55.745Z" },
+ { url = "https://files.pythonhosted.org/packages/79/22/d1de07632b78ac8e6b785f41fa9aad7a978ec8c0a1bf15772def36d77aac/ninja-1.13.0-py3-none-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:1c97223cdda0417f414bf864cfb73b72d8777e57ebb279c5f6de368de0062988", size = 179034, upload-time = "2025-08-11T15:09:57.394Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/de/0e6edf44d6a04dabd0318a519125ed0415ce437ad5a1ec9b9be03d9048cf/ninja-1.13.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fb46acf6b93b8dd0322adc3a4945452a4e774b75b91293bafcc7b7f8e6517dfa", size = 180716, upload-time = "2025-08-11T15:09:58.696Z" },
+ { url = "https://files.pythonhosted.org/packages/54/28/938b562f9057aaa4d6bfbeaa05e81899a47aebb3ba6751e36c027a7f5ff7/ninja-1.13.0-py3-none-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4be9c1b082d244b1ad7ef41eb8ab088aae8c109a9f3f0b3e56a252d3e00f42c1", size = 146843, upload-time = "2025-08-11T15:10:00.046Z" },
+ { url = "https://files.pythonhosted.org/packages/2a/fb/d06a3838de4f8ab866e44ee52a797b5491df823901c54943b2adb0389fbb/ninja-1.13.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:6739d3352073341ad284246f81339a384eec091d9851a886dfa5b00a6d48b3e2", size = 154402, upload-time = "2025-08-11T15:10:01.657Z" },
+ { url = "https://files.pythonhosted.org/packages/31/bf/0d7808af695ceddc763cf251b84a9892cd7f51622dc8b4c89d5012779f06/ninja-1.13.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:11be2d22027bde06f14c343f01d31446747dbb51e72d00decca2eb99be911e2f", size = 552388, upload-time = "2025-08-11T15:10:03.349Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/70/c99d0c2c809f992752453cce312848abb3b1607e56d4cd1b6cded317351a/ninja-1.13.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:aa45b4037b313c2f698bc13306239b8b93b4680eb47e287773156ac9e9304714", size = 472501, upload-time = "2025-08-11T15:10:04.735Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/43/c217b1153f0e499652f5e0766da8523ce3480f0a951039c7af115e224d55/ninja-1.13.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5f8e1e8a1a30835eeb51db05cf5a67151ad37542f5a4af2a438e9490915e5b72", size = 638280, upload-time = "2025-08-11T15:10:06.512Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/45/9151bba2c8d0ae2b6260f71696330590de5850e5574b7b5694dce6023e20/ninja-1.13.0-py3-none-musllinux_1_2_ppc64le.whl", hash = "sha256:3d7d7779d12cb20c6d054c61b702139fd23a7a964ec8f2c823f1ab1b084150db", size = 642420, upload-time = "2025-08-11T15:10:08.35Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/fb/95752eb635bb8ad27d101d71bef15bc63049de23f299e312878fc21cb2da/ninja-1.13.0-py3-none-musllinux_1_2_riscv64.whl", hash = "sha256:d741a5e6754e0bda767e3274a0f0deeef4807f1fec6c0d7921a0244018926ae5", size = 585106, upload-time = "2025-08-11T15:10:09.818Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/31/aa56a1a286703800c0cbe39fb4e82811c277772dc8cd084f442dd8e2938a/ninja-1.13.0-py3-none-musllinux_1_2_s390x.whl", hash = "sha256:e8bad11f8a00b64137e9b315b137d8bb6cbf3086fbdc43bf1f90fd33324d2e96", size = 707138, upload-time = "2025-08-11T15:10:11.366Z" },
+ { url = "https://files.pythonhosted.org/packages/34/6f/5f5a54a1041af945130abdb2b8529cbef0cdcbbf9bcf3f4195378319d29a/ninja-1.13.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b4f2a072db3c0f944c32793e91532d8948d20d9ab83da9c0c7c15b5768072200", size = 581758, upload-time = "2025-08-11T15:10:13.295Z" },
+ { url = "https://files.pythonhosted.org/packages/95/97/51359c77527d45943fe7a94d00a3843b81162e6c4244b3579fe8fc54cb9c/ninja-1.13.0-py3-none-win32.whl", hash = "sha256:8cfbb80b4a53456ae8a39f90ae3d7a2129f45ea164f43fadfa15dc38c4aef1c9", size = 267201, upload-time = "2025-08-11T15:10:15.158Z" },
+ { url = "https://files.pythonhosted.org/packages/29/45/c0adfbfb0b5895aa18cec400c535b4f7ff3e52536e0403602fc1a23f7de9/ninja-1.13.0-py3-none-win_amd64.whl", hash = "sha256:fb8ee8719f8af47fed145cced4a85f0755dd55d45b2bddaf7431fa89803c5f3e", size = 309975, upload-time = "2025-08-11T15:10:16.697Z" },
+ { url = "https://files.pythonhosted.org/packages/df/93/a7b983643d1253bb223234b5b226e69de6cda02b76cdca7770f684b795f5/ninja-1.13.0-py3-none-win_arm64.whl", hash = "sha256:3c0b40b1f0bba764644385319028650087b4c1b18cdfa6f45cb39a3669b81aa9", size = 290806, upload-time = "2025-08-11T15:10:18.018Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "25.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
+]
+
+[[package]]
+name = "patchelf"
+version = "0.17.2.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/2c/a3/fdd3fa938c864aa2f11dd0b7f08befeda983d2dcdee44da493c6977a653f/patchelf-0.17.2.4.tar.gz", hash = "sha256:970ee5cd8af33e5ea2099510b2f9013fa1b8d5cd763bf3fd3961281c18101a09", size = 149629, upload-time = "2025-07-23T21:16:32.071Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b1/a7/8c4f86c78ec03db954d05fd9c57a114cc3a172a2d3e4a8b949cd5ff89471/patchelf-0.17.2.4-py3-none-macosx_10_9_universal2.whl", hash = "sha256:343bb1b94e959f9070ca9607453b04390e36bbaa33c88640b989cefad0aa049e", size = 184436, upload-time = "2025-07-23T21:16:20.578Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/19/f7821ef31aab01fa7dc8ebe697ece88ec4f7a0fdd3155dab2dfee4b00e5c/patchelf-0.17.2.4-py3-none-manylinux1_x86_64.manylinux_2_5_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:d9b35ebfada70c02679ad036407d9724ffe1255122ba4ac5e4be5868618a5689", size = 482846, upload-time = "2025-07-23T21:16:23.73Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/50/107fea848ecfd851d473b079cab79107487d72c4c3cdb25b9d2603a24ca2/patchelf-0.17.2.4-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:2931a1b5b85f3549661898af7bf746afbda7903c7c9a967cfc998a3563f84fad", size = 477811, upload-time = "2025-07-23T21:16:25.145Z" },
+ { url = "https://files.pythonhosted.org/packages/89/a9/a9a2103e159fd65bffbc21ecc5c8c36e44eb34fe53b4ef85fb6d08c2a635/patchelf-0.17.2.4-py3-none-manylinux2014_armv7l.manylinux_2_17_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:ae44cb3c857d50f54b99e5697aa978726ada33a8a6129d4b8b7ffd28b996652d", size = 431226, upload-time = "2025-07-23T21:16:26.765Z" },
+ { url = "https://files.pythonhosted.org/packages/87/93/897d612f6df7cfd987bdf668425127efeff8d8e4ad8bfbab1c69d2a0d861/patchelf-0.17.2.4-py3-none-manylinux2014_ppc64le.manylinux_2_17_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:680a266a70f60a7a4f4c448482c5bdba80cc8e6bb155a49dcc24238ba49927b0", size = 540276, upload-time = "2025-07-23T21:16:27.983Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/b8/2b92d11533482bac9ee989081d6880845287751b5f528adbd6bb27667fbd/patchelf-0.17.2.4-py3-none-manylinux2014_s390x.manylinux_2_17_s390x.musllinux_1_1_s390x.whl", hash = "sha256:d842b51f0401460f3b1f3a3a67d2c266a8f515a5adfbfa6e7b656cb3ac2ed8bc", size = 596632, upload-time = "2025-07-23T21:16:29.253Z" },
+ { url = "https://files.pythonhosted.org/packages/14/e2/975d4bdb418f942b53e6187b95bd9e0d5e0488b7bc214685a1e43e2c2751/patchelf-0.17.2.4-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:7076d9e127230982e20a81a6e2358d3343004667ba510d9f822d4fdee29b0d71", size = 508281, upload-time = "2025-07-23T21:16:30.865Z" },
+]
+
+[[package]]
+name = "pkgconf"
+version = "2.4.3.post2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "os_name == 'nt'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/be/4f/27b39de8c295efed8fbc32517ee07e4b26e9eb95d0fbf8b5d698e76d7412/pkgconf-2.4.3.post2.tar.gz", hash = "sha256:73d966e18f75e89da54c83a65effc8c2e9b7316553a060c8293ee527a0834c10", size = 144454, upload-time = "2025-06-08T10:19:41.581Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6f/08/0a89947c84804f1646e2ba0f836bc535f325b6a1d2e8c5bdcdadeb8c8916/pkgconf-2.4.3.post2-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:7c90084ac070447370240f2df664786726ab2a399e51677d3dba10cf7cd0cc36", size = 47873, upload-time = "2025-06-08T10:19:16.404Z" },
+ { url = "https://files.pythonhosted.org/packages/7f/f3/202c5a410fd432d02cc32f070fa82382c3c312dbe23b62a840b41e1d273e/pkgconf-2.4.3.post2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e9adb489a4a52dad6f6029d5dffd2d4e4262b5b9387ae34869ef5576ce7834e9", size = 46329, upload-time = "2025-06-08T10:19:18.139Z" },
+ { url = "https://files.pythonhosted.org/packages/55/81/60669fa13e37ae3cab204d5e82d1c908c56f6037651116e5e29d20bf0546/pkgconf-2.4.3.post2-py3-none-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:ae888298e699e5ff91ada94d304f2b6bac1b83f0b7c3cad9fcd07032ff511106", size = 62144, upload-time = "2025-06-08T10:19:19.745Z" },
+ { url = "https://files.pythonhosted.org/packages/78/c7/55c1d732a026b8e2a7ba23d730a1484063f7e85e19372045093db58feed3/pkgconf-2.4.3.post2-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:94d4e41290fdc5293b6ac19c4bbd1a1a934866b6ca23c1393275a810e2cc10d0", size = 58855, upload-time = "2025-06-08T10:19:21.349Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/b8/4536a1647d7cad90a2decc486882e6eb5d6c6da4d233214ae3b922a81c8a/pkgconf-2.4.3.post2-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c01f8e33fdf236c2365cd98e875eb98754d9868c52e168bf14a9fca818064695", size = 58266, upload-time = "2025-06-08T10:19:22.939Z" },
+ { url = "https://files.pythonhosted.org/packages/29/5a/03ebbacdc3129c21b822cb7a3b48894b8decd0dc2efba7d3bfa783991592/pkgconf-2.4.3.post2-py3-none-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4b34a33281d80b5d6c7ffc31aaeb58d590a6e9082fc09361b80b491d55c1b679", size = 68586, upload-time = "2025-06-08T10:19:24.53Z" },
+ { url = "https://files.pythonhosted.org/packages/52/fd/5f8666a58c2a7d8565a64434ed833e2eac6a733eb7e133eafb36001e7e9d/pkgconf-2.4.3.post2-py3-none-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:aef6dad009f6627c9dcc8c25a7f1b40d273b8c8bf6035a380093406906b4df68", size = 62255, upload-time = "2025-06-08T10:19:25.741Z" },
+ { url = "https://files.pythonhosted.org/packages/21/a4/ce37c5b42e59dc4f157553fa0413a0b12e2549b586193bc2429a3d637760/pkgconf-2.4.3.post2-py3-none-manylinux_2_27_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5bc7de745a75ae453118944bb069cc8cc4175c6b1c96c0263537826c6c87e142", size = 52943, upload-time = "2025-06-08T10:19:27.35Z" },
+ { url = "https://files.pythonhosted.org/packages/1c/92/18de0b35344f6fd63a1c79b497cdf907276c67967ef5958ec0009dbcb13b/pkgconf-2.4.3.post2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9e4eba8ff57743113c6f1ae1a3ca24dab775ef669fc5889dafff76e7cdf3155d", size = 59671, upload-time = "2025-06-08T10:19:28.635Z" },
+ { url = "https://files.pythonhosted.org/packages/f7/ba/4217032c3f98b1751205659d96b2452c0ef08cfcc6956d504ad05c29795c/pkgconf-2.4.3.post2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:876f061f930b36a5e299103d8145e39ca02b612d85984be33af6a0ccd9c464d5", size = 56607, upload-time = "2025-06-08T10:19:30.23Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/d0/3deff09bc801aa0214053fa147e41c685b1c5ce974bfd20c6ceeb7333c20/pkgconf-2.4.3.post2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f38b1081b06860edce8926d67899dfe7b85db03723b3fa18b3e12efa5dd94395", size = 64167, upload-time = "2025-06-08T10:19:31.435Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/e1/ec39d2166a07899c4ca0c608139496b0f6044deb50aedb1da687b173d933/pkgconf-2.4.3.post2-py3-none-musllinux_1_2_ppc64le.whl", hash = "sha256:95ddd0d06dd50418a04613fae5a6e0c46cc06329de006f1513ea6f7bdc40807b", size = 69318, upload-time = "2025-06-08T10:19:32.997Z" },
+ { url = "https://files.pythonhosted.org/packages/14/f4/71f16620dd87ce7e8ec4ea8dcd17c0075d72ed153cc6105d1949e085ceb6/pkgconf-2.4.3.post2-py3-none-musllinux_1_2_s390x.whl", hash = "sha256:f7f616a789c18ce9aebb5fc4cfdc48577575f2ab7df803b4df06a5298db9bdfa", size = 62008, upload-time = "2025-06-08T10:19:34.611Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/a9/48ea4d861bca750ed6a38b81e4e82d5f53c24f3430bcdec49e30d8ee39fc/pkgconf-2.4.3.post2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:201696a9c7d60668cab62a706ea159a560c08700a8690e70abc2e572a955752d", size = 60560, upload-time = "2025-06-08T10:19:36.194Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/4b/8c6e6be7bc9dc2daf885512b28723590a55fdebd68004b4083935949e984/pkgconf-2.4.3.post2-py3-none-win32.whl", hash = "sha256:90ee5b800865ecbdaf4e9302b06091b52d5528831c3e45f344a7287879d7adfa", size = 49753, upload-time = "2025-06-08T10:19:37.448Z" },
+ { url = "https://files.pythonhosted.org/packages/05/5b/2344be3846958600757697178844d681b38b457cccd2ea524a200895245b/pkgconf-2.4.3.post2-py3-none-win_amd64.whl", hash = "sha256:e11231d852a230dd35e61ca79c0d89136a6c9ccf7654a2a076384af01d5eb902", size = 49753, upload-time = "2025-06-08T10:19:39.033Z" },
+ { url = "https://files.pythonhosted.org/packages/56/76/75cb3e62b23628251f00574a6631c9c479bf272a0f6931e0c16c5247dc8d/pkgconf-2.4.3.post2-py3-none-win_arm64.whl", hash = "sha256:b1d137097771fcbcfc94926ea795244248833c9fe46c9631ea88bf156dc7b1cc", size = 44448, upload-time = "2025-06-08T10:19:40.279Z" },
+]
+
+[[package]]
+name = "platformdirs"
+version = "4.4.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyelftools"
+version = "0.32"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b9/ab/33968940b2deb3d92f5b146bc6d4009a5f95d1d06c148ea2f9ee965071af/pyelftools-0.32.tar.gz", hash = "sha256:6de90ee7b8263e740c8715a925382d4099b354f29ac48ea40d840cf7aa14ace5", size = 15047199, upload-time = "2025-02-19T14:20:05.549Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/af/43/700932c4f0638c3421177144a2e86448c0d75dbaee2c7936bda3f9fd0878/pyelftools-0.32-py3-none-any.whl", hash = "sha256:013df952a006db5e138b1edf6d8a68ecc50630adbd0d83a2d41e7f846163d738", size = 188525, upload-time = "2025-02-19T14:19:59.919Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.19.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
+]
+
+[[package]]
+name = "pyproject-hooks"
+version = "1.2.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228, upload-time = "2024-09-29T09:24:13.293Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z" },
+]
+
+[[package]]
+name = "pyproject-metadata"
+version = "0.9.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "packaging" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/64/ae/5fa065b049e97f96880de0611dbba513f0ee313b6edd0a64664c7b46a8e8/pyproject_metadata-0.9.1.tar.gz", hash = "sha256:b8b2253dd1b7062b78cf949a115f02ba7fa4114aabe63fa10528e9e1a954a816", size = 38415, upload-time = "2025-03-10T22:15:11.313Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7e/b1/8e63033b259e0a4e40dd1ec4a9fee17718016845048b43a36ec67d62e6fe/pyproject_metadata-0.9.1-py3-none-any.whl", hash = "sha256:ee5efde548c3ed9b75a354fc319d5afd25e9585fa918a34f62f904cc731973ad", size = 18829, upload-time = "2025-03-10T22:15:09.632Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "8.4.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" },
+]
+
+[[package]]
+name = "requests"
+version = "2.32.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "charset-normalizer" },
+ { name = "idna" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
+]
+
+[[package]]
+name = "roman-numerals-py"
+version = "3.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017, upload-time = "2025-02-22T07:34:54.333Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742, upload-time = "2025-02-22T07:34:52.422Z" },
+]
+
+[[package]]
+name = "snowballstemmer"
+version = "3.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575, upload-time = "2025-05-09T16:34:51.843Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" },
+]
+
+[[package]]
+name = "sphinx"
+version = "8.2.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "alabaster" },
+ { name = "babel" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "docutils" },
+ { name = "imagesize" },
+ { name = "jinja2" },
+ { name = "packaging" },
+ { name = "pygments" },
+ { name = "requests" },
+ { name = "roman-numerals-py" },
+ { name = "snowballstemmer" },
+ { name = "sphinxcontrib-applehelp" },
+ { name = "sphinxcontrib-devhelp" },
+ { name = "sphinxcontrib-htmlhelp" },
+ { name = "sphinxcontrib-jsmath" },
+ { name = "sphinxcontrib-qthelp" },
+ { name = "sphinxcontrib-serializinghtml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876, upload-time = "2025-03-02T22:31:59.658Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741, upload-time = "2025-03-02T22:31:56.836Z" },
+]
+
+[[package]]
+name = "sphinxcontrib-applehelp"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" },
+]
+
+[[package]]
+name = "sphinxcontrib-devhelp"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" },
+]
+
+[[package]]
+name = "sphinxcontrib-htmlhelp"
+version = "2.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" },
+]
+
+[[package]]
+name = "sphinxcontrib-jsmath"
+version = "1.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" },
+]
+
+[[package]]
+name = "sphinxcontrib-qthelp"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" },
+]
+
+[[package]]
+name = "sphinxcontrib-serializinghtml"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" },
+]
+
+[[package]]
+name = "urllib3"
+version = "2.5.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" },
+]
+
+[[package]]
+name = "wheel"
+version = "0.45.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/8a/98/2d9906746cdc6a6ef809ae6338005b3f21bb568bea3165cfc6a243fdc25c/wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729", size = 107545, upload-time = "2024-11-23T00:18:23.513Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248", size = 72494, upload-time = "2024-11-23T00:18:21.207Z" },
+]