# Operators

## nary

An `nary` operator is used to denote a function of any number of arguments, each of which is separated by an occurrence of the operator, e.g. A+B or A+B+C. The `nary("x")` function is a syntax extension function to declare x to be an `nary` operator. Functions may be declared to be `nary`. If `declare(j,nary);` is done, this tells the simplifier to simplify, e.g. `j(j(a,b),j(c,d))` to `j(a, b, c, d)`.

See also `syntax`.

## nofix

`nofix` operators are used to denote functions of no arguments. The mere presence of such an operator in a command will cause the corresponding function to be evaluated. For example, when one types "exit;" to exit from a Maxima break, "exit" is behaving similar to a `nofix` operator. The function `nofix("x")` is a syntax extension function which declares x to be a `nofix` operator.

See also `syntax`.

## operator

See `operators`.

## postfix

`postfix` operators like the `prefix` variety denote functions of a single argument, but in this case the argument immediately precedes an occurrence of the operator in the input string, e.g. 3! . The `postfix("x")` function is a syntax extension function to declare x to be a `postfix` operator.

See also `syntax`.

## prefix

A `prefix` operator is one which signifies a function of one argument, which argument immediately follows an occurrence of the operator. `prefix("x")` is a syntax extension function to declare x to be a `prefix` operator.

See also `syntax`.

## Definitions for Operators

Operator: "!"
The factorial operator. For any complex number `x` (including integer, rational, and real numbers) except for negative integers, `x!` is defined as `gamma(x+1)`.

For an integer `x`, `x!` simplifies to the product of the integers from 1 to `x` inclusive. `0!` simplifies to 1. For a floating point number `x`, `x!` simplifies to the value of `gamma (x+1)`. For `x` equal to `n/2` where `n` is an odd integer, `x!` simplifies to a rational factor times `sqrt (%pi)` (since `gamma (1/2)` is equal to `sqrt (%pi)`). If `x` is anything else, `x!` is not simplified.

The variables `factlim`, `minfactorial`, and `factcomb` control the simplification of expressions containing factorials.

The functions `gamma`, `bffac`, and `cbffac` are varieties of the gamma function. `makegamma` substitutes `gamma` for factorials and related functions.

See also `binomial`.

• The factorial of an integer, half-integer, or floating point argument is simplified unless the operand is greater than `factlim`.
```(%i1) factlim: 10\$
(%i2) [0!, (7/2)!, 4.77!, 8!, 20!];
105 sqrt(%pi)
(%o2) [1, -------------, 81.44668037931193, 40320, 20!]
16
```
• The factorial of a complex number, known constant, or general expression is not simplified. Even so it may be possible simplify the factorial after evaluating the operand.
```(%i1) [(%i + 1)!, %pi!, %e!, (cos(1) + sin(1))!];
(%o1)    [(%i + 1)!, %pi!, %e!, (sin(1) + cos(1))!]
(%i2) ev (%, numer, %enumer);
(%o2) [(%i + 1)!, 7.188082728976031, 4.260820476357003,

1.227580202486819]
```
• The factorial of an unbound symbol is not simplified.
```(%i1) kill (foo)\$
(%i2) foo!;
(%o2)                       foo!
```
• Factorials are simplified, not evaluated. Thus `x!` may be replaced even in a quoted expression.
```(%i1) '([0!, (7/2)!, 4.77!, 8!, 20!]);
105 sqrt(%pi)
(%o1) [1, -------------, 81.44668037931193, 40320, 20!]
16
```

Operator: "!!"
The double factorial operator.

For an integer, float, or rational number `n`, `n!!` evaluates to the product `n (n-2) (n-4) (n-6) ... (n - 2 (k-1))` where `k` is equal to `entier (n/2)`, that is, the largest integer less than or equal to `n/2`. Note that this definition does not coincide with other published definitions for arguments which are not integers.

For an even (or odd) integer `n`, `n!!` evaluates to the product of all the consecutive even (or odd) integers from 2 (or 1) through `n` inclusive.

