UNPKG

1.86 kBtext/coffeescriptView Raw
1# Tangent function of numerical and symbolic arguments
2
3
4
5Eval_tan = ->
6 push(cadr(p1))
7 Eval()
8 tangent()
9
10tangent = ->
11 save()
12 yytangent()
13 restore()
14
15yytangent = ->
16 n = 0
17 d = 0.0
18
19 p1 = pop()
20
21 if (car(p1) == symbol(ARCTAN))
22 push(cadr(p1))
23 return
24
25 if (isdouble(p1))
26 d = Math.tan(p1.d)
27 if (Math.abs(d) < 1e-10)
28 d = 0.0
29 push_double(d)
30 return
31
32 # tan function is antisymmetric, tan(-x) = -tan(x)
33
34 if (isnegative(p1))
35 push(p1)
36 negate()
37 tangent()
38 negate()
39 return
40
41 # multiply by 180/pi to go from radians to degrees.
42 # we go from radians to degrees because it's much
43 # easier to calculate symbolic results of most (not all) "classic"
44 # angles (e.g. 30,45,60...) if we calculate the degrees
45 # and the we do a switch on that.
46 # Alternatively, we could look at the fraction of pi
47 # (e.g. 60 degrees is 1/3 pi) but that's more
48 # convoluted as we'd need to look at both numerator and
49 # denominator.
50
51 push(p1)
52 push_integer(180)
53 multiply()
54 if evaluatingAsFloats
55 push_double(Math.PI)
56 else
57 push_symbol(PI)
58 divide()
59
60 n = pop_integer()
61
62 # most "good" (i.e. compact) trigonometric results
63 # happen for a round number of degrees. There are some exceptions
64 # though, e.g. 22.5 degrees, which we don't capture here.
65 if (n < 0 || isNaN(n))
66 push(symbol(TAN))
67 push(p1)
68 list(2)
69 return
70
71 switch (n % 360)
72 when 0, 180
73 push_integer(0)
74 when 30, 210
75 push_rational(1, 3)
76 push_integer(3)
77 push_rational(1, 2)
78 power()
79 multiply()
80 when 150, 330
81 push_rational(-1, 3)
82 push_integer(3)
83 push_rational(1, 2)
84 power()
85 multiply()
86 when 45, 225
87 push_integer(1)
88 when 135, 315
89 push_integer(-1)
90 when 60, 240
91 push_integer(3)
92 push_rational(1, 2)
93 power()
94 when 120, 300
95 push_integer(3)
96 push_rational(1, 2)
97 power()
98 negate()
99 else
100 push(symbol(TAN))
101 push(p1)
102 list(2)
103
104