## Logical Operations

The following commands and algebraic functions return true/false values, where 1 represents "true" and 0 represents "false." In cases where a truth value is required (such as for the condition part of a rewrite rule, or as the condition for a Z [ Z ] control structure), any nonzero value is accepted to mean "true." (Specifically, anything for which `dnonzero` returns 1 is "true," and anything for which `dnonzero` returns 0 or cannot decide is assumed "false." Note that this means that Z [ Z ] will execute the "then" portion if its condition is provably true, but it will execute the "else" portion for any condition like a = b that is not provably true, even if it might be true. Algebraic functions that have conditions as arguments, like `? :` and `&&`, remain unevaluated if the condition is neither provably true nor provably false. See section Declarations.)

The a = (`calc-equal-to`) command, or `eq(a,b)' function (which can also be written `a = b' or `a == b' in an algebraic formula) is true if a and b are equal, either because they are identical expressions, or because they are numbers which are numerically equal. (Thus the integer 1 is considered equal to the float 1.0.) If the equality of a and b cannot be determined, the comparison is left in symbolic form. Note that as a command, this operation pops two values from the stack and pushes back either a 1 or a 0, or a formula `a = b' if the values' equality cannot be determined.

Many Calc commands use `=' formulas to represent equations. For example, the a S (`calc-solve-for`) command rearranges an equation to solve for a given variable. The a M (`calc-map-equation`) command can be used to apply any function to both sides of an equation; for example, 2 a M * multiplies both sides of the equation by two. Note that just 2 * would not do the same thing; it would produce the formula `2 (a = b)' which represents 2 if the equality is true or zero if not.

The `eq` function with more than two arguments (e.g., C-u 3 a = or `a = b = c') tests if all of its arguments are equal. In algebraic notation, the `=' operator is unusual in that it is neither left- nor right-associative: `a = b = c' is not the same as `(a = b) = c' or `a = (b = c)' (which each compare one variable with the 1 or 0 that results from comparing two other variables).

The a # (`calc-not-equal-to`) command, or `neq(a,b)' or `a != b' function, is true if a and b are not equal. This also works with more than two arguments; `a != b != c != d' tests that all four of a, b, c, and d are distinct numbers.

The a < (`calc-less-than`) [`lt(a,b)' or `a < b'] operation is true if a is less than b. Similar functions are a > (`calc-greater-than`) [`gt(a,b)' or `a > b'], a [ (`calc-less-equal`) [`leq(a,b)' or `a <= b'], and a ] (`calc-greater-equal`) [`geq(a,b)' or `a >= b'].

While the inequality functions like `lt` do not accept more than two arguments, the syntax `a <= b < c' is translated to an equivalent expression involving intervals: `b in [a .. c)'. (See the description of `in` below.) All four combinations of `<' and `<=' are allowed, or any of the four combinations of `>' and `>='. Four-argument constructions like `a < b < c < d', and mixtures like `a < b = c' that involve both equalities and inequalities, are not allowed.

The a . (`calc-remove-equal`) [`rmeq`] command extracts the righthand side of the equation or inequality on the top of the stack. It also works elementwise on vectors. For example, if `[x = 2.34, y = z / 2]' is on the stack, then a . produces `[2.34, z / 2]'. As a special case, if the righthand side is a variable and the lefthand side is a number (as in `2.34 = x'), then Calc keeps the lefthand side instead. Finally, this command works with assignments `x := 2.34' as well as equations, always taking the the righthand side, and for `=>' (evaluates-to) operators, always taking the lefthand side.