For an argument `n` which is not an integer, float, or rational, `n!!` yields a noun form `genfact (n, n/2, 2)`.

Operator: "#"
Represents the negation of syntactic equality `=`.

Note that because of the rules for evaluation of predicate expressions (in particular because `not expr` causes evaluation of expr), `not a = b` is not equivalent to `a # b` in some cases.

Examples:

```(%i1) a = b;
(%o1)                         a = b
(%i2) is (a = b);
(%o2)                         false
(%i3) a # b;
(%o3)                         a # b
(%i4) not a = b;
(%o4)                         true
(%i5) is (a # b);
(%o5)                         true
(%i6) is (not a = b);
(%o6)                         true
```

Operator: "."
The dot operator, for matrix (non-commutative) multiplication. When "." is used in this way, spaces should be left on both sides of it, e.g. A . B. This distinguishes it plainly from a decimal point in a floating point number.

See also `dot`, `dot0nscsimp`, `dot0simp`, `dot1simp`, `dotassoc`, `dotconstrules`, `dotdistrib`, `dotexptsimp`, `dotident`, and `dotscrules`.

Operator: ":"
The assignment operator. E.g. A:3 sets the variable A to 3.

Operator: "::"
Assignment operator. :: assigns the value of the expression on its right to the value of the quantity on its left, which must evaluate to an atomic variable or subscripted variable.

Operator: "::="
The "::=" is used instead of ":=" to indicate that what follows is a macro definition, rather than an ordinary functional definition. See `macros`.

Operator: ":="
The function definition operator. E.g. `f(x):=sin(x)` defines a function `f`.

Operator: "="
denotes an equation to Maxima. To the pattern matcher in Maxima it denotes a total relation that holds between two expressions if and only if the expressions are syntactically identical.

The negation of `=` is represented by `#`. Note that because of the rules for evaluation of predicate expressions (in particular because `not expr` causes evaluation of expr), `not a = b` is not equivalent to `a # b` in some cases.

Operator: and
The logical conjunction operator. `and` is an n-ary infix operator; its operands are Boolean expressions, and its result is a Boolean value.

`and` forces evaluation (like `is`) of one or more operands, and may force evaluation of all operands.

Operands are evaluated in the order in which they appear. `and` evaluates only as many of its operands as necessary to determine the result. If any operand is `false`, the result is `false` and no further operands are evaluated.

The global flag `prederror` governs the behavior of `and` when an evaluated operand cannot be determined to be `true` or `false`. `and` prints an error message when `prederror` is `true`. Otherwise, `and` returns `unknown`.

`and` is not commutative: `a and b` might not be equal to `b and a` due to the treatment of indeterminate operands.

Operator: or
The logical disjunction operator. `or` is an n-ary infix operator; its operands are Boolean expressions, and its result is a Boolean value.

`or` forces evaluation (like `is`) of one or more operands, and may force evaluation of all operands.

Operands are evaluated in the order in which they appear. `or` evaluates only as many of its operands as necessary to determine the result. If any operand is `true`, the result is `true` and no further operands are evaluated.

The global flag `prederror` governs the behavior of `or` when an evaluated operand cannot be determined to be `true` or `false`. `or` prints an error message when `prederror` is `true`. Otherwise, `or` returns `unknown`.

`or` is not commutative: `a or b` might not be equal to `b or a` due to the treatment of indeterminate operands.

Operator: not
The logical negation operator. `not` is a prefix operator; its operand is a Boolean expression, and its result is a Boolean value.

`not` forces evaluation (like `is`) of its operand.

The global flag `prederror` governs the behavior of `not` when its operand cannot be determined to be `true` or `false`. `not` prints an error message when `prederror` is `true`. Otherwise, `not` returns `unknown`.

Function: abs (expr)
Returns the absolute value expr. If expr is complex, returns the complex modulus of expr.

If `declare(f,additive)` has been executed, then:

