NAME
samuel - symbolic interactive calculator
SYNOPSIS
samuel [options]
DESCRIPTION
samuel is a simple algebraic calculator based on saml(3), 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) 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) 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) 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) utility to reformat and colorize the output.
- -Q, --rationals
-
Equivalent to -m0 (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 -m1 (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/numberZ. 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) or induce(1). Can be used to create temporary files which are private to this invocation.
- PATH
-
This path is used to spawn induce(1), 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/nZ, 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
AUTHOR
Thierry Bousch ([email protected])