Go backward to Bit Counting Example. Go up to Example Definitions.

The Sine Function
.................

A somewhat limited sine function could be defined as follows, using
the well-known Taylor series expansion for `sin(x)':

     (defmath mysin ((float (anglep x)))
       (interactive 1 "mysn")
       (setq x (to-radians x))    ; Convert from current angular mode.
       (let ((sum x)              ; Initial term of Taylor expansion of sin.
             newsum
             (nfact 1)            ; "nfact" equals "n" factorial at all times.
             (xnegsqr :"-(x^2)")) ; "xnegsqr" equals -x^2.
         (for ((n 3 100 2))       ; Upper limit of 100 is a good precaution.
           (working "mysin" sum)  ; Display "Working" message, if enabled.
           (setq nfact (* nfact (1- n) n)
                 x (* x xnegsqr)
                 newsum (+ sum (/ x nfact)))
           (if (~= newsum sum)    ; If newsum is "nearly equal to" sum,
               (break))           ;  then we are done.
           (setq sum newsum))
         sum))

The actual `sin' function in Calc works by first reducing the problem
to a sine or cosine of a nonnegative number less than `pi/4'.  This
ensures that the Taylor series will converge quickly.  Also, the
calculation is carried out with two extra digits of precision to guard
against cumulative round-off in `sum'.  Finally, complex arguments are
allowed and handled by a separate algorithm.

     (defmath mysin ((float (scalarp x)))
       (interactive 1 "mysn")
       (setq x (to-radians x))    ; Convert from current angular mode.
       (with-extra-prec 2         ; Evaluate with extra precision.
         (cond ((complexp x)
                (mysin-complex x))
               ((< x 0)
                (- (mysin-raw (- x)))    ; Always call mysin-raw with x >= 0.
               (t (mysin-raw x))))))

     (defmath mysin-raw (x)
       (cond ((>= x 7)
              (mysin-raw (% x (two-pi))))     ; Now x < 7.
             ((> x (pi-over-2))
              (- (mysin-raw (- x (pi)))))     ; Now -pi/2 <= x <= pi/2.
             ((> x (pi-over-4))
              (mycos-raw (- x (pi-over-2))))  ; Now -pi/2 <= x <= pi/4.
             ((< x (- (pi-over-4)))
              (- (mycos-raw (+ x (pi-over-2)))))  ; Now -pi/4 <= x <= pi/4,
             (t (mysin-series x))))           ; so the series will be efficient.

where `mysin-complex' is an appropriate function to handle complex
numbers, `mysin-series' is the routine to compute the sine Taylor
series as before, and `mycos-raw' is a function analogous to
`mysin-raw' for cosines.

The strategy is to ensure that `x' is nonnegative before calling
`mysin-raw'.  This function then recursively reduces its argument to a
suitable range, namely, plus-or-minus `pi/4'.  Note that each test,
and particularly the first comparison against 7, is designed so that
small roundoff errors cannnot produce an infinite loop.  (Suppose we
compared with `(two-pi)' instead; if due to roundoff problems the
modulo operator ever returned `(two-pi)' exactly, an infinite
recursion could result!)  We use modulo only for arguments that will
clearly get reduced, knowing that the next rule will catch any
reductions that this rule misses.

If a program is being written for general use, it is important to code
it carefully as shown in this second example.  For quick-and-dirty
programs, when you know that your own use of the sine function will
never encounter a large argument, a simpler program like the first one
shown is fine.