(1) If `f` is univariate, whenever the simplifier encounters `f` applied to a sum, `f` will be distributed over that sum. I.e. `f(y+x)` will simplify to `f(y)+f(x)`.

(2) If `f` is a function of 2 or more arguments, additivity is defined as additivity in the first argument to `f`, as in the case of `sum` or `integrate`, i.e. `f(h(x)+g(x),x)` will simplify to `f(h(x),x)+f(g(x),x)`. This simplification does not occur when `f` is applied to expressions of the form `sum(x[i],i,lower-limit,upper-limit)`.

Keyword: allbut
works with the `part` commands (i.e. `part`, `inpart`, `substpart`, `substinpart`, `dpart`, and `lpart`). For example,

```(%i1) expr: e+d+c+b+a\$
(%i2) part (expr, [2, 5]);
(%o2)                         d + a
```

while

```(%i3) part (expr, allbut (2, 5));
(%o3)                       e + c + b
```

It also works with the `kill` command,

```kill (allbut (name_1, ..., name_k))
```

will do a `kill (all)` except it will not `kill` the names specified. Note: `name_i` means a name such as function name such as `u`, `f`, `foo`, or `g`, not an infolist such as `functions`.

Declaration: antisymmetric
If `declare(h,antisymmetric)` is done, this tells the simplifier that `h` is antisymmetric. E.g. `h(x,z,y)` will simplify to `- h(x, y, z)`. That is, it will give (-1)^n times the result given by `symmetric` or `commutative`, where n is the number of interchanges of two arguments necessary to convert it to that form.

Function: cabs (expr)
Returns the complex absolute value (the complex modulus) of expr.

Declaration: commutative
If `declare(h,commutative)` is done, this tells the simplifier that `h` is a commutative function. E.g. `h(x,z,y)` will simplify to `h(x, y, z)`. This is the same as `symmetric`.

Function: entier (x)
Returns the largest integer less than or equal to x where x is numeric. `fix` (as in `fixnum`) is a synonym for this, so `fix(x)` is precisely the same.

Function: equal (expr_1, expr_2)
Used with an `is`, returns `true` (or `false`) if and only if expr_1 and expr_2 are equal (or not equal) for all possible values of their variables (as determined by `ratsimp`). Thus `is (equal ((x + 1)^2, x^2 + 2*x + 1))` returns `true` whereas if `x` is unbound `is ((x + 1)^2 = x^2 + 2*x + 1)` returns `false`. Note also that `is(rat(0)=0)` yields `false` but `is (equal (rat(0), 0))` yields `true`.

If a determination can't be made, then `is (equal (a, b))` returns a simplified but equivalent expression, whereas `is (a=b)` always returns either `true` or `false`.

All variables occurring in expr_1 and expr_2 are presumed to be real valued.

The negation of `equal` is `notequal`. Note that because of the rules for evaluation of predicate expressions (in particular because `not expr` causes evaluation of expr), `notequal` is not equivalent to `not equal` in some cases.

`ev (expr, pred)` is equivalent to `is (expr)`.

```(%i1) is (x^2 >= 2*x - 1);
(%o1)                         true
(%i2) assume (a > 1);
(%o2)                        [a > 1]
(%i3) is (log (log (a+1) + 1) > 0 and a^2 + 1 > 2*a);
(%o3)                         true
```

Function: notequal (expr_1, expr_2)
Represents the negation of `equal (expr_1, expr_2)`.

Note that because of the rules for evaluation of predicate expressions (in particular because `not expr` causes evaluation of expr), `notequal` is not equivalent to `not equal` in some cases.

Examples:

