eigenmath/rationalize.cpp

225 lines
3.0 KiB
C++
Raw Permalink Normal View History

2004-03-03 21:24:06 +01:00
#include "stdafx.h"
#include "defs.h"
#define DEBUG 0
static void __rationalize_tensor(void);
static void multiply_denominators(U *);
static void multiply_denominators_term(U *);
static void multiply_denominators_factor(U *);
static void __lcm(void);
2005-06-25 21:29:07 +02:00
void
eval_rationalize(void)
{
push(cadr(p1));
eval();
rationalize();
}
2004-03-03 21:24:06 +01:00
void
rationalize(void)
{
int x = expanding;
save();
2006-09-19 23:04:36 +02:00
yyrationalize();
2004-03-03 21:24:06 +01:00
restore();
expanding = x;
}
2006-09-19 23:04:36 +02:00
void
yyrationalize(void)
2004-03-03 21:24:06 +01:00
{
p1 = pop();
2005-08-06 22:57:37 +02:00
if (istensor(p1)) {
2004-03-03 21:24:06 +01:00
__rationalize_tensor();
return;
}
expanding = 0;
if (car(p1) != symbol(ADD)) {
push(p1);
return;
}
#if DEBUG
printf("rationalize: this is the input expr:\n");
printline(p1);
#endif
// get common denominator
2004-06-25 22:45:15 +02:00
push(one);
2004-03-03 21:24:06 +01:00
multiply_denominators(p1);
p2 = pop();
#if DEBUG
printf("rationalize: this is the common denominator:\n");
printline(p2);
#endif
// multiply each term by common denominator
2004-06-25 22:45:15 +02:00
push(zero);
2004-03-03 21:24:06 +01:00
p3 = cdr(p1);
while (iscons(p3)) {
push(p2);
push(car(p3));
multiply();
add();
p3 = cdr(p3);
}
#if DEBUG
printf("rationalize: original expr times common denominator:\n");
printline(stack[tos - 1]);
#endif
// collect common factors
2006-01-15 00:55:11 +01:00
Condense();
2004-03-03 21:24:06 +01:00
#if DEBUG
printf("rationalize: after factoring:\n");
printline(stack[tos - 1]);
#endif
// divide by common denominator
push(p2);
divide();
#if DEBUG
printf("rationalize: after dividing by common denom. (and we're done):\n");
printline(stack[tos - 1]);
#endif
}
static void
multiply_denominators(U *p)
{
if (car(p) == symbol(ADD)) {
p = cdr(p);
while (iscons(p)) {
multiply_denominators_term(car(p));
p = cdr(p);
}
} else
multiply_denominators_term(p);
}
static void
multiply_denominators_term(U *p)
{
if (car(p) == symbol(MULTIPLY)) {
p = cdr(p);
while (iscons(p)) {
multiply_denominators_factor(car(p));
p = cdr(p);
}
} else
multiply_denominators_factor(p);
}
static void
multiply_denominators_factor(U *p)
{
if (car(p) != symbol(POWER))
return;
push(p);
p = caddr(p);
// like x^(-2) ?
if (isnegativenumber(p)) {
inverse();
__lcm();
return;
}
// like x^(-a) ?
if (car(p) == symbol(MULTIPLY) && isnegativenumber(cadr(p))) {
inverse();
__lcm();
return;
}
// no match
pop();
}
static void
__rationalize_tensor(void)
{
int i, n;
push(p1);
eval(); // makes a copy
p1 = pop();
2005-08-06 22:57:37 +02:00
if (!istensor(p1)) { // might be zero
2004-03-03 21:24:06 +01:00
push(p1);
return;
}
n = p1->u.tensor->nelem;
for (i = 0; i < n; i++) {
push(p1->u.tensor->elem[i]);
rationalize();
p1->u.tensor->elem[i] = pop();
}
push(p1);
}
2007-05-08 16:57:30 +02:00
#if SELFTEST
2004-03-03 21:24:06 +01:00
static char *s[] = {
"rationalize(a/b+c/d)",
"(a*d+b*c)/(b*d)",
"rationalize(t*y/(t+y)+2*t^2*y*(2*t+y)^(-2))",
2006-08-23 01:37:52 +02:00
"t*y*(6*t^2+y^2+6*t*y)/((t+y)*(2*t+y)^2)",
2004-03-03 21:24:06 +01:00
"rationalize(x^(-2*a)+x^(-4*a))",
"(1+x^(2*a))/(x^(4*a))",
"rationalize(x^(1/3)+x^(2/3))",
"x^(1/3)*(1+x^(1/3))",
};
void
test_rationalize(void)
{
test(__FILE__, s, sizeof s / sizeof (char *));
}
2007-05-08 16:57:30 +02:00
#endif
2004-03-03 21:24:06 +01:00
static void
__lcm(void)
{
save();
p1 = pop();
p2 = pop();
push(p1);
push(p2);
multiply();
push(p1);
push(p2);
gcd();
divide();
restore();
}