Go forward to Rewrite Rules. Go backward to Summations. Go up to Algebra.

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 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 Set Operations, 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 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.)