```(%i1) equal (a, b);
(%o1)                      equal(a, b)
(%i2) maybe (equal (a, b));
(%o2)                        unknown
(%i3) notequal (a, b);
(%o3)                    notequal(a, b)
(%i4) not equal (a, b);
`macsyma' was unable to evaluate the predicate:
equal(a, b)
-- an error.  Quitting.  To debug this try debugmode(true);
(%i5) maybe (notequal (a, b));
(%o5)                        unknown
(%i6) maybe (not equal (a, b));
(%o6)                        unknown
(%i7) assume (a > b);
(%o7)                        [a > b]
(%i8) equal (a, b);
(%o8)                      equal(a, b)
(%i9) maybe (equal (a, b));
(%o9)                         false
(%i10) notequal (a, b);
(%o10)                   notequal(a, b)
(%i11) not equal (a, b);
(%o11)                        true
(%i12) maybe (notequal (a, b));
(%o12)                        true
(%i13) maybe (not equal (a, b));
(%o13)                        true
```

Operator: eval
As an argument in a call to `ev (expr)`, `eval` causes an extra evaluation of expr. See `ev`.

Function: evenp (expr)
Returns `true` if expr is an even integer. `false` is returned in all other cases.

Function: fix (x)
A synonym for `entier (x)`.

Function: fullmap (f, expr_1, ...)
Similar to `map`, but `fullmap` keeps mapping down all subexpressions until the main operators are no longer the same.

`fullmap` is used by the Maxima simplifier for certain matrix manipulations; thus, Maxima sometimes generates an error message concerning `fullmap` even though `fullmap` was not explicitly called by the user.

```(%i1) a + b*c\$
(%i2) fullmap (g, %);
(%o2)                   g(b) g(c) + g(a)
(%i3) map (g, %th(2));
(%o3)                     g(b c) + g(a)
```

Function: fullmapl (f, list_1, ...)
Similar to `fullmap`, but `fullmapl` only maps onto lists and matrices.

```(%i1) fullmapl ("+", [3, [4, 5]], [[a, 1], [0, -1.5]]);
(%o1)                [[a + 3, 4], [4, 3.5]]
```

Function: is (expr)
Attempts to determine whether the predicate expr is provable from the facts in the `assume` database.

If the predicate is provably `true` or `false`, `is` returns `true` or `false`, respectively. Otherwise, the return value is controlled by the global flag `prederror`. When `prederror` is `false`, `is` returns `unknown` for a predicate which cannot be proven nor disproven, and reports an error otherwise.

See also `assume`, `facts`, and `maybe`.

Examples:

`is` causes evaluation of predicates.

```(%i1) %pi > %e;
(%o1)                       %pi > %e
(%i2) is (%pi > %e);
(%o2)                         true
```

`is` attempts to derive predicates from the `assume` database.

```(%i1) assume (a > b);
(%o1)                        [a > b]
(%i2) assume (b > c);
(%o2)                        [b > c]
(%i3) is (a < b);
(%o3)                         false
(%i4) is (a > c);
(%o4)                         true
(%i5) is (equal (a, c));
(%o5)                         false
```

If `is` can neither prove nor disprove a predicate from the `assume` database, the global flag `prederror` governs the behavior of `is`.

```(%i1) assume (a > b);
(%o1)                        [a > b]
(%i2) prederror: true\$
(%i3) is (a > 0);
`macsyma' was unable to evaluate the predicate:
a > 0
-- an error.  Quitting.  To debug this try debugmode(true);
(%i4) prederror: false\$
(%i5) is (a > 0);
(%o5)                        unknown
```

Function: maybe (expr)
Attempts to determine whether the predicate expr is provable from the facts in the `assume` database.

If the predicate is provably `true` or `false`, `maybe` returns `true` or `false`, respectively. Otherwise, `maybe` returns `unknown`.

`maybe` is functionally equivalent to `is` with `prederror: false`, but the result is computed without actually assigning a value to `prederror`.

See also `assume`, `facts`, and `is`.

Examples:

```(%i1) maybe (x > 0);
(%o1)                        unknown
(%i2) assume (x > 1);
(%o2)                        [x > 1]
(%i3) maybe (x > 0);
(%o3)                         true
```

Function: isqrt (x)
Returns the "integer square root" of the absolute value of x, which is an integer.

