# Printing

## The print-Statement

### `print expression;`

### `print expression, ..., expression;`

### `print expression : parameters;`

Print the value of the expression. Some limited ways of formatting output are described in the section on strings. Four levels of printing (that may in specific cases coincide) exist, and may be indicated after the colon: `Default` (which is the same as the level obtained if no level is indicated), `Minimal`, `Maximal`, and `Magma`. The last of these produces output representing the value of the identifier as valid Magma-input (when possible).

## Formatted Printing

### `printf format, expression, ..., expression;`

Print values of the expressions under control of format. The first argument, the *format string*, must be a string which contains two types of objects: plain characters, which are simply printed, and conversion specifications (indicated by the `%` character), each of which causes conversion and printing of zero or more of the expressions. (Use `%%` to get a literal percent character.) Currently, the only conversion specifications allowed are: `%o` and `%O`, which stand for “object”, `%m`, which stands for “magma”, and `%h`, which stands for “hexadecimal”.

The hexadecimal conversion specification will print its argument in hexadecimal; currently, it only supports integer arguments. The object and magma conversion specifications each print the corresponding argument; they differ only in the printing mode used. The `%o` form uses the default printing mode, while the `%O` form uses the printing mode specified by the next argument (as a string). The “magma” conversion specification uses a printing mode of `Magma`. It is thus equivalent to (but shorter than) using `%O` and an extra argument of `"Magma"`.

For each of these conversion specifications, the object can be printed in a field of a particular width by placing extra characters immediately after the `%` character: digits describing a positive integer, specifying a field with width equal to that number and with right-justification; digits describing a negative integer, specifying a field with width equal to the absolute value of the number and with left-justification; or the character `*` specifying a field width given by the next appropriate expression argument (with justification determined by the sign of the number). This statement is thus like the C language function `printf()`, except that `%o` (and `%O` and `%m`) covers all kinds of objects — it is not necessary to have different conversion specifications for the different types of Magma objects. Note also that this statement does *not* print a newline character after its arguments while the `print` statement does (a `\n` character should be placed in the format string if this is desired). A newline character will be printed just before the next prompt, though, if there is an incomplete line at that point.

### `Example: printf (ex-f268ee)`

The following statements demonstrate simple uses of *printf*.

```magma
> for i := 1 to 150 by 33 do printf "[%3o]\\n", i; end for;
[  1]
[ 34]
[ 67]
[100]
[133]
> for i := 1 to 150 by 33 do printf "[%-3o]\\n", i; end for;
[1  ]
[34 ]
[67 ]
[100]
[133]
> for w := 1 to 5 do printf "[%*o]", w, 1; end for;
[1][ 1][  1][   1][    1]

```

### `Example: printf2 (ex-2f73a2)`

Some further uses of the `printf` statement are illustrated below.

```magma
> x := 3;
> y := 4;
> printf "x = %o, y = %o\\n", x, y;
x = 3, y = 4
> printf "G'"; printf "day";
G'day
> p := 53.211;
> x := 123.2;
> printf "%.3o%% of %.2o is %.3o\\n", p, x, p/100.0 * x;
53.211% of 123.20 is 65.556
> Zx<x> := PolynomialRing(Integers());
> printf "%O\\n", x, "Magma";
Polynomial(\\[0, 1])

```

### `fprintf file, format, expression, ..., expression;`

Print values of the expressions under control of format into the file given by file. The first argument file must be either a string specifying a file which can be opened for appending (tilde expansion is performed on the filename), or a file object (see the section below on external files) opened for writing. The rest of the arguments are exactly as in the `printf` statement. In the string (filename) case, the file is opened for appending, the string obtained from the formatted printing of the other arguments is appended to the file, and the file is closed. In the file object case, the string obtained from the formatted printing of the other arguments is simply appended to the file. Note that this statement, like `printf`, does *not* print a newline character after its arguments (a `\n` character should be placed in the format string if this is desired).

### `Example: fprintf (ex-97d95e)`

The following statements demonstrate a (rather contrived) use of `fprintf` with a file pipe.

```magma
> p := 1000000000000000000000000000057;
> F := POpen("sort -n", "w");
> for i := 100 to 110 do
>    fprintf F, "%30o (2^%o mod p)\\n", 2^i mod p, i;
> end for;
> // Close F and then see output on standard output:
> delete F;
 37107316853453566312041115519 (2^109 mod p)
 70602400912917605986812821219 (2^102 mod p)
 74214633706907132624082231038 (2^110 mod p)
129638414606681695789005139447 (2^106 mod p)
141204801825835211973625642438 (2^103 mod p)
259276829213363391578010278894 (2^107 mod p)
267650600228229401496703205319 (2^100 mod p)
282409603651670423947251284876 (2^104 mod p)
518553658426726783156020557788 (2^108 mod p)
535301200456458802993406410638 (2^101 mod p)
564819207303340847894502569752 (2^105 mod p)

```

