calc: Examples of Rewrite Rules

 
 11.11.13 Examples of Rewrite Rules
 ----------------------------------
 
 Returning to the example of substituting the pattern ‘sin(x)^2 +
 cos(x)^2’ with 1, we saw that the rule ‘opt(a) sin(x)^2 + opt(a)
 cos(x)^2 := a’ does a good job of finding suitable cases.  Another
 solution would be to use the rule ‘cos(x)^2 := 1 - sin(x)^2’, followed
 by algebraic simplification if necessary.  This rule will be the most
 effective way to do the job, but at the expense of making some changes
 that you might not desire.
 
    Another algebraic rewrite rule is ‘exp(x+y) := exp(x) exp(y)’.  To
 make this work with the ‘j r’ command so that it can be easily targeted
 to a particular exponential in a large formula, you might wish to write
 the rule as ‘select(exp(x+y)) := select(exp(x) exp(y))’.  The ‘select’
 markers will be ignored by the regular ‘a r’ command (SeeSelections
 with Rewrite Rules).
 
    A surprisingly useful rewrite rule is ‘a/(b-c) := a*(b+c)/(b^2-c^2)’.
 This will simplify the formula whenever ‘b’ and/or ‘c’ can be made
 simpler by squaring.  For example, applying this rule to ‘2 / (sqrt(2) +
 3)’ yields ‘6:7 - 2:7 sqrt(2)’ (assuming Symbolic mode has been enabled
 to keep the square root from being evaluated to a floating-point
 approximation).  This rule is also useful when working with symbolic
 complex numbers, e.g., ‘(a + b i) / (c + d i)’.
 
    As another example, we could define our own “triangular numbers”
 function with the rules ‘[tri(0) := 0, tri(n) := n + tri(n-1) :: n>0]’.
 Enter this vector and store it in a variable: ‘s t trirules’.  Now,
 given a suitable formula like ‘tri(5)’ on the stack, type ‘a r trirules’
 to apply these rules repeatedly.  After six applications, ‘a r’ will
 stop with 15 on the stack.  Once these rules are debugged, it would
 probably be most useful to add them to ‘EvalRules’ so that Calc will
 evaluate the new ‘tri’ function automatically.  We could then use ‘Z K’
 on the keyboard macro ‘' tri($) <RET>’ to make a command that applies
 ‘tri’ to the value on the top of the stack.  SeeProgramming.
 
    The following rule set, contributed by François Pinard, implements
 “quaternions”, a generalization of the concept of complex numbers.
 Quaternions have four components, and are here represented by function
 calls ‘quat(W, [X, Y, Z])’ with “real part” W and the three “imaginary”
 parts collected into a vector.  Various arithmetical operations on
 quaternions are supported.  To use these rules, either add them to
 ‘EvalRules’, or create a command based on ‘a r’ for simplifying
 quaternion formulas.  A convenient way to enter quaternions would be a
 command defined by a keyboard macro containing: ‘' quat($$$$, [$$$, $$,
 $]) <RET>’.
 
      [ quat(w, x, y, z) := quat(w, [x, y, z]),
        quat(w, [0, 0, 0]) := w,
        abs(quat(w, v)) := hypot(w, v),
        -quat(w, v) := quat(-w, -v),
        r + quat(w, v) := quat(r + w, v) :: real(r),
        r - quat(w, v) := quat(r - w, -v) :: real(r),
        quat(w1, v1) + quat(w2, v2) := quat(w1 + w2, v1 + v2),
        r * quat(w, v) := quat(r * w, r * v) :: real(r),
        plain(quat(w1, v1) * quat(w2, v2))
           := quat(w1 * w2 - v1 * v2, w1 * v2 + w2 * v1 + cross(v1, v2)),
        quat(w1, v1) / r := quat(w1 / r, v1 / r) :: real(r),
        z / quat(w, v) := z * quatinv(quat(w, v)),
        quatinv(quat(w, v)) := quat(w, -v) / (w^2 + v^2),
        quatsqr(quat(w, v)) := quat(w^2 - v^2, 2 * w * v),
        quat(w, v)^k := quatsqr(quat(w, v)^(k / 2))
                     :: integer(k) :: k > 0 :: k % 2 = 0,
        quat(w, v)^k := quatsqr(quat(w, v)^((k - 1) / 2)) * quat(w, v)
                     :: integer(k) :: k > 2,
        quat(w, v)^-k := quatinv(quat(w, v)^k) :: integer(k) :: k > 0 ]
 
    Quaternions, like matrices, have non-commutative multiplication.  In
 other words, ‘q1 * q2 = q2 * q1’ is not necessarily true if ‘q1’ and
 ‘q2’ are ‘quat’ forms.  The ‘quat*quat’ rule above uses ‘plain’ to
 prevent Calc from rearranging the product.  It may also be wise to add
 the line ‘[quat(), matrix]’ to the ‘Decls’ matrix, to ensure that Calc’s
 other algebraic operations will not rearrange a quaternion product.
 SeeDeclarations.
 
    These rules also accept a four-argument ‘quat’ form, converting it to
 the preferred form in the first rule.  If you would rather see results
 in the four-argument form, just append the two items ‘phase(2), quat(w,
 [x, y, z]) := quat(w, x, y, z)’ to the end of the rule set.  (But
 remember that multi-phase rule sets don’t work in ‘EvalRules’.)