Function: max (x_1, x_2, ...)
Returns the maximum of its arguments (or returns a simplified form if some of its arguments are non-numeric).

Function: min (x_1, x_2, ...)
Returns the minimum of its arguments (or returns a simplified form if some of its arguments are non-numeric).

Function: mod (p)
Function: mod (p, m)
Converts the polynomial p to a modular representation with respect to the current modulus which is the value of the variable `modulus`.

`mod (p, m)` specifies a modulus m to be used instead of the current value of `modulus`.

See `modulus`.

Function: oddp (expr)
is `true` if expr is an odd integer. `false` is returned in all other cases.

Operator: pred
As an argument in a call to `ev (expr)`, `pred` causes predicates (expressions which evaluate to `true` or `false`) to be evaluated. See `ev`.

Function: make_random_state (n)
Function: make_random_state (s)
Function: make_random_state (true)
Function: make_random_state (false)

A random state object represents the state of the random number generator. The state comprises 627 32-bit words.

`make_random_state (n)` returns a new random state object created from an integer seed value equal to n modulo 2^32. n may be negative.

`make_random_state (s)` returns a copy of the random state s.

`make_random_state (true)` returns a new random state object, using the current computer clock time as the seed.

`make_random_state (false)` returns a copy of the current state of the random number generator.

Function: set_random_state (s)
Copies s to the random number generator state.

`set_random_state` always returns `done`.

Function: random (x)
Returns a pseudorandom number. If x is an integer, `random (x)` returns an integer from 0 through `x - 1` inclusive. If x is a floating point number, `random (x)` returns a nonnegative floating point number less than x. `random` complains with an error if x is neither an integer nor a float, or if x is not positive.

The functions `make_random_state` and `set_random_state` maintain the state of the random number generator.

The Maxima random number generator is an implementation of the Mersenne twister MT 19937.

Examples:

```(%i1) s1: make_random_state (654321)\$
(%i2) set_random_state (s1);
(%o2)                         done
(%i3) random (1000);
(%o3)                          768
(%i4) random (9573684);
(%o4)                        7657880
(%i5) random (2^75);
(%o5)                11804491615036831636390
(%i6) s2: make_random_state (false)\$
(%i7) random (1.0);
(%o7)                   .2310127244107132
(%i8) random (10.0);
(%o8)                   4.394553645870825
(%i9) random (100.0);
(%o9)                   32.28666704056853
(%i10) set_random_state (s2);
(%o10)                        done
(%i11) random (1.0);
(%o11)                  .2310127244107132
(%i12) random (10.0);
(%o12)                  4.394553645870825
(%i13) random (100.0);
(%o13)                  32.28666704056853
```

Function: sign (expr)
Attempts to determine the sign of expr on the basis of the facts in the current data base. It returns one of the following answers: `pos` (positive), `neg` (negative), `zero`, `pz` (positive or zero), `nz` (negative or zero), `pn` (positive or negative), or `pnz` (positive, negative, or zero, i.e. nothing known).

Function: signum (x)
For numeric x, returns 0 if x is 0, otherwise returns -1 or +1 as x is less than or greater than 0, respectively.

If x is not numeric then a simplified but equivalent form is returned. For example, `signum(-x)` gives `-signum(x)`.

Function: sort (list, p)
Function: sort (list)
Sorts list according to a predicate `p` of two arguments, such as `"<"` or `orderlessp`.

`sort (list)` sorts list according to Maxima's built-in ordering.

list may contain numeric or nonnumeric items, or both.

Function: sqrt (x)
The square root of x. It is represented internally by `x^(1/2)`. See also `rootscontract`.

`radexpand` if `true` will cause nth roots of factors of a product which are powers of n to be pulled outside of the radical, e.g. `sqrt(16*x^2)` will become `4*x` only if `radexpand` is `true`.

Option variable: sqrtdispflag
Default value: `true`

When `sqrtdispflag` is `false`, causes `sqrt` to display with exponent 1/2.

Function: sublis (list, expr)
Makes multiple parallel substitutions into an expression.