## Verbose Printing

The following statements allow convenient printing of information conditioned by whether an appropriate verbose flag is turned on.

### `vprint flag: expression, ..., expression;`

### `vprint flag, n: expression, ..., expression;`

If the verbose flag *flag* (see the function `SetVerbose`) has a level greater than or equal to $n$, print the expressions to the right of the colon exactly as in the `print` statement. If the flag has level 0 (i.e. is not turned on), do nothing. In the first form of this statement, where a specific level is not given, $n$ is taken to be 1. This statement is useful in Magma code found in packages where one wants to print verbose information if an appropriate verbose flag is turned on.

### `vprintf flag: format, expression, ..., expression;`

### `vprintf flag, n: format, expression, ..., expression;`

If the verbose flag *flag* (see the function `SetVerbose`) has a level greater than or equal to $n$, print using the format and the expressions to the right of the colon exactly as in the `printf` statement. If the flag has level 0 (i.e. is not turned on), do nothing. In the first form of this statement, where a specific level is not given, $n$ is taken to be 1. This statement is useful in Magma code found in packages where one wants to print verbose information if an appropriate verbose flag is turned on.

## Automatic Printing

Magma allows *automatic printing* of expressions: basically, a statement consisting of an expression (or list of expressions) alone is taken as a shorthand for the `print`-statement. Some subtleties are involved in understanding the precise behaviour of Magma in interpreting lone expressions as statements. The rules Magma follows are outlined here. In the following, a *call-form* means any expression of the form $f({\rm\sl arguments})$; that is, anything which could be a procedure call *or* a function call.

**(a)**
Any single expression followed by a semicolon which is not a call-form is printed, just as if you had ‘print’ in front of it.

**(b)**
For a single call-form followed by a semicolon (which could be a function call or procedure call), the first signature which matches the input arguments is taken and if that is procedural, the whole call is taken as a procedure call, otherwise it is taken as function call and the results are printed.

**(c)**
A comma-separated list of any expressions is printed, just as if you had ‘print’ in front of it. Here any call-form is taken as a function call only so procedure calls are impossible.

**(d)**
A print level modifier is allowed after an expression list (whether the list has length 1 or more). Again any call-form is taken as a function call only so procedure calls are impossible.

**(e)**
Any list of objects printed, whether by any of the above rules or by the ‘print’ statement, is placed in the previous value buffer. `$1` gives the last printed list, `$2` the one before, etc. Note that multi-return values stay as a list of values in the previous value buffer. The only way to get at the individual values of such a list is by assignment to a list of identifiers, or by `where` (this is of course the only way to get the second result out of `Quotrem`, etc.). In other places, a `$1` expression is evaluated with principal value semantics.

Magma also provides procedures to manipulate the previous value buffer in which $1, etc. are stored.

### `ShowPrevious()`

Show all the previous values stored. This does *not* change the contents of the previous value buffer.

### `ShowPrevious(i): RngIntElt`

Show the $i$-th previous value stored. This does *not* change the contents of the previous value buffer.

### `ClearPrevious()`

Clear all the previous values stored. This is useful for ensuring that no more memory is used than that referred to by the current identifiers.

### `SetPreviousSize(n): RngIntElt`

Set the size of the previous value buffer (this is not how many values are defined in it at the moment, but the maximum number that will be stored). The default size is 3.

### `GetPreviousSize() -> RngIntElt`

Return the size of the previous value buffer.

### `Example: Auto Print (ex-feb63d)`

Examples which illustrate point (a):

```magma
> 1;
1
> x := 3;
> x;
3

```

Examples which illustrate point (b):

```magma
> 1 + 1;            // really function call '+'(1, 1)
2
> Q := [ 0 ];
> Append(~Q, 1);    // first (in fact only) match is procedure call
> Append(Q, 1);     // first (in fact only) match is function call
[ 0, 1, 1 ]
> // Assuming fp is assigned to a procedure or function:
> fp(x);            // whichever fp is at runtime
> SetVerbose("Meataxe", true);  // simple procedure call

```

Examples which illustrate point (c):

```magma
> 1, 2;
1 2
> // Assuming f assigned:
> f(x), 1;                            // f only can be a function
> SetVerbose("Meataxe", true), 1;     // type error in 'SetVerbose'
>                                     // (since no function form)

```

