Previous: Bit Counting Example, Up: Example Definitions

##### 17.5.5.2 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 cannot 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.
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 0, "mathjax_display_tex": 0, "mathjax_asciimath": 1, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.808533787727356, "perplexity": 6726.4891508555165}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2014-52/segments/1418802775338.41/warc/CC-MAIN-20141217075255-00060-ip-10-231-17-201.ec2.internal.warc.gz"}