The variable `sublis_apply_lambda` controls simplification after `sublis`.

Example:

```(%i1) sublis ([a=b, b=a], sin(a) + cos(b));
(%o1)                    sin(b) + cos(a)
```

Function: sublist (list, p)
Returns the list of elements of list for which the predicate `p` returns `true`.

Example:

```(%i1) L: [1, 2, 3, 4, 5, 6]\$
(%i2) sublist (L, evenp);
(%o2)                       [2, 4, 6]
```

Option variable: sublis_apply_lambda
Default value: `true` - controls whether `lambda`'s substituted are applied in simplification after `sublis` is used or whether you have to do an `ev` to get things to apply. `true` means do the application.

Function: subst (a, b, c)
Substitutes a for b in c. b must be an atom or a complete subexpression of c. For example, `x+y+z` is a complete subexpression of `2*(x+y+z)/w` while `x+y` is not. When b does not have these characteristics, one may sometimes use `substpart` or `ratsubst` (see below). Alternatively, if b is of the form `e/f` then one could use `subst (a*f, e, c)` while if b is of the form `e^(1/f)` then one could use `subst (a^f, e, c)`. The `subst` command also discerns the `x^y` in `x^-y` so that `subst (a, sqrt(x), 1/sqrt(x))` yields `1/a`. a and b may also be operators of an expression enclosed in double-quotes `"` or they may be function names. If one wishes to substitute for the independent variable in derivative forms then the `at` function (see below) should be used.

`subst` is an alias for `substitute`.

`subst (eq_1, expr)` or `subst ([eq_1, ..., eq_k], expr)` are other permissible forms. The eq_i are equations indicating substitutions to be made. For each equation, the right side will be substituted for the left in the expression expr.

`exptsubst` if `true` permits substitutions like `y` for `%e^x` in `%e^(a*x)` to take place.

When `opsubst` is `false`, `subst` will not attempt to substitute into the operator of an expression. E.g. `(opsubst: false, subst (x^2, r, r+r[0]))` will work.

Examples:

```(%i1) subst (a, x+y, x + (x+y)^2 + y);
2
(%o1)                      y + x + a
(%i2) subst (-%i, %i, a + b*%i);
(%o2)                       a - %i b
```

For further examples, do `example (subst)`.

Function: substinpart (x, expr, n_1, ..., n_k)
Similar to `substpart`, but `substinpart` works on the internal representation of expr.

```(%i1) x . 'diff (f(x), x, 2);
2
D
(%o1)                    x . -- (f(x))
2
dx
(%i2) substinpart (d^2, %, 2);
2
(%o2)                        x . d
(%i3) substinpart (f1, f[1](x+1), 0);
(%o3)                       f1(x + 1)
```

If the last argument to a part function is a list of indices then several subexpressions are picked out, each one corresponding to an index of the list. Thus

```(%i1) part (x+y+z, [1, 3]);
(%o1)                         z + x
```

`piece` holds the value of the last expression selected when using the part functions. It is set during the execution of the function and thus may be referred to in the function itself as shown below. If `partswitch` is set to `true` then `end` is returned when a selected part of an expression doesn't exist, otherwise an error message is given.

```(%i1) expr: 27*y^3 + 54*x*y^2 + 36*x^2*y + y + 8*x^3 + x + 1;
3         2       2            3
(%o1)     27 y  + 54 x y  + 36 x  y + y + 8 x  + x + 1
(%i2) part (expr, 2, [1, 3]);
2
(%o2)                         54 y
(%i3) sqrt (piece/54);
(%o3)                        abs(y)
(%i4) substpart (factor (piece), expr, [1, 2, 3, 5]);
3
(%o4)               (3 y + 2 x)  + y + x + 1
(%i5) expr: 1/x + y/x - 1/z;
1   y   1
(%o5)                      - - + - + -
z   x   x
(%i6) substpart (xthru (piece), expr, [2, 3]);
y + 1   1
(%o6)                       ----- - -
x     z
```

