Little fix after the last commit (mostly a git fail)
[eigenmath-fx.git] / rationalize.cpp
blob64c6838ea1b592b06cd70cf3f2739ee5916c2446
1 #include "stdafx.h"
2 #include "defs.h"
3 #define DEBUG 0
4 static void __rationalize_tensor(void);
5 static void multiply_denominators(U *);
6 static void multiply_denominators_term(U *);
7 static void multiply_denominators_factor(U *);
8 static void __lcm(void);
10 void
11 eval_rationalize(void)
13 push(cadr(p1));
14 eval();
15 rationalize();
18 void
19 rationalize(void)
21 int x = expanding;
22 save();
23 yyrationalize();
24 restore();
25 expanding = x;
28 void
29 yyrationalize(void)
31 p1 = pop();
33 if (istensor(p1)) {
34 __rationalize_tensor();
35 return;
38 expanding = 0;
40 if (car(p1) != symbol(ADD)) {
41 push(p1);
42 return;
45 // get common denominator
47 push(one);
48 multiply_denominators(p1);
49 p2 = pop();
51 // multiply each term by common denominator
53 push(zero);
54 p3 = cdr(p1);
55 while (iscons(p3)) {
56 push(p2);
57 push(car(p3));
58 multiply();
59 add();
60 p3 = cdr(p3);
63 // collect common factors
65 Condense();
67 // divide by common denominator
69 push(p2);
70 divide();
73 static void
74 multiply_denominators(U *p)
76 if (car(p) == symbol(ADD)) {
77 p = cdr(p);
78 while (iscons(p)) {
79 multiply_denominators_term(car(p));
80 p = cdr(p);
82 } else
83 multiply_denominators_term(p);
86 static void
87 multiply_denominators_term(U *p)
89 if (car(p) == symbol(MULTIPLY)) {
90 p = cdr(p);
91 while (iscons(p)) {
92 multiply_denominators_factor(car(p));
93 p = cdr(p);
95 } else
96 multiply_denominators_factor(p);
99 static void
100 multiply_denominators_factor(U *p)
102 if (car(p) != symbol(POWER))
103 return;
105 push(p);
107 p = caddr(p);
109 // like x^(-2) ?
111 if (isnegativenumber(p)) {
112 inverse();
113 __lcm();
114 return;
117 // like x^(-a) ?
119 if (car(p) == symbol(MULTIPLY) && isnegativenumber(cadr(p))) {
120 inverse();
121 __lcm();
122 return;
125 // no match
127 pop();
130 static void
131 __rationalize_tensor(void)
133 int i, n;
135 push(p1);
137 eval(); // makes a copy
139 p1 = pop();
141 if (!istensor(p1)) { // might be zero
142 push(p1);
143 return;
146 n = p1->u.tensor->nelem;
148 for (i = 0; i < n; i++) {
149 push(p1->u.tensor->elem[i]);
150 rationalize();
151 p1->u.tensor->elem[i] = pop();
154 push(p1);
157 static void
158 __lcm(void)
160 save();
162 p1 = pop();
163 p2 = pop();
165 push(p1);
166 push(p2);
167 multiply();
168 push(p1);
169 push(p2);
170 gcd();
171 divide();
173 restore();