1 | # Sine function of numerical and symbolic arguments
|
2 |
|
3 |
|
4 |
|
5 | Eval_sin = ->
|
6 | #console.log "sin ---- "
|
7 | push(cadr(p1))
|
8 | Eval()
|
9 | sine()
|
10 | #console.log "sin end ---- "
|
11 |
|
12 | sine = ->
|
13 | #console.log "sine ---- "
|
14 | save()
|
15 | p1 = pop()
|
16 | if (car(p1) == symbol(ADD))
|
17 | # sin of a sum can be further decomposed into
|
18 | #sin(alpha+beta) = sin(alpha)*cos(beta)+sin(beta)*cos(alpha)
|
19 | sine_of_angle_sum()
|
20 | else
|
21 | sine_of_angle()
|
22 | restore()
|
23 | #console.log "sine end ---- "
|
24 |
|
25 | # Use angle sum formula for special angles.
|
26 |
|
27 | #define A p3
|
28 | #define B p4
|
29 |
|
30 | # decompose sum sin(alpha+beta) into
|
31 | # sin(alpha)*cos(beta)+sin(beta)*cos(alpha)
|
32 | sine_of_angle_sum = ->
|
33 | #console.log "sin of angle sum ---- "
|
34 | p2 = cdr(p1)
|
35 | while (iscons(p2))
|
36 | p4 = car(p2); # p4 is B
|
37 | if (isnpi(p4)) # p4 is B
|
38 | push(p1)
|
39 | push(p4); # p4 is B
|
40 | subtract()
|
41 | p3 = pop(); # p3 is A
|
42 | push(p3); # p3 is A
|
43 | sine()
|
44 | push(p4); # p4 is B
|
45 | cosine()
|
46 | multiply()
|
47 | push(p3); # p3 is A
|
48 | cosine()
|
49 | push(p4); # p4 is B
|
50 | sine()
|
51 | multiply()
|
52 | add()
|
53 | #console.log "sin of angle sum end ---- "
|
54 | return
|
55 | p2 = cdr(p2)
|
56 | sine_of_angle()
|
57 | #console.log "sin of angle sum end ---- "
|
58 |
|
59 | sine_of_angle = ->
|
60 |
|
61 | if (car(p1) == symbol(ARCSIN))
|
62 | push(cadr(p1))
|
63 | return
|
64 |
|
65 | if isdouble(p1)
|
66 | d = Math.sin(p1.d)
|
67 | if (Math.abs(d) < 1e-10)
|
68 | d = 0.0
|
69 | push_double(d)
|
70 | return
|
71 |
|
72 | # sine function is antisymmetric, sin(-x) = -sin(x)
|
73 |
|
74 | if (isnegative(p1))
|
75 | push(p1)
|
76 | negate()
|
77 | sine()
|
78 | negate()
|
79 | return
|
80 |
|
81 | # sin(arctan(x)) = x / 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(cadr(p1))
|
87 | push_integer(1)
|
88 | push(cadr(p1))
|
89 | push_integer(2)
|
90 | power()
|
91 | add()
|
92 | push_rational(-1, 2)
|
93 | power()
|
94 | multiply()
|
95 | return
|
96 |
|
97 | # multiply by 180/pi to go from radians to degrees.
|
98 | # we go from radians to degrees because it's much
|
99 | # easier to calculate symbolic results of most (not all) "classic"
|
100 | # angles (e.g. 30,45,60...) if we calculate the degrees
|
101 | # and the we do a switch on that.
|
102 | # Alternatively, we could look at the fraction of pi
|
103 | # (e.g. 60 degrees is 1/3 pi) but that's more
|
104 | # convoluted as we'd need to look at both numerator and
|
105 | # denominator.
|
106 |
|
107 | push(p1)
|
108 | push_integer(180)
|
109 | multiply()
|
110 | if evaluatingAsFloats
|
111 | push_double(Math.PI)
|
112 | else
|
113 | push_symbol(PI)
|
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(SIN))
|
123 | push(p1)
|
124 | list(2)
|
125 | return
|
126 |
|
127 | # values of some famous angles. Many more here:
|
128 | # https://en.wikipedia.org/wiki/Trigonometric_constants_expressed_in_real_radicals
|
129 |
|
130 | switch (n % 360)
|
131 | when 0, 180
|
132 | push_integer(0)
|
133 | when 30, 150
|
134 | push_rational(1, 2)
|
135 | when 210, 330
|
136 | push_rational(-1, 2)
|
137 | when 45, 135
|
138 | push_rational(1, 2)
|
139 | push_integer(2)
|
140 | push_rational(1, 2)
|
141 | power()
|
142 | multiply()
|
143 | when 225, 315
|
144 | push_rational(-1, 2)
|
145 | push_integer(2)
|
146 | push_rational(1, 2)
|
147 | power()
|
148 | multiply()
|
149 | when 60, 120
|
150 | push_rational(1, 2)
|
151 | push_integer(3)
|
152 | push_rational(1, 2)
|
153 | power()
|
154 | multiply()
|
155 | when 240, 300
|
156 | push_rational(-1, 2)
|
157 | push_integer(3)
|
158 | push_rational(1, 2)
|
159 | power()
|
160 | multiply()
|
161 | when 90
|
162 | push_integer(1)
|
163 | when 270
|
164 | push_integer(-1)
|
165 | else
|
166 | push(symbol(SIN))
|
167 | push(p1)
|
168 | list(2)
|
169 |
|
170 |
|