Also, setting the option `inflag` to `true` and calling `part` or `substpart` is the same as calling `inpart` or `substinpart`.

Function: substpart (x, expr, n_1, ..., n_k)
Substitutes x for the subexpression picked out by the rest of the arguments as in `part`. It returns the new value of expr. x may be some operator to be substituted for an operator of expr. In some cases x needs to be enclosed in double-quotes `"` (e.g. `substpart ("+", a*b, 0)` yields `b + a`).

```(%i1) 1/(x^2 + 2);
1
(%o1)                        ------
2
x  + 2
(%i2) substpart (3/2, %, 2, 1, 2);
1
(%o2)                       --------
3/2
x    + 2
(%i3) a*x + f (b, y);
(%o3)                     a x + f(b, y)
(%i4) substpart ("+", %, 1, 0);
(%o4)                    x + f(b, y) + a
```

Also, setting the option `inflag` to `true` and calling `part` or `substpart` is the same as calling `inpart` or `substinpart`.

Function: subvarp (expr)
Returns `true` if expr is a subscripted variable, for example `a[i]`.

Function: symbolp (expr)
Returns `true` if expr is a symbol, else `false`. In effect, `symbolp(x)` is equivalent to the predicate `atom(x) and not numberp(x)`.

See also `Identifiers`.

Function: unorder ()
Disables the aliasing created by the last use of the ordering commands `ordergreat` and `orderless`. `ordergreat` and `orderless` may not be used more than one time each without calling `unorder`. See also `ordergreat` and `orderless`.

```(%i1) unorder();
(%o1)                          []
(%i2) b*x + a^2;
2
(%o2)                       b x + a
(%i3) ordergreat (a);
(%o3)                         done
(%i4) b*x + a^2;
2
(%o4)                       a  + b x
(%i5) %th(1) - %th(3);
2    2
(%o5)                        a  - a
(%i6) unorder();
(%o6)                          [a]
```

Function: vectorpotential (givencurl)
Returns the vector potential of a given curl vector, in the current coordinate system. `potentialzeroloc` has a similar role as for `potential`, but the order of the left-hand sides of the equations must be a cyclic permutation of the coordinate variables.

Function: xthru (expr)
Combines all terms of expr (which should be a sum) over a common denominator without expanding products and exponentiated sums as `ratsimp` does. `xthru` cancels common factors in the numerator and denominator of rational expressions but only if the factors are explicit.

Sometimes it is better to use `xthru` before `ratsimp`ing an expression in order to cause explicit factors of the gcd of the numerator and denominator to be canceled thus simplifying the expression to be `ratsimp`ed.

```(%i1) ((x+2)^20 - 2*y)/(x+y)^20 + (x+y)^(-19) - x/(x+y)^20;
20
1       (x + 2)   - 2 y       x
(%o1)        --------- + --------------- - ---------
19             20             20
(y + x)        (y + x)        (y + x)
(%i2) xthru (%);
20
(x + 2)   - y
(%o2)                     -------------
20
(y + x)
```

Function: zeroequiv (expr, v)
Tests whether the expression expr in the variable v is equivalent to zero, returning `true`, `false`, or `dontknow`.

`zeroequiv` has these restrictions:

1. Do not use functions that Maxima does not know how to differentiate and evaluate.
2. If the expression has poles on the real line, there may be errors in the result (but this is unlikely to occur).
3. If the expression contains functions which are not solutions to first order differential equations (e.g. Bessel functions) there may be incorrect results.
4. The algorithm uses evaluation at randomly chosen points for carefully selected subexpressions. This is always a somewhat hazardous business, although the algorithm tries to minimize the potential for error.

For example `zeroequiv (sin(2*x) - 2*sin(x)*cos(x), x)` returns `true` and `zeroequiv (%e^x + x, x)` returns `false`. On the other hand `zeroequiv (log(a*b) - log(a) - log(b), a)` returns `dontknow` because of the presence of an extra parameter `b`.