Little fix after the last commit (mostly a git fail)
[eigenmath-fx.git] / gcd.cpp
blob3d8ca656e42e919150fadc1c2e7208fb7e4f180a
1 // Greatest common denominator
3 #include "stdafx.h"
4 #include "defs.h"
6 void
7 eval_gcd(void)
9 p1 = cdr(p1);
10 push(car(p1));
11 eval();
12 p1 = cdr(p1);
13 while (iscons(p1)) {
14 push(car(p1));
15 eval();
16 gcd();
17 p1 = cdr(p1);
21 void
22 gcd(void)
24 int x = expanding;
25 save();
26 gcd_main();
27 restore();
28 expanding = x;
31 void
32 gcd_main(void)
34 expanding = 1;
36 p2 = pop();
37 p1 = pop();
39 if (equal(p1, p2)) {
40 push(p1);
41 return;
44 if (isrational(p1) && isrational(p2)) {
45 push(p1);
46 push(p2);
47 gcd_numbers();
48 return;
51 if (car(p1) == symbol(ADD) && car(p2) == symbol(ADD)) {
52 gcd_expr_expr();
53 return;
56 if (car(p1) == symbol(ADD)) {
57 gcd_expr(p1);
58 p1 = pop();
61 if (car(p2) == symbol(ADD)) {
62 gcd_expr(p2);
63 p2 = pop();
66 if (car(p1) == symbol(MULTIPLY) && car(p2) == symbol(MULTIPLY)) {
67 gcd_term_term();
68 return;
71 if (car(p1) == symbol(MULTIPLY)) {
72 gcd_term_factor();
73 return;
76 if (car(p2) == symbol(MULTIPLY)) {
77 gcd_factor_term();
78 return;
81 // gcd of factors
83 if (car(p1) == symbol(POWER)) {
84 p3 = caddr(p1);
85 p1 = cadr(p1);
86 } else
87 p3 = one;
89 if (car(p2) == symbol(POWER)) {
90 p4 = caddr(p2);
91 p2 = cadr(p2);
92 } else
93 p4 = one;
95 if (!equal(p1, p2)) {
96 push(one);
97 return;
100 // are both exponents numerical?
102 if (isnum(p3) && isnum(p4)) {
103 push(p1);
104 if (lessp(p3, p4))
105 push(p3);
106 else
107 push(p4);
108 power();
109 return;
112 // are the exponents multiples of eah other?
114 push(p3);
115 push(p4);
116 divide();
118 p5 = pop();
120 if (isnum(p5)) {
122 push(p1);
124 // choose the smallest exponent
126 if (car(p3) == symbol(MULTIPLY) && isnum(cadr(p3)))
127 p5 = cadr(p3);
128 else
129 p5 = one;
131 if (car(p4) == symbol(MULTIPLY) && isnum(cadr(p4)))
132 p6 = cadr(p4);
133 else
134 p6 = one;
136 if (lessp(p5, p6))
137 push(p3);
138 else
139 push(p4);
141 power();
142 return;
145 push(p3);
146 push(p4);
147 subtract();
149 p5 = pop();
151 if (!isnum(p5)) {
152 push(one);
153 return;
156 // can't be equal because of test near beginning
158 push(p1);
160 if (isnegativenumber(p5))
161 push(p3);
162 else
163 push(p4);
165 power();
168 // in this case gcd is used as a composite function, i.e. gcd(gcd(gcd...
170 void
171 gcd_expr_expr(void)
173 if (length(p1) != length(p2)) {
174 push(one);
175 return;
178 p3 = cdr(p1);
179 push(car(p3));
180 p3 = cdr(p3);
181 while (iscons(p3)) {
182 push(car(p3));
183 gcd();
184 p3 = cdr(p3);
186 p3 = pop();
188 p4 = cdr(p2);
189 push(car(p4));
190 p4 = cdr(p4);
191 while (iscons(p4)) {
192 push(car(p4));
193 gcd();
194 p4 = cdr(p4);
196 p4 = pop();
198 push(p1);
199 push(p3);
200 divide();
201 p5 = pop();
203 push(p2);
204 push(p4);
205 divide();
206 p6 = pop();
208 if (equal(p5, p6)) {
209 push(p5);
210 push(p3);
211 push(p4);
212 gcd();
213 multiply();
214 } else
215 push(one);
218 void
219 gcd_expr(U *p)
221 p = cdr(p);
222 push(car(p));
223 p = cdr(p);
224 while (iscons(p)) {
225 push(car(p));
226 gcd();
227 p = cdr(p);
231 void
232 gcd_term_term(void)
234 push(one);
235 p3 = cdr(p1);
236 while (iscons(p3)) {
237 p4 = cdr(p2);
238 while (iscons(p4)) {
239 push(car(p3));
240 push(car(p4));
241 gcd();
242 multiply();
243 p4 = cdr(p4);
245 p3 = cdr(p3);
249 void
250 gcd_term_factor(void)
252 push(one);
253 p3 = cdr(p1);
254 while (iscons(p3)) {
255 push(car(p3));
256 push(p2);
257 gcd();
258 multiply();
259 p3 = cdr(p3);
263 void
264 gcd_factor_term(void)
266 push(one);
267 p4 = cdr(p2);
268 while (iscons(p4)) {
269 push(p1);
270 push(car(p4));
271 gcd();
272 multiply();
273 p4 = cdr(p4);
277 #if SELFTEST
279 static char *s[] = {
281 "gcd(30,42)",
282 "6",
284 "gcd(42,30)",
285 "6",
287 "gcd(-30,42)",
288 "6",
290 "gcd(42,-30)",
291 "6",
293 "gcd(30,-42)",
294 "6",
296 "gcd(-42,30)",
297 "6",
299 "gcd(-30,-42)",
300 "6",
302 "gcd(-42,-30)",
303 "6",
305 "gcd(x,x)",
306 "x",
308 "gcd(-x,x)",
309 "x",
311 "gcd(x,-x)",
312 "x",
314 "gcd(-x,-x)",
315 "-x",
317 "gcd(x^2,x^3)",
318 "x^2",
320 "gcd(x,y)",
321 "1",
323 "gcd(y,x)",
324 "1",
326 "gcd(x*y,y)",
327 "y",
329 "gcd(x*y,y^2)",
330 "y",
332 "gcd(x^2*y^2,x^3*y^3)",
333 "x^2*y^2",
335 "gcd(x^2,x^3)",
336 "x^2",
338 // gcd of expr
340 "gcd(x+y,x+z)",
341 "1",
343 "gcd(x+y,x+y)",
344 "x+y",
346 "gcd(x+y,2*x+2*y)",
347 "x+y",
349 "gcd(-x-y,x+y)",
350 "x+y",
352 "gcd(4*x+4*y,6*x+6*y)",
353 "2*x+2*y",
355 "gcd(4*x+4*y+4,6*x+6*y+6)",
356 "2+2*x+2*y",
358 "gcd(4*x+4*y+4,6*x+6*y+12)",
359 "1",
361 "gcd(27*t^3+y^3+9*t*y^2+27*t^2*y,t+y)",
362 "1",
364 // gcd expr factor
366 "gcd(2*a^2*x^2+a*x+a*b,a)",
367 "a",
369 "gcd(2*a^2*x^2+a*x+a*b,a^2)",
370 "a",
372 "gcd(2*a^2*x^2+2*a*x+2*a*b,a)",
373 "a",
375 // gcd expr term
377 "gcd(2*a^2*x^2+2*a*x+2*a*b,2*a)",
378 "2*a",
380 "gcd(2*a^2*x^2+2*a*x+2*a*b,3*a)",
381 "a",
383 "gcd(2*a^2*x^2+2*a*x+2*a*b,4*a)",
384 "2*a",
386 // gcd factor factor
388 "gcd(x,x^2)",
389 "x",
391 "gcd(x,x^a)",
392 "1",
394 // multiple arguments
396 "gcd(12,18,9)",
397 "3",
400 void
401 test_gcd(void)
403 test(__FILE__, s, sizeof s / sizeof (char *));
406 #endif