Examples which illustrate point (d):

```magma
> 1: Magma;
1
> Sym(3), []: Maximal;
Symmetric group acting on a set of cardinality 3
Order = 6 = 2 * 3
[]
> SetVerbose("Meataxe", true): Magma; // type error as above

```

Examples which illustrate point (e):

```magma
> 1;
1
> $1;
1
> 2, 3;
2 3
> $1;
2 3
> Quotrem(124124, 123);
1009 17
> $1;
1009 17
> a, b := $1;
> a;
1009

```

## Indentation

Magma has an indentation level which determines how many initial spaces should be printed before each line. The level can be increased or decreased. Each time the top level of Magma is reached (i.e. a prompt is printed), the level is reset to 0. The level is usually changed in verbose output of recursive functions and procedures. The functions `SetIndent` and `GetIndent` are used to control and examine the number of spaces used for each indentation level (default 4).

### `IndentPush()`

Increase (push) the indentation level by 1. Thus the beginning of a line will have $s$ more spaces than before, where $s$ is the current number of indentation spaces.

### `IndentPush(C): RngIntElt`

Increases the indentation level by $C$.

### `IndentPop()`

Decrease (pop) the indentation level by 1. Thus the beginning of a line will have $s$ fewer spaces than before, where $s$ is the current number of indentation spaces. If the current level is already 0, an error occurs.

### `IndentPop(C): RngIntElt`

Decreases the indent level by $C$.

## Printing to a File

### `PrintFile(F, x): MonStgElt, Any`

### `Write(F, x): MonStgElt, Any`

```magma
Overwrite: BoolElt                    Default: false
```

Print $x$ to the file specified by the string $F$. If this file already exists, the output will be appended, unless the optional parameter `Overwrite` is set to true, in which case the file is overwritten.

### `WriteBinary(F, s): MonStgElt, BStgElt`

```magma
Overwrite: BoolElt                    Default: false
```

Write the binary string $s$ to the file specified by the string $F$. If this file already exists, the output will be appended, unless the optional parameter `Overwrite` is set to true, in which case the file is overwritten.

### `PrintFile(F, x, L): MonStgElt, Any, MonStgElt`

### `Write(F, x, L): MonStgElt, Any, MonStgElt`

```magma
Overwrite: BoolElt                    Default: false
```

Print $x$ in format defined by the string $L$ to the file specified by the string $F$. If this file already exists, the output will be appended unless the optional parameter `Overwrite` is set to true, in which case the file is overwritten. The level $L$ can be any of the print levels on the `print` command above (i.e., it must be one of the strings `"Default"`, `"Minimal"`, `"Maximal"`, or `"Magma"`).

### `PrintFileMagma(F, x): MonStgElt, Any`

```magma
Overwrite: BoolElt                    Default: false
```

Print $x$ in Magma format to the file specified by the string $F$. If this file already exists, the output will be appended, unless the optional parameter `Overwrite` is set to true, in which case the file is overwritten.

## Printing to a String

Magma allows the user to obtain the string corresponding to the output obtained when printing an object by means of the `Sprint` function. The `Sprintf` function allows formatted printing like the `printf` statement.

### `Sprint(x): Elt -> MonStgElt`

### `Sprint(x, L): Elt, MonStgElt -> MonStgElt`

Given any Magma object $x$, this function returns a string containing the output obtained when $x$ is printed. If a print level $L$ is given also (a string), the printing is done according to that level (see the `print` statement for the possible printing levels).

### `Sprintf(F, ...): MonStgElt, ... -> MonStgElt`

Given a format string $F$, together with appropriate extra arguments corresponding to $F$, return the string resulting from the formatted printing of $F$ and the arguments. The format string $F$ and arguments should be exactly as for the `printf` statement – see that statement for details.

### `Example: Sprintf (ex-66c7f1)`

We demonstrate elementary uses of `Sprintf`.

```magma
> Q := [Sprintf("{%4o<->%-4o}", x, x): x in [1,10,100,1000]];
> Q;
[ {   1<->1   }, {  10<->10  }, { 100<->100 }, {1000<->1000} ]

```

## Redirecting Output

### `SetOutputFile(F): MonStgElt`

```magma
Overwrite: BoolElt                    Default: false
```

Redirect all Magma output to the file specified by the string $F$. By using `SetOutputFile(F: Overwrite := true)` the file $F$ is emptied before output is written onto it.

### `UnsetOutputFile()`

Close the output file, so that output will be directed to standard output again.

### `HasOutputFile() -> BoolElt`

If Magma currently has an output or log file $F$, return `true` and $F$; otherwise return `false`.
