UNPKG

2.93 kBtext/coffeescriptView Raw
1### cos =====================================================================
2
3Tags
4----
5scripting, JS, internal, treenode, general concept
6
7Parameters
8----------
9x
10
11General description
12-------------------
13Returns the cosine of x.
14
15###
16
17
18Eval_cos = ->
19 push(cadr(p1))
20 Eval()
21 cosine()
22
23cosine = ->
24 save()
25 p1 = pop()
26 if (car(p1) == symbol(ADD))
27 cosine_of_angle_sum()
28 else
29 cosine_of_angle()
30 restore()
31
32# Use angle sum formula for special angles.
33
34#define A p3
35#define B p4
36
37cosine_of_angle_sum = ->
38 p2 = cdr(p1)
39 while (iscons(p2))
40 p4 = car(p2); # p4 is B
41 if (isnpi(p4)) # p4 is B
42 push(p1)
43 push(p4); # p4 is B
44 subtract()
45 p3 = pop(); # p3 is A
46 push(p3); # p3 is A
47 cosine()
48 push(p4); # p4 is B
49 cosine()
50 multiply()
51 push(p3); # p3 is A
52 sine()
53 push(p4); # p4 is B
54 sine()
55 multiply()
56 subtract()
57 return
58 p2 = cdr(p2)
59 cosine_of_angle()
60
61cosine_of_angle = ->
62
63 if (car(p1) == symbol(ARCCOS))
64 push(cadr(p1))
65 return
66
67 if (isdouble(p1))
68 d = Math.cos(p1.d)
69 if (Math.abs(d) < 1e-10)
70 d = 0.0
71 push_double(d)
72 return
73
74 # cosine function is symmetric, cos(-x) = cos(x)
75
76 if (isnegative(p1))
77 push(p1)
78 negate()
79 p1 = pop()
80
81 # cos(arctan(x)) = 1 / sqrt(1 + x^2)
82
83 # see p. 173 of the CRC Handbook of Mathematical Sciences
84
85 if (car(p1) == symbol(ARCTAN))
86 push_integer(1)
87 push(cadr(p1))
88 push_integer(2)
89 power()
90 add()
91 push_rational(-1, 2)
92 power()
93 return
94
95 # multiply by 180/pi to go from radians to degrees.
96 # we go from radians to degrees because it's much
97 # easier to calculate symbolic results of most (not all) "classic"
98 # angles (e.g. 30,45,60...) if we calculate the degrees
99 # and the we do a switch on that.
100 # Alternatively, we could look at the fraction of pi
101 # (e.g. 60 degrees is 1/3 pi) but that's more
102 # convoluted as we'd need to look at both numerator and
103 # denominator.
104
105 push(p1)
106 push_integer(180)
107 multiply()
108
109 if evaluatingAsFloats
110 push_double(Math.PI)
111 else
112 push_symbol(PI)
113
114 divide()
115
116 n = pop_integer()
117
118 # most "good" (i.e. compact) trigonometric results
119 # happen for a round number of degrees. There are some exceptions
120 # though, e.g. 22.5 degrees, which we don't capture here.
121 if (n < 0 || isNaN(n))
122 push(symbol(COS))
123 push(p1)
124 list(2)
125 return
126
127 switch (n % 360)
128 when 90, 270
129 push_integer(0)
130 when 60, 300
131 push_rational(1, 2)
132 when 120, 240
133 push_rational(-1, 2)
134 when 45, 315
135 push_rational(1, 2)
136 push_integer(2)
137 push_rational(1, 2)
138 power()
139 multiply()
140 when 135, 225
141 push_rational(-1, 2)
142 push_integer(2)
143 push_rational(1, 2)
144 power()
145 multiply()
146 when 30, 330
147 push_rational(1, 2)
148 push_integer(3)
149 push_rational(1, 2)
150 power()
151 multiply()
152 when 150, 210
153 push_rational(-1, 2)
154 push_integer(3)
155 push_rational(1, 2)
156 power()
157 multiply()
158 when 0
159 push_integer(1)
160 when 180
161 push_integer(-1)
162 else
163 push(symbol(COS))
164 push(p1)
165 list(2)
166