---
name: "samuel"
section: "1"
platform: "linux"
package: "saml"
version: "970418-9"
release: "Debian 3.0 (Woody)"
platforms: ["linux"]
url: "https://new.carta.tech/samuel"
---

# samuel(1)

symbolic interactive calculator

## NAME

samuel - symbolic interactive calculator

## SYNOPSIS

**samuel** \[*options*\]

## DESCRIPTION

**samuel** is a simple algebraic calculator based on [**saml**(3)](/saml/3.md), the Simple Algebraic Math Library. It can be used interactively or, conversely, as a filter, so you can build shell scripts around it. The input can contain any of the following:

- **??**

  Lists all variables. The associated mref number is written in parentheses.

- *expr***;**

  The expression is evaluated, and printed on standard output (unless it is an assignment). It is also stored in the special variable *last*. This variable will be clobbered by the next expression. Assignments are a special case of expressions, and are described below. All expressions must be semicolon-terminated.

- **\<“***filename***”**

  Include (source) a file. From this point, **samuel** will read from the file indicated, and tokenize the input using the same rules as before. When an end-of-file condition is detected, **samuel** closes the file and reverts to the previous input stream. You can have up to 9 nested includes, that is, 10 input streams opened at once (including stdin).

### Expressions

An *expr* can be any of the following:

- *integer*

  Any sequence of decimal digits; thus, always non-negative. They can be as big as you want.

- **\\***literal*

  An identifier preceded by a backslash represents a literal. In some cases, the backslash can be omitted; see the discussion below.

- **?***variable*

  Read the value of a variable. In some cases, the question mark can be omitted, see below. If no such variable exists, an error is returned.

- **^***variable*

  The current value of *variable* is returned, and then the variable is destroyed. If there was no variable with this name, an error is returned.

- *identifier*

  Return the value of the identifier. There is some magic involved here. In "normal" mode, the identifier is assumed to be a variable if there is one with this name, and a literal otherwise; moreover, subscripted identifiers will be handed to the [**induce**(1)](/induce/1.md) program, unless the option **-i** has been chosen. In "explicit-variables" mode, a naked identifier will always be interpreted as a literal.

