Programming in GP: control statements

break({n = 1})

interrupts execution of current seq, and immediately exits from the n innermost enclosing loops, within the current function call (or the top level loop); the integer n must be positive. If n is greater than the number of enclosing loops, all enclosing loops are exited.




for(X = a,b,seq)

evaluates seq, where the formal variable X goes from a to b. Nothing is done if a > b. a and b must be in R.




fordiv(n,X,seq)

evaluates seq, where the formal variable X ranges through the divisors of n (see divisors, which is used as a subroutine). It is assumed that factor can handle n, without negative exponents. Instead of n, it is possible to input a factorization matrix, i.e. the output of factor(n).

This routine uses divisors as a subroutine, then loops over the divisors. In particular, if n is an integer, divisors are sorted by increasing size.

To avoid storing all divisors, possibly using a lot of memory, the following (much slower) routine loops over the divisors using essentially constant space:

FORDIV(N)=
 { my(P, E);
 
   P = factor(N); E = P[,2]; P = P[,1];
   forvec( v = vector(#E, i, [0,E[i]]),
   X = factorback(P, v)
   \\ ...
 );
 }
 ? for(i=1,10^5, FORDIV(i))
 time = 3,445 ms.
 ? for(i=1,10^5, fordiv(i, d, ))
 time = 490 ms.




forell(E,a,b,seq)

evaluates seq, where the formal variable E ranges through all elliptic curves of conductors from a to b. Th elldata database must be installed and contain data for the specified conductors.

The library syntax is forell(void *data, long (*call)(void*,GEN), GEN a, GEN b).




forprime(X = a,b,seq)

evaluates seq, where the formal variable X ranges over the prime numbers between a to b (including a and b if they are prime). More precisely, the value of X is incremented to the smallest prime strictly larger than X at the end of each iteration. Nothing is done if a > b. Note that a and b must be in R.

f(N) =
 {
   forprime(p = 2, N,
     print(p);
     if (p == 3, p = 6);
   )
 }
 ? f(12)
 2
 3
 7
 11




forstep(X = a,b,s,seq)

evaluates 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 < b. s must be in R^* or a vector of steps [s_1,...,s_n]. In the latter case, the successive steps are used in the order they appear in s.

? forstep(x=5, 20, [2,4], print(x))
 5
 7
 11
 13
 17
 19




forsubgroup(H = G,{bound},seq)

evaluates seq for each subgroup H of the abelian group G (given in SNF form or as a vector of elementary divisors), whose index is bounded by B. The subgroups are not ordered in any obvious way, unless G is a p-group in which case Birkhoff's algorithm produces them by decreasing index. A subgroup is given as a matrix whose columns give its generators on the implicit generators of G. For example, the following prints all subgroups of index less than 2 in G = Z/2Z g_1 x Z/2Z g_2:

? G = [2,2]; forsubgroup(H=G, 2, print(H))
 [1; 1]
 [1; 2]
 [2; 1]
 [1, 0; 1, 1]

The last one, for instance is generated by (g_1, g_1 + g_2). This routine is intended to treat huge groups, when subgrouplist is not an option due to the sheer size of the output.

For maximal speed the subgroups have been left as produced by the algorithm. To print them in canonical form (as left divisors of G in HNF form), one can for instance use

? G = matdiagonal([2,2]); forsubgroup(H=G, 2, print(mathnf(concat(G,H))))
 [2, 1; 0, 1]
 [1, 0; 0, 2]
 [2, 0; 0, 1]
 [1, 0; 0, 1]

Note that in this last representation, the index [G:H] is given by the determinant. See galoissubcyclo and galoisfixedfield for applications to Galois theory.

The library syntax is forsubgroup(void *data, long (*call)(void*,GEN), GEN G, GEN bound).




forvec(X = v,seq,{flag = 0})

Let v be an n-component vector (where n is arbitrary) of two-component vectors [a_i,b_i] for 1 <= i <= n. This routine evaluates seq, where the formal variables X[1],..., X[n] go from a_1 to b_1,..., from a_n to b_n, i.e.X goes from [a_1,...,a_n] to [b_1,...,b_n] with respect to the lexicographic ordering. (The formal variable with the highest index moves the fastest.) If flag = 1, generate only nondecreasing vectors X, and if flag = 2, generate only strictly increasing vectors X.

The type of X is the same as the type of v: t_VEC or t_COL.




if(a,{seq1},{seq2})

evaluates the expression sequence seq1 if a is non-zero, otherwise the expression seq2. Of course, seq1 or seq2 may be empty:

if (a,seq) evaluates seq if a is not equal to zero (you don't have to write the second comma), and does nothing otherwise,

if (a,,seq) evaluates seq if a is equal to zero, and does nothing otherwise. You could get the same result using the ! ( not) operator: if (!a,seq).

Note that the boolean operators && and || are evaluated according to operator precedence as explained in Section [Label: se:operators], but that, contrary to other operators, the evaluation of the arguments is stopped as soon as the final truth value has been determined. For instance

if (reallydoit && longcomplicatedfunction(), ...)

is a perfectly safe statement.

Recall that functions such as break and next operate on loops (such as forxxx, while, until). The if statement is not a loop (obviously!).




next({n = 1})

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.




return({x = 0})

returns from current subroutine, with result x. If x is omitted, return the (void) value (return no result, like print).




until(a,seq)

evaluates seq until a is not equal to 0 (i.e.until a is true). If a is initially not equal to 0, seq is evaluated once (more generally, the condition on a is tested after execution of the seq, not before as in while).




while(a,seq)

while a is non-zero, evaluates the expression sequence seq. The test is made before evaluating the seq, hence in particular if a is initially equal to zero the seq will not be evaluated at all.