The a & (`calc-logical-and`) [`land(a,b)' or `a && b'] function is true if both of its arguments are true, i.e., are non-zero numbers. In this case, the result will be either a or b, chosen arbitrarily. If either argument is zero, the result is zero. Otherwise, the formula is left in symbolic form.

The a | (`calc-logical-or`) [`lor(a,b)' or `a || b'] function is true if either or both of its arguments are true (nonzero). The result is whichever argument was nonzero, choosing arbitrarily if both are nonzero. If both a and b are zero, the result is zero.

The a ! (`calc-logical-not`) [`lnot(a)' or `! a'] function is true if a is false (zero), or false if a is true (nonzero). It is left in symbolic form if a is not a number.

The a : (`calc-logical-if`) [`if(a,b,c)' or `a ? b : c'] function is equal to either b or c if a is a nonzero number or zero, respectively. If a is not a number, the test is left in symbolic form and neither b nor c is evaluated in any way. In algebraic formulas, this is one of the few Calc functions whose arguments are not automatically evaluated when the function itself is evaluated. The others are `lambda`, `quote`, and `condition`.

One minor surprise to watch out for is that the formula `a?3:4' will not work because the `3:4' is parsed as a fraction instead of as three separate symbols. Type something like `a ? 3 : 4' or `a?(3):4' instead.

As a special case, if a evaluates to a vector, then both b and c are evaluated; the result is a vector of the same length as a whose elements are chosen from corresponding elements of b and c according to whether each element of a is zero or nonzero. Each of b and c must be either a vector of the same length as a, or a non-vector which is matched with all elements of a.

The a { (`calc-in-set`) [`in(a,b)'] function is true if the number a is in the set of numbers represented by b. If b is an interval form, a must be one of the values encompassed by the interval. If b is a vector, a must be equal to one of the elements of the vector. (If any vector elements are intervals, a must be in any of the intervals.) If b is a plain number, a must be numerically equal to b. See section Set Operations using Vectors, for a group of commands that manipulate sets of this sort.

The `typeof(a)' function produces an integer or variable which characterizes a. If a is a number, vector, or variable, the result will be one of the following numbers:

``` 1   Integer
2   Fraction
3   Floating-point number
4   HMS form
5   Rectangular complex number
6   Polar complex number
7   Error form
8   Interval form
9   Modulo form
10   Date-only form
11   Date/time form
12   Infinity (inf, uinf, or nan)
100  Variable
101  Vector (but not a matrix)
102  Matrix
```

Otherwise, a is a formula, and the result is a variable which represents the name of the top-level function call.

The `integer(a)' function returns true if a is an integer. The `real(a)' function is true if a is a real number, either integer, fraction, or float. The `constant(a)' function returns true if a is any of the objects for which `typeof` would produce an integer code result except for variables, and provided that the components of an object like a vector or error form are themselves constant. Note that infinities do not satisfy any of these tests, nor do special constants like `pi` and `e`.

See section Declarations, for a set of similar functions that recognize formulas as well as actual numbers. For example, `dint(floor(x))' is true because `floor(x)' is provably integer-valued, but `integer(floor(x))' does not because `floor(x)' is not literally an integer constant.

The `refers(a,b)' function is true if the variable (or sub-expression) b appears in a, or false otherwise. Unlike the other tests described here, this function returns a definite "no" answer even if its arguments are still in symbolic form. The only case where `refers` will be left unevaluated is if a is a plain variable (different from b).

The `negative(a)' function returns true if a "looks" negative, because it is a negative number, because it is of the form -x, or because it is a product or quotient with a term that looks negative. This is most useful in rewrite rules. Beware that `negative(a)' evaluates to 1 or 0 for any argument a, so it can only be stored in a formula if the default simplifications are turned off first with m O (or if it appears in an unevaluated context such as a rewrite rule condition).

The `variable(a)' function is true if a is a variable, or false if not. If a is a function call, this test is left in symbolic form. Built-in variables like `pi` and `inf` are considered variables like any others by this test.

The `nonvar(a)' function is true if a is a non-variable. If its argument is a variable it is left unsimplified; it never actually returns zero. However, since Calc's condition-testing commands consider "false" anything not provably true, this is often good enough.

The functions `lin`, `linnt`, `islin`, and `islinnt` check if an expression is "linear," i.e., can be written in the form a + b x for some constants a and b, and some variable or subformula x. The function `islin(f,x)' checks if formula f is linear in x, returning 1 if so. For example, `islin(x,x)', `islin(-x,x)', `islin(3,x)', and `islin(x y / 3 - 2, x)' all return 1. The `lin(f,x)' function is similar, except that instead of returning 1 it returns the vector [a, b, x]. For the above examples, this vector would be [0, 1, x], [0, -1, x], [3, 0, x], and [-2, y/3, x], respectively. Both `lin` and `islin` generally remain unevaluated for expressions which are not linear, e.g., `lin(2 x^2, x)' and `lin(sin(x), x)'. The second argument can also be a formula; `islin(2 + 3 sin(x), sin(x))' returns true.

The `linnt` and `islinnt` functions perform a similar check, but require a "non-trivial" linear form, which means that the b coefficient must be non-zero. For example, `lin(2,x)' returns [2, 0, x] and `lin(y,x)' returns [y, 0, x], but `linnt(2,x)' and `linnt(y,x)' are left unevaluated (in other words, these formulas are considered to be only "trivially" linear in x).

All four linearity-testing functions allow you to omit the second argument, in which case the input may be linear in any non-constant formula. Here, the a=0, b=1 case is also considered trivial, and only constant values for a and b are recognized. Thus, `lin(2 x y)' returns [0, 2, x y], `lin(2 - x y)' returns [2, -1, x y], and `lin(x y)' returns [0, 1, x y]. The `linnt` function would allow the first two cases but not the third. Also, neither `lin` nor `linnt` accept plain constants as linear in the one-argument case: `islin(2,x)' is true, but `islin(2)' is false.

The `istrue(a)' function returns 1 if a is a nonzero number or provably nonzero formula, or 0 if a is anything else. Calls to `istrue` can only be manipulated if m O mode is used to make sure they are not evaluated prematurely. (Note that declarations are used when deciding whether a formula is true; `istrue` returns 1 when `dnonzero` would return 1, and it returns 0 when `dnonzero` would return 0 or leave itself in symbolic form.)