- *tensorid***!***number*

  Defines a tensor of order one with one coordinate (this will work only if you have enabled tensors via the **-t** option; otherwise, you'll get type conflict errors very quickly). You can add and multiply these basic blocks to obtain tensors of any order. The *tensorid* can be any identifier (even bracketed or subscripted) and the *number* must be a small non-negative integer representing the coordinate number.

- *lvalue* **=** *expr*

  The value of *expr* is stored into the *lvalue* and returned; as in C, assignments are a special case of expressions. The *lvalue* can be a *variable* (if no such variable existed, it is created, otherwise the previous value is overwritten), but also a *file* or a *pipe*, with similar semantics:

- **“*filename*”** and **“\|*command*”**

  Any sequence of characters between double quotes. It is assumed to be a *pipe* if the first character is a \`**\|**', and a *file* otherwise. If they appear in the right-hand side of an expression, the file (or the output of the command) is read and parsed, and some value is returned. If they appear as the left-hand side of an assignment, the value of the right-hand side will be copied into the file or the pipe.

- *function***(***expr***,** *expr...***)**

  A *function* can be any C identifier; the arguments are evaluated, and are passed as command-line arguments to the external program called \`**fn\_***function*' (it must be in your path). The output of the program is then read and parsed, and some value is returned. For instance, \`foo(-n,x+1)' is equivalent to

  ```
      "|fn_foo '-n' '+1+x'"
  ```

  in an expression. The program fn\_foo can be anything, but you should be extremely careful if it is a shell script; for instance, echo "$1" will not give \`-n' (as you might expect) in this example.

- *expr bop expr*

  Where *bop* can be any of \`**+**' (addition), \`**-**' (substraction), \`**\***' or \`**.**' (multiplication), \`**/**' (division), \`**&**' (greatest common divisor). The result of the operation is returned.

- *uop expr*

  Where *uop* can be \`**+**' or \`**-**'.

- **(***expr***,** *subst***,** *subst...***)**

  Applies a list of substitutions to *expr*. Each substitution has the form \`*unary to expr*', where *unary* is any expression which evaluates to a unary monomial, and *to* is either \`**-\>**' for a simple substitution, or \`**\>\>**' for a repeated substitution (we apply it until we reach a fixed point); for instance \`x^2.y **-\>** (x-z)\*2' is a valid substitution. The list of substitutions can be empty, in this case you simply get the value of the parenthesised expression.

  Another kind of substitution, which only applies to tensors, is \`*tensorid1* **=\>** *tensorid2*'; it maps the first *tensorid* to the second one, maybe causing a contraction. If the first tensorid doesn't appear in *expr*, an error is returned.

- *expr***^***number*

  Raises the expression to a non-negative power. Feature: 0**^**0 returns one.

- *expr***:***elit*

  Differentiates *expr* with respect to *elit*, where *elit* is any expression which evaluates to a literal.

- **~***elit***(***expr***,***expr***)**

  Returns the resultant of the two polynomials with respect to *elit*; this can be used to eliminate a literal between two equations.

- **\|** *expr***,** *expr...* **\|**

  The number of expressions between the bars must be a perfect square. If there are *n*^2 of them, **samuel** will consider them as the elements of a *n*\**n* matrix, and will return the determinant of this matrix.

- *expr* **~~ (***expr***,***elit***)**

  Computes the remainder of the first expression modulo the second one, with respect to some literal. For now, this construction is only syntactic sugar for **modulo(***E1***,***E2***,***L***)** so it will fail if **fn\_modulo** is not in your path.

### Precedence of Operators

All operators are left-associative, except the assignment which is right-associative. Here is the list of priorities, from the highest to the lowest:

- (1)

  power \`**^**' and derivation \`**:**';

- (2)

  unary plus and minus;

- (3)

  multiplication and division;

- (4)

  binary plus and minus;

- (5)

  greatest common divisor \`**&**';

- (6)

  modulo \`**~~**'

- (7)

  assignment \`**=**'.

### Interpolation of subscripted identifiers

Samuel accepts three kinds of identifiers:

- (1)

  C identifiers, i.e., any sequence of letters, digits and underscores, the first character being a non-digit.

- (2)

  Subscripted C identifiers; as above, followed by a comma-separated list of integers between brackets, like \`foo\_bar\[-1,3\]'.

- (3)

  Bracketed identifiers, a la FORM: any sequence of characters between brackets; opening and closing brackets must match, like \`\[foo\[bar\]+2\]'.

Without the **-i** and **-e** options, subscripted C identifiers are handed to the [**induce**(1)](/induce/1.md) program. They will be replaced ("interpolated") in the input stream by the appropriate pipe. For instance, the following substitution would take place:

```
    foo[-1,3] --> "|induce -q foo[-1,3]"
```

Note that it only affects "naked" identifiers, i.e. not preceded by a backslash or a question mark (nor in the LHS of an assignment); still, this behaviour can be undesirable; you can disable it with the **-i** option.

Interpolation is also disabled in "explicit-variables" mode, i.e., when the **-e** option is set. You don't want this kind of magic in batch mode, for obvious reliability reasons.

### Variables and Literals

It is perfectly possible for a variable and a literal to have the same name, so there must be some way to distinguish them. You can prepend a **\\** or a **?** before every identifier to remove ambiguity, but usually it's not needed; the naked identifier will be "correctly" interpreted. This interpretation depends on the mode **samuel** is running in:

- (1)

  Normal mode. If the identifier contains subscripts, it will be interpolated. Otherwise, if there's a variable with this name, its value will be returned. Otherwise, it's assumed to be a literal.

- (2)

  Normal mode without interpolation. This is what you get with the **-i** option. Like (1) but with interpolation disabled.

- (3)

  Explicit-variables mode. Activated by the **-e** option. A naked identifier will *always* represent a literal. This is the only way to ensure that **samuel** will run in a reliable and deterministic way with expressions containing arbitrary literals. Without this precaution, there might be name clashes between literals and temporary variables.

## OPTIONS

- **-b**, **--batch**

  Batch mode; this is equivalent to **-eq**.

- **-e**, **--explicit-variables**

  Enter "explicit-variables" mode. See above. In some sense, this option implies **-i**.

- **-i**, **--no-induce**

  Disable interpolation of subscripted names.

- **-q**, **--quiet**

  Quiet mode; this is the default mode when the standard output is not a tty. Only error messages will be written to stderr.

- **-v**, **--verbose**

  Verbose mode; this is the default mode when the standard output is a tty.

- **--help**, **--usage**

  Prints a small usage summary on standard output, and exits successfully.

- **--version**, **--copyright**

  Prints the **samuel** version string, a copyright message, and exits successfully. This manpage documents version 1.10. A version string ending with "r" means that **samuel** has been compiled with [**readline**(3)](/readline/3.md) support.

- **--post***,* **--post-processor** *program*

  Instead of displaying expressions on standard output, post-process them through *program*, where *program* is any string which means something for the shell; it will be executed for each displayed expression. You can for instance use the [**colorize**(1)](/colorize/1.md) utility to reformat and colorize the output.

- **-Q**, **--rationals**

  Equivalent to **-m***0* (see below). With this option, **samuel** works on polynomials with rational coefficients. This mode is the default when the environment variable **MODULUS** is not set.

- **-Z**, **--integers**

  Equivalent to **-m***1* (see below). If this option is specified, **samuel** will use polynomials with integer coefficients. This modifies the semantics of some operations: divisions will truncate their results (towards zero), and gcd's will be computed over Z\[X1...Xn\] instead of Q\[X1...Xn\], so the results can differ by a multiplicative constant. In particular, the gcd of two constant polynomials will be the gcd of the constants (as one might expect), whereas it would be 1 over the rationals.

- **-m**, **--modulo** *number*

  If *number* is an integer greater than one, all calculations will be made modulo this integer, i.e., polynomials have their coefficients in Z/*number*Z. The special values 0 and 1 mean that the base ring is Q or Z, respectively. The modulus cannot exceed 2^32-1; greater moduli will be (silently) clamped to this value. See also the BUGS section.

- **-c, --condition** *X***,***A0***,***A1...An*

  Take the coefficients in K\[X\]/(*P*) where *P* is the polynomial with integer coefficients *A0...An*. An element of the splitting field like 3+X-X^2 will be written as (3,1,-1). The unfortunate thing is that **samuel** can *not* parse this notation. Also, you can't have more than one condition.

- **-r**, **--rational-functions**

  It does not work yet. Don't use.

- **-t**, **--tensors**

  With this option, **samuel** will use tensors with polynomial coordinates instead of polynomials. This option is orthogonal to the previous ones, which simply select the type of the coefficients of polynomials.

- **-n**, **--nice** *adjust*

  Adds *adjust* to the niceness of the process, as symbolic calculations can be very CPU-intensive.

- **--sparse**

  Use polynomials of type ST\_POLY; this can be more efficient when the set of literals is very sparse.

- **--dense**

  Use polynomials of type ST\_APOLY. This is the default, and usually more efficient than ST\_POLY. It assumes, however, that the set of literals in each polynomial is reasonably dense.

## ENVIRONMENT

The following variables are relevant to **samuel**:

- **MODULUS**

  Contains the default modulus; if this variable doesn't exist, the default modulus is 0. This variable is set by **samuel** and inherited by all its subprocesses. Therefore, it is possible to call **samuel** recursively and have the same modulus in all its invocations.

- **LITERALS**

  This variable, if present, can contain either *dense* or *sparse* (other values are ignored) and overrides the builtin preference (dense) between dense and sparse polynomials. It will be overriden by the corresponding command-line options. Here again, this variable is set by samuel and inherited by all its subprocesses.

- **SPID**

  Contains the process id of the latest invocation of [**samuel**(1)](/samuel/1.md) or [**induce**(1)](/induce/1.md). Can be used to create temporary files which are private to this invocation.

- **PATH**

  This path is used to spawn [**induce**(1)](/induce/1.md), commands in pipes, and external functions.

## EXIT CODE

**samuel** returns 2 on usage errors, 1 if the input contained syntax errors, and 0 otherwise. Run-time errors are *not* reported.

## BUGS

The lexer is too laxist about identifiers; it shouldn't allow bracketed literals containing whitespace or nested brackets. If you save an expression containing such an identifier into a file, **samuel** will be unable to reread this file.

Divisions in Z/*n*Z, with *n* a composite number, are almost guaranteed to return rubbish. Also, **samuel** should issue a warning (or more) when the modulus is out of range, instead of clamping it silently.

There should be a way to trap SIGINT so that you could kill a child process with **^C** without killing **samuel** at the same time. For now, you have to switch to another tty (or suspend **samuel**) and kill the subprocess.

## SEE ALSO

[**colorize**(1)](/colorize/1.md), [**induce**(1)](/induce/1.md), [**readline**(3)](/readline/3.md), [**saml**(3)](/saml/3.md)

## AUTHOR

Thierry Bousch (bousch@topo.math.u-psud.fr)
