UNPKG

2.21 kBtext/coffeescriptView Raw
1
2
3Eval_rationalize = ->
4 push(cadr(p1))
5 Eval()
6 rationalize()
7
8rationalize = ->
9 x = expanding
10 save()
11 yyrationalize()
12 restore()
13 expanding = x
14
15yyrationalize = ->
16 p1 = pop()
17
18 if (istensor(p1))
19 __rationalize_tensor()
20 return
21
22 expanding = 0
23
24 if (car(p1) != symbol(ADD))
25 push(p1)
26 return
27
28 if DEBUG
29 printf("rationalize: this is the input expr:\n")
30 printline(p1)
31
32 # get common denominator
33
34 push(one)
35 multiply_denominators(p1)
36 p2 = pop()
37
38 if DEBUG
39 printf("rationalize: this is the common denominator:\n")
40 printline(p2)
41
42 # multiply each term by common denominator
43
44 push(zero)
45 p3 = cdr(p1)
46 while (iscons(p3))
47 push(p2)
48 push(car(p3))
49 multiply()
50 add()
51 p3 = cdr(p3)
52
53 if DEBUG
54 printf("rationalize: original expr times common denominator:\n")
55 printline(stack[tos - 1])
56
57 # collect common factors
58
59 Condense()
60
61 if DEBUG
62 printf("rationalize: after factoring:\n")
63 printline(stack[tos - 1])
64
65 # divide by common denominator
66
67 push(p2)
68 divide()
69
70 if DEBUG
71 printf("rationalize: after dividing by common denom. (and we're done):\n")
72 printline(stack[tos - 1])
73
74multiply_denominators = (p) ->
75 if (car(p) == symbol(ADD))
76 p = cdr(p)
77 while (iscons(p))
78 multiply_denominators_term(car(p))
79 p = cdr(p)
80 else
81 multiply_denominators_term(p)
82
83multiply_denominators_term = (p) ->
84 if (car(p) == symbol(MULTIPLY))
85 p = cdr(p)
86 while (iscons(p))
87 multiply_denominators_factor(car(p))
88 p = cdr(p)
89 else
90 multiply_denominators_factor(p)
91
92multiply_denominators_factor = (p) ->
93 if (car(p) != symbol(POWER))
94 return
95
96 push(p)
97
98 p = caddr(p)
99
100 # like x^(-2) ?
101
102 if (isnegativenumber(p))
103 inverse()
104 __lcm()
105 return
106
107 # like x^(-a) ?
108
109 if (car(p) == symbol(MULTIPLY) && isnegativenumber(cadr(p)))
110 inverse()
111 __lcm()
112 return
113
114 # no match
115
116 pop()
117
118__rationalize_tensor = ->
119
120 i = 0
121 push(p1)
122
123 Eval(); # makes a copy
124
125 p1 = pop()
126
127 if (!istensor(p1)) # might be zero
128 push(p1)
129 return
130
131 n = p1.tensor.nelem
132
133 for i in [0...n]
134 push(p1.tensor.elem[i])
135 rationalize()
136 p1.tensor.elem[i] = pop()
137
138 check_tensor_dimensions p1
139
140
141 push(p1)
142
143
144
145__lcm = ->
146 save()
147
148 p1 = pop()
149 p2 = pop()
150
151 push(p1)
152 push(p2)
153 multiply()
154 push(p1)
155 push(p2)
156 gcd()
157 divide()
158
159 restore()