Files
SAPFOR/dvm/fdvm/trunk/Sage/lib/oldsrc/symb_alg.c
2023-09-14 19:43:13 +03:00

1051 lines
26 KiB
C

/*********************************************************************/
/* pC++/Sage++ Copyright (C) 1993 */
/* Indiana University University of Oregon University of Rennes */
/*********************************************************************/
/* file: symb_alg.c */
#include "db.h"
extern PTR_LLND make_llnd();
extern PTR_FILE cur_file;
/*
* The following routines are used to evaluate low level expressions
*/
int get_symbs(n, p, s)
PTR_LLND p;
PTR_SYMB s[];
int n;
{
int i;
if (p == NULL)
return (n);
if (p->variant == VAR_REF) {
for (i = 0; i < n; i++)
if (s[i] == p->entry.Template.symbol)
break;
if (i == n) {
s[n++] = p->entry.Template.symbol;
}
}
n = get_symbs(n, p->entry.Template.ll_ptr1, s);
n = get_symbs(n, p->entry.Template.ll_ptr2, s);
return (n);
}
int eval_exp(p, s, vals, n, valu) /* returns 0 on failure */
int n;
PTR_LLND p;
PTR_SYMB s[];
int vals[];
int *valu;
{
int i, lv, rv, rs, ls;
if (p == NULL)
return (0);
if (p->variant == INT_VAL) {
*valu = p->entry.ival;
return (1);
}
if (p->variant == VAR_REF) {
for (i = 0; i < n; i++)
if (s[i] == p->entry.Template.symbol) {
*valu = vals[i];
return (1);
}
return (0);
}
lv = 0;
rv = 0;
rs = 0;
ls = 0;
rs = eval_exp(p->entry.Template.ll_ptr2, s, vals, n, &rv);
ls = eval_exp(p->entry.Template.ll_ptr1, s, vals, n, &lv);
switch (p->variant) {
case MINUS_OP:
*valu = -lv;
break;
case ADD_OP:
*valu = lv + rv;
break;
case MULT_OP:
*valu = lv * rv;
break;
case DIV_OP:
*valu = (rv != 0) ? lv / rv : 0;
break;
case SUBT_OP:
*valu = lv - rv;
break;
default:
fprintf(stderr, "bad op: %d\n", p->variant);
return (0);
}
if (p->variant != MINUS_OP)
return (rs * ls);
else
return (ls);
}
/* returns 1 if p and q are constant or linear in the same var */
/* and 0 otherwise. result = 1 if p is less than q for a large value */
/* and result = 0 otherwise */
int numerical_less(p, q, result)
PTR_LLND p, q;
int *result;
{
PTR_SYMB psyms[20], qsyms[20];
int pvals[20], qvals[20];
int pn, qn, pv, qv, ps, qs;
pn = 0;
qn = 0;
pv = 0;
qv = 0;
qs = 0;
ps = 0;
pn = get_symbs(pn, p, psyms);
qn = get_symbs(qn, q, qsyms);
if (pn > 1 || qn > 1)
return (0);
if (pn == 1 && qn == 1 && psyms[0] != qsyms[0])
return (0);
pvals[0] = 512;
qvals[0] = 512;
ps = eval_exp(p, psyms, pvals, pn, &pv);
qs = eval_exp(q, qsyms, qvals, qn, &qv);
if (ps * qs == 0)
return (0);
*result = (pv < qv) ? 1 : 0;
return (1);
}
int less(p, q)
PTR_LLND p, q;
{
char *name1, *name2;
int i;
if (p->variant == MINUS_OP)
p = p->entry.Template.ll_ptr1;
if (q->variant == MINUS_OP)
q = q->entry.Template.ll_ptr1;
if (q->variant == INT_VAL) {
if (p->variant == INT_VAL) {
if (p->entry.ival < q->entry.ival)
return (1);
else
return (0);
}
else
return (1);
}
if (p->variant == INT_VAL)
return (0);
if (p->variant == VAR_REF && q->variant == VAR_REF) {
name1 = p->entry.Template.symbol->ident;
name2 = q->entry.Template.symbol->ident;
i = 0;
while (name1[i] != '\0' && name2[i] != '\0') {
if (name1[i] > name2[i])
return (0);
if (name1[i] < name2[i])
return (1);
i++;
}
if (name1[i] == '\0' && name2[i] != '\0')
return (1);
else
return (0);
}
if (p->variant == VAR_REF)
return (1);
if (q->variant == VAR_REF)
return (0);
return (0);
}
int rest_constant(p)
PTR_LLND p;
{
if (p == NULL)
return (1);
if (p->variant == INT_VAL)
return (1);
if (p->variant == MINUS_OP)
return (rest_constant(p->entry.Template.ll_ptr1));
if (p->variant == MULT_OP)
return (rest_constant(p->entry.Template.ll_ptr1) *
rest_constant(p->entry.Template.ll_ptr2));
if (p->variant == DIV_OP)
return (rest_constant(p->entry.Template.ll_ptr1) *
rest_constant(p->entry.Template.ll_ptr2));
return (0);
}
int term_less(p, q)
PTR_LLND p, q;
{
PTR_LLND p_rchld, q_rchld;
/* assume in normal form */
if (p == NULL && q == NULL)
return (0);
if (p == NULL)
return (1);
if (q == NULL)
return (0);
if (p->variant == MINUS_OP)
p = p->entry.Template.ll_ptr1;
if (q->variant == MINUS_OP)
q = q->entry.Template.ll_ptr1;
if (p->variant == DIV_OP && q->variant == DIV_OP) {
p_rchld = p->entry.Template.ll_ptr2;
q_rchld = q->entry.Template.ll_ptr2;
if (less(p_rchld, q_rchld))
return (1);
if (less(q_rchld, p_rchld))
return (0);
/* must be equal */
return (term_less(p->entry.Template.ll_ptr1,
q->entry.Template.ll_ptr1));
}
if (p->variant == DIV_OP && q->variant != DIV_OP) {
if (rest_constant(p->entry.Template.ll_ptr1))
return (term_less(p->entry.Template.ll_ptr2, q));
}
if (p->variant == MULT_OP && q->variant != MULT_OP) {
if (rest_constant(p->entry.Template.ll_ptr1))
return (term_less(p->entry.Template.ll_ptr2, q));
}
if (p->variant != DIV_OP && q->variant == DIV_OP) {
if (rest_constant(q->entry.Template.ll_ptr1))
return (term_less(p, q->entry.Template.ll_ptr2));
}
if (p->variant != MULT_OP && q->variant == MULT_OP) {
if (rest_constant(q->entry.Template.ll_ptr1))
return (term_less(p, q->entry.Template.ll_ptr2));
}
if (p->variant == MULT_OP && q->variant == MULT_OP) {
p_rchld = p->entry.Template.ll_ptr2;
q_rchld = q->entry.Template.ll_ptr2;
if (less(p_rchld, q_rchld))
return (1);
if (less(q_rchld, p_rchld))
return (0);
/* must be equal */
return (term_less(p->entry.Template.ll_ptr1, q->entry.Template.ll_ptr1));
}
/* both not mult */
return (less(p, q));
}
void sort_term(p)
PTR_LLND p;
{
int notdone;
PTR_LLND q;
PTR_LLND lchild, rchild, gchild;
if(p == NULL) return;
if (p->variant == MINUS_OP)
p = p->entry.Template.ll_ptr1;
if (p->variant != MULT_OP && p->variant != DIV_OP)
return;
notdone = 1;
while (notdone) {
q = p;
notdone = 0;
while (q != NULL && q->entry.Template.ll_ptr1 != NULL) {
lchild = q->entry.Template.ll_ptr1;
rchild = q->entry.Template.ll_ptr2;
if(lchild == NULL || rchild == NULL) return;
if (lchild->variant == INT_VAL && rchild->variant == INT_VAL) {
notdone = 1;
if (q->variant == SUBT_OP)
q->entry.ival = lchild->entry.ival - rchild->entry.ival;
else if (q->variant == ADD_OP)
q->entry.ival = rchild->entry.ival + lchild->entry.ival;
else if (q->variant == MULT_OP)
q->entry.ival = rchild->entry.ival * lchild->entry.ival;
else if (q->variant == DIV_OP &&
rchild->entry.ival != 0)
q->entry.ival = lchild->entry.ival / rchild->entry.ival;
else
q->entry.ival = 888888;
q->variant = INT_VAL;
/* better dispose of lchild and rchild later */
q->entry.Template.ll_ptr1 = NULL;
q->entry.Template.ll_ptr2 = NULL;
}
else if ((q->variant == MULT_OP &&
lchild->variant != MULT_OP && lchild->variant != DIV_OP)
&& less(lchild, rchild)) {
notdone = 1;
q->entry.Template.ll_ptr1 = rchild;
q->entry.Template.ll_ptr2 = lchild;
}
else if (q->variant == MULT_OP && lchild->variant == MULT_OP) {
gchild = lchild->entry.Template.ll_ptr2;
if (rchild->variant == INT_VAL && gchild->variant == INT_VAL) {
notdone = 1;
rchild->entry.ival = rchild->entry.ival * gchild->entry.ival;
q->entry.Template.ll_ptr1 = lchild->entry.Template.ll_ptr1;
}
else if (less(gchild, rchild)) {
notdone = 1;
q->entry.Template.ll_ptr2 = gchild;
lchild->entry.Template.ll_ptr2 = rchild;
}
}
q = q->entry.Template.ll_ptr1;
}
}
}
void sort_exp(p)
PTR_LLND p;
{
int notdone, var;
PTR_LLND q, q1;
PTR_LLND lchild, rchild, gchild;
q = p;
while (q != NULL && (q->variant != ADD_OP && q->variant != SUBT_OP)) {
if (q != NULL && (q->variant == MULT_OP || q->variant == DIV_OP))
sort_term(q);
if (q->variant == DIV_OP) {
if (q->entry.Template.ll_ptr1->variant == ADD_OP ||
q->entry.Template.ll_ptr1->variant == SUBT_OP)
sort_exp(q->entry.Template.ll_ptr1);
if (q->entry.Template.ll_ptr2->variant == ADD_OP ||
q->entry.Template.ll_ptr2->variant == SUBT_OP)
sort_exp(q->entry.Template.ll_ptr2);
}
q = q->entry.Template.ll_ptr1;
}
q1 = q;
if (q1 == NULL)
return;
while (q != NULL) {
if (q->variant == ADD_OP || q->variant == SUBT_OP)
sort_term(q->entry.Template.ll_ptr2);
else if (q->variant == MULT_OP || q->variant == DIV_OP)
sort_term(q);
if (q->variant == ADD_OP || q->variant == SUBT_OP)
q = q->entry.Template.ll_ptr1;
else
q = NULL;
}
notdone = 1;
q = q1;
while (notdone) {
q = p;
notdone = 0;
while (q != NULL && q->variant != MULT_OP && q->variant != DIV_OP &&
q->entry.Template.ll_ptr1 != NULL) {
lchild = q->entry.Template.ll_ptr1;
rchild = q->entry.Template.ll_ptr2;
if(lchild == NULL || rchild == NULL) return; /* should never happen! */
if (lchild->variant == INT_VAL && rchild->variant == INT_VAL) {
var = q->variant;
q->variant = INT_VAL;
if (var == ADD_OP)
q->entry.ival = lchild->entry.ival + rchild->entry.ival;
else
q->entry.ival = lchild->entry.ival - rchild->entry.ival;
q->entry.Template.ll_ptr1 = NULL;
q->entry.Template.ll_ptr2 = NULL;
notdone = 1;
}
else if ((lchild->variant != ADD_OP && lchild->variant != SUBT_OP)
&& term_less(lchild, rchild)) {
notdone = 1;
q->entry.Template.ll_ptr1 = rchild;
q->entry.Template.ll_ptr2 = lchild;
if (q->variant == SUBT_OP) {
q->variant = ADD_OP;
lchild = make_llnd(cur_file, INT_VAL, NULL, NULL, 0);
q->entry.Template.ll_ptr1=make_llnd(cur_file,SUBT_OP,lchild,rchild,
NULL);
}
}
else if (lchild->variant == ADD_OP || lchild->variant == SUBT_OP) {
gchild = lchild->entry.Template.ll_ptr2;
if (term_less(gchild, rchild)) {
notdone = 1;
q->entry.Template.ll_ptr2 = gchild;
lchild->entry.Template.ll_ptr2 = rchild;
var = q->variant;
q->variant = lchild->variant;
lchild->variant = var;
}
}
q = q->entry.Template.ll_ptr1;
}
}
}
PTR_LLND copy_llnd(p)
PTR_LLND p;
{
PTR_LLND newp;
if (p == NULL)
return (NULL);
newp = make_llnd(cur_file, p->variant, NULL, NULL, p->entry.Template.symbol);
newp->entry.Template.ll_ptr1 = copy_llnd(p->entry.Template.ll_ptr1);
newp->entry.Template.ll_ptr2 = copy_llnd(p->entry.Template.ll_ptr2);
return (newp);
}
int integer_difference(p,q, value, dif)
PTR_LLND p,q, *dif;
int *value;
{
PTR_LLND s;
void simplify(), normal_form();
s = make_llnd(cur_file, SUBT_OP, copy_llnd(p),copy_llnd(q), NULL);
normal_form(&s);
*dif = s;
if(s->variant == INT_VAL){
*value = s->entry.ival;
return 1;
}
else if (s->variant == MINUS_OP){
s = s->entry.Template.ll_ptr1;
*value = -s->entry.ival;
return 1;
}
return 0;
}
int no_division(p)
PTR_LLND p;
{
return (1);
#if 0
while (p != NULL && p->variant == MULT_OP)
p = p->entry.Template.ll_ptr1;
if (p == NULL)
return (1);
if (p->variant == DIV_OP)
return (0);
return (1);
#endif
}
void expand(p)
PTR_LLND p;
{
PTR_LLND lson, rson, lgchld, rgchld, cpy, new;
if (p == NULL)
return;
if (p->variant == MULT_OP) {
lson = p->entry.Template.ll_ptr1;
rson = p->entry.Template.ll_ptr2;
if (lson->variant == MULT_OP) {
expand(p->entry.Template.ll_ptr1);
lson = p->entry.Template.ll_ptr1;
}
if (rson->variant == MULT_OP) {
expand(p->entry.Template.ll_ptr2);
rson = p->entry.Template.ll_ptr2;
}
if ((lson->variant == ADD_OP || lson->variant == SUBT_OP)) {
lgchld = lson->entry.Template.ll_ptr1;
rgchld = lson->entry.Template.ll_ptr2;
cpy = copy_llnd(rson);
new = make_llnd(cur_file, MULT_OP, rgchld, rson, NULL);
lson->entry.Template.ll_ptr1 = lgchld;
lson->entry.Template.ll_ptr2 = cpy;
p->entry.Template.ll_ptr2 = new;
p->variant = lson->variant;
lson->variant = MULT_OP;
}
else if ((rson->variant == ADD_OP || rson->variant == SUBT_OP) &&
no_division(rson->entry.Template.ll_ptr2) &&
no_division(rson->entry.Template.ll_ptr1)) {
lgchld = rson->entry.Template.ll_ptr1;
rgchld = rson->entry.Template.ll_ptr2;
cpy = copy_llnd(lson);
new = make_llnd(cur_file, MULT_OP, lson, lgchld, NULL);
rson->entry.Template.ll_ptr1 = cpy;
rson->entry.Template.ll_ptr2 = rgchld;
p->entry.Template.ll_ptr1 = new;
p->variant = rson->variant;
rson->variant = MULT_OP;
}
}
expand(p->entry.Template.ll_ptr2);
expand(p->entry.Template.ll_ptr1);
}
void left_allign_term(p) /* need fix for divide, similar to - fix
* below */
PTR_LLND *p;
{
PTR_LLND root_rc, tail_r_chain, last_r_chain, q;
if (*p == NULL)
return;
if ((*p)->variant == MULT_OP) {
if ((*p)->entry.Template.ll_ptr2->variant != DIV_OP)
left_allign_term(&((*p)->entry.Template.ll_ptr2));
left_allign_term(&((*p)->entry.Template.ll_ptr1));
/* now link these together */
root_rc = (*p)->entry.Template.ll_ptr2;
q = root_rc;
last_r_chain = NULL;
while (q->variant == MULT_OP /* || q->variant == DIV_OP */ ) {
last_r_chain = q;
q = q->entry.Template.ll_ptr1;
}
tail_r_chain = q;
if (root_rc == tail_r_chain)
return;
last_r_chain->entry.Template.ll_ptr1 = *p;
(*p)->entry.Template.ll_ptr2 = tail_r_chain;
*p = root_rc;
}
if ((*p)->variant == DIV_OP) {
left_allign_term(&((*p)->entry.Template.ll_ptr1));
left_allign_term(&((*p)->entry.Template.ll_ptr2));
}
return;
}
void left_allign_exp(p)
PTR_LLND *p;
{
PTR_LLND root_rc, tail_r_chain, last_r_chain, q;
if (*p == NULL)
return;
if ((*p)->variant == ADD_OP || (*p)->variant == SUBT_OP) {
left_allign_exp(&((*p)->entry.Template.ll_ptr1));
left_allign_exp(&((*p)->entry.Template.ll_ptr2));
/* now link these together */
root_rc = (*p)->entry.Template.ll_ptr2;
if(root_rc == NULL) return;
if ((*p)->variant == SUBT_OP) {
for (q = root_rc; q != NULL &&
(q->variant == ADD_OP || q->variant == SUBT_OP);
q = q->entry.Template.ll_ptr1)
if (q->variant == SUBT_OP)
q->variant = ADD_OP;
else if (q->variant == ADD_OP)
q->variant = SUBT_OP;
}
q = root_rc;
last_r_chain = NULL;
while (q->variant == ADD_OP || q->variant == SUBT_OP) {
last_r_chain = q;
q = q->entry.Template.ll_ptr1;
}
tail_r_chain = q;
if (root_rc == tail_r_chain)
return;
last_r_chain->entry.Template.ll_ptr1 = *p;
(*p)->entry.Template.ll_ptr2 = tail_r_chain;
*p = root_rc;
}
else if ((*p)->variant == MULT_OP || (*p)->variant == DIV_OP) {
left_allign_term(p);
}
else {
left_allign_exp(&((*p)->entry.Template.ll_ptr1));
left_allign_exp(&((*p)->entry.Template.ll_ptr2));
}
return;
}
void clear_unary_minus(p)
PTR_LLND p;
{
PTR_LLND after_minus;
while (p != NULL &&
p->variant != ADD_OP && p->variant != SUBT_OP)
p = p->entry.Template.ll_ptr1;
if (p == NULL)
return;
if (p->variant == ADD_OP || p->variant == SUBT_OP) {
if (p->entry.Template.ll_ptr2->variant == MINUS_OP) {
after_minus =
p->entry.Template.ll_ptr2->entry.Template.ll_ptr1;
p->entry.Template.ll_ptr2 = after_minus;
if (p->variant == ADD_OP)
p->variant = SUBT_OP;
else
p->variant = ADD_OP;
}
clear_unary_minus(p->entry.Template.ll_ptr1);
}
}
int get_term_coef(p)
PTR_LLND p;
{
int sign, lval;
sign = 1;
while (p != NULL && p->variant == MINUS_OP) {
p = p->entry.Template.ll_ptr1;
sign = -sign;
}
if (p == NULL)
return (sign);
if (p->variant == ADD_OP || p->variant == SUBT_OP)
/* should only happen with division as parent */
return (1);
if (p->variant == VAR_REF)
return (sign);
if (p->variant == INT_VAL)
return (sign * p->entry.ival);
if (p->variant == MULT_OP) {
lval = sign * get_term_coef(p->entry.Template.ll_ptr1);
if (p->entry.Template.ll_ptr2->variant == INT_VAL)
return (lval * p->entry.Template.ll_ptr2->entry.ival);
else
return (lval);
}
if (p->variant == DIV_OP) {
return (sign);
}
else {
fprintf(stderr, "bad coeficient extraction in get_term_coef\n");
return (1);
}
}
void replace_coef(p, v)
PTR_LLND p;
int v;
{
PTR_LLND new_int, new_var, q;
if (p == NULL) {
fprintf(stderr, "replace_coef failed\n");
return;
}
if (p->variant == INT_VAL) {
p->entry.ival = v;
return;
}
if (p->variant == ADD_OP || p->variant == SUBT_OP) {
if (v == 1)
return;
replace_coef(p->entry.Template.ll_ptr1, v);
replace_coef(p->entry.Template.ll_ptr2, v);
return;
}
if (p->variant == VAR_REF) {
if (v == 1)
return;
p->variant = MULT_OP;
new_int = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
new_int->entry.ival = v;
new_var = make_llnd(cur_file, VAR_REF,NULL,NULL,p->entry.Template.symbol);
p->entry.Template.ll_ptr1 = new_int;
p->entry.Template.ll_ptr2 = new_var;
p->entry.Template.symbol = NULL;
return;
}
else if (v == 1 && p->variant == MULT_OP &&
rest_constant(p->entry.Template.ll_ptr1)) {
new_var = p->entry.Template.ll_ptr2;
p->variant = new_var->variant;
p->entry.Template.symbol = new_var->entry.Template.symbol;
p->entry.Template.ll_ptr1 = new_var->entry.Template.ll_ptr1;
p->entry.Template.ll_ptr2 = new_var->entry.Template.ll_ptr2;
}
else if (p->variant == MULT_OP &&
p->entry.Template.ll_ptr1->variant == DIV_OP)
replace_coef(p->entry.Template.ll_ptr2, v);
else if (p->variant == DIV_OP) {
if (v == 1)
return;
q = make_llnd(cur_file, DIV_OP, p->entry.Template.ll_ptr1,
p->entry.Template.ll_ptr2, NULL);
p->entry.Template.ll_ptr1 = q;
p->variant = MULT_OP;
new_int = make_llnd(cur_file, INT_VAL, NULL, NULL, NULL);
new_int->entry.ival = v;
p->entry.Template.ll_ptr2 = new_int;
}
else
replace_coef(p->entry.Template.ll_ptr1, v);
}
int identical(p, q)
PTR_LLND p, q;
{
if (q == NULL && p == NULL)
return (1);
if (q == NULL && p != NULL)
return (0);
if (q != NULL && p == NULL)
return (0);
/* now p and q not null */
if (p->variant != q->variant)
return (0);
switch (p->variant) {
case VAR_REF:
return (p->entry.Template.symbol == q->entry.Template.symbol);
case ARRAY_REF:
if (p->entry.Template.symbol != q->entry.Template.symbol)
return (0);
else
return (identical(q->entry.Template.ll_ptr1,
p->entry.Template.ll_ptr1) *
identical(q->entry.Template.ll_ptr2,
p->entry.Template.ll_ptr2));
case INT_VAL:
return (p->entry.ival == q->entry.ival);
default:
return (identical(q->entry.Template.ll_ptr1,
p->entry.Template.ll_ptr1) *
identical(q->entry.Template.ll_ptr2,
p->entry.Template.ll_ptr2));
}
}
int same_upto_coef(p, q)
PTR_LLND p, q;
{
PTR_LLND plc, prc, qlc, qrc;
if (p == NULL && q == NULL)
return (1);
if (p == NULL)
return (0);
if (q == NULL)
return (0);
if (p->variant == MINUS_OP)
p = p->entry.Template.ll_ptr1;
if (q->variant == MINUS_OP)
q = q->entry.Template.ll_ptr1;
if (rest_constant(p) && rest_constant(q))
return (1);
plc = p->entry.Template.ll_ptr1;
prc = p->entry.Template.ll_ptr2;
qlc = q->entry.Template.ll_ptr1;
qrc = q->entry.Template.ll_ptr2;
if (p->variant == VAR_REF) {
if (q->variant == VAR_REF) {
if (p->entry.Template.symbol == q->entry.Template.symbol)
return (1);
else
return (0);
}
else if (q->variant == MULT_OP || q->variant == DIV_OP) {
if (rest_constant(qlc) &&
qrc->variant == VAR_REF &&
qrc->entry.Template.symbol == p->entry.Template.symbol
)
return (1);
else
return (0);
}
else
return (0);
}
else if (q->variant == VAR_REF) {
if (p->variant == MULT_OP || p->variant == DIV_OP) {
if (rest_constant(plc) &&
prc->variant == VAR_REF &&
prc->entry.Template.symbol == q->entry.Template.symbol
)
return (1);
else
return (0);
}
else
return (0);
}
else if ((p->variant == ADD_OP && q->variant == ADD_OP) ||
(p->variant == SUBT_OP && q->variant == SUBT_OP) ||
(p->variant == DIV_OP && q->variant == DIV_OP))
return (identical(p, q));
else if (p->variant == MULT_OP && q->variant == DIV_OP) {
if ( (rest_constant(prc) && same_upto_coef(plc, q))
||
(rest_constant(plc) && same_upto_coef(prc, q)) )
return (1);
else
return (0);
}
else if (q->variant == MULT_OP && p->variant == DIV_OP) {
if ( (rest_constant(qrc) && same_upto_coef(qlc, p))
||
(rest_constant(qlc) && same_upto_coef(qrc, p)) )
return (1);
else
return (0);
}
else if (p->variant == q->variant) {
if (same_upto_coef(plc, qlc) && same_upto_coef(prc, qrc))
return (1);
else
return (0);
}
else
return (0);
}
void simplify(p)
PTR_LLND *p;
{
PTR_LLND q, left, lower, right, qlast, qnext;
PTR_LLND rec_nrm_frm();
int not_done, val, var, vl, vr, lvar;
/* clear_unary_minus(*p); */
not_done = 1;
if ((*p)->variant == MULT_OP || (*p)->variant == DIV_OP ||
(*p)->variant == ADD_OP || (*p)->variant == SUBT_OP) {
if((*p)->entry.Template.ll_ptr1 == NULL) return;
if ((*p)->entry.Template.ll_ptr1->variant != VAR_REF &&
(*p)->entry.Template.ll_ptr1->variant != INT_VAL)
(*p)->entry.Template.ll_ptr1 =
rec_nrm_frm((*p)->entry.Template.ll_ptr1);
if((*p)->entry.Template.ll_ptr2 == NULL) return;
if ((*p)->entry.Template.ll_ptr2->variant != VAR_REF &&
(*p)->entry.Template.ll_ptr2->variant != INT_VAL)
(*p)->entry.Template.ll_ptr2 =
rec_nrm_frm((*p)->entry.Template.ll_ptr2);
}
while (not_done) {
not_done = 0;
q = *p;
qlast = NULL;
while (q != NULL && q->variant != MULT_OP && q->variant != DIV_OP &&
q->entry.Template.ll_ptr1 != NULL) {
var = q->variant;
if (var == ADD_OP || var == SUBT_OP) {
right = q->entry.Template.ll_ptr2;
left = q->entry.Template.ll_ptr1;
if (left->variant != ADD_OP && left->variant != SUBT_OP) {
if (same_upto_coef(left, right)) {
not_done = 1;
vl = get_term_coef(left);
vr = get_term_coef(right);
if (var == ADD_OP)
val = vl + vr;
else
val = vl - vr;
if (val == 0) {
if (qlast != NULL) {
qlast->entry.Template.ll_ptr1 =
make_llnd(cur_file, INT_VAL, NULL, NULL, 0);
}
else
*p = make_llnd(cur_file, INT_VAL, NULL, NULL, 0);
}
else {
if (val < 0) {
if (var == ADD_OP)
q->variant = SUBT_OP;
else
q->variant = ADD_OP;
val = -val;
}
replace_coef(right, val);
q->variant = right->variant;
if (right->variant != VAR_REF)
q->entry.Template.symbol = NULL;
else
q->entry.Template.symbol =
right->entry.Template.symbol;
q->entry.Template.ll_ptr1
= right->entry.Template.ll_ptr1;
q->entry.Template.ll_ptr2
= right->entry.Template.ll_ptr2;
}
}
}
else {
lvar = left->variant;
lower = left->entry.Template.ll_ptr2;
if (same_upto_coef(lower, right)) {
not_done = 1;
vl = get_term_coef(lower);
vr = get_term_coef(right);
if (var == ADD_OP)
val = vr;
else
val = -vr;
if (lvar == ADD_OP)
val = val + vl;
else
val = val - vl;
if (val == 0) {
if (qlast != NULL) {
qlast->entry.Template.ll_ptr1 =
left->entry.Template.ll_ptr1;
}
else
*p = left->entry.Template.ll_ptr1;
}
else {
q->variant = ADD_OP;
if (val >= 0)
replace_coef(right, val);
else {
replace_coef(right, -val);
q->variant = SUBT_OP;
}
q->entry.Template.ll_ptr1 =
left->entry.Template.ll_ptr1;
}
}
}
}
qlast = q;
q = q->entry.Template.ll_ptr1;
}
} /* end of outer while */
/* now eliminate left over 0 terms. */
q = *p;
qlast = NULL;
qnext = NULL;
while (q != NULL && ((qnext = q->entry.Template.ll_ptr1) != NULL)
&& (q->variant == ADD_OP || q->variant == SUBT_OP)
&& (qnext->variant == ADD_OP || qnext->variant == SUBT_OP)) {
qlast = q;
q = q->entry.Template.ll_ptr1;
}
if (qnext == NULL)
return;
if (qnext->variant == INT_VAL && qnext->entry.ival == 0) {
if (q->variant == ADD_OP) {
if (qlast != NULL) {
qlast->entry.Template.ll_ptr1 =
q->entry.Template.ll_ptr2;
/* dispose of q and qnext */
}
else {
*p = q->entry.Template.ll_ptr2;
/* dispose of q and qnext */
}
}
else if (q->variant == SUBT_OP) {
q->variant = MINUS_OP;
q->entry.Template.ll_ptr1 =
q->entry.Template.ll_ptr2;
q->entry.Template.ll_ptr2 = NULL;
/* dispose of qnext */
}
}
}
PTR_LLND
rec_nrm_frm(cp)
PTR_LLND cp;
{
expand(cp);
left_allign_exp(&cp);
sort_exp(cp);
simplify(&cp);
return (cp);
}
void elim_stupid_expr_list(p)
PTR_LLND *p;
{
if (*p == NULL)
return;
if ((*p)->variant == INT_VAL || (*p)->variant == VAR_REF)
return;
if ((*p)->variant == EXPR_LIST) {
if ((*p)->entry.Template.ll_ptr2 == NULL)
p = &((*p)->entry.Template.ll_ptr1);
else
return;
}
elim_stupid_expr_list(&((*p)->entry.Template.ll_ptr1));
elim_stupid_expr_list(&((*p)->entry.Template.ll_ptr2));
}
PTR_LLND norm_frm_exp(p)
PTR_LLND p;
{
PTR_LLND cp;
cp = copy_llnd(p);
elim_stupid_expr_list(&cp);
return (rec_nrm_frm(cp));
}
void normal_form(p)
PTR_LLND *p;
{
if (p == NULL)
return;
if (*p == NULL)
return;
switch ((*p)->variant) {
case STAR_RANGE:
break;
case ARRAY_REF:
normal_form(&((*p)->entry.Template.ll_ptr1));
break;
case RANGE_LIST:
case EXPR_LIST:
normal_form(&((*p)->entry.Template.ll_ptr1));
normal_form(&((*p)->entry.Template.ll_ptr2));
break;
case DDOT:
normal_form(&((*p)->entry.Template.ll_ptr1));
normal_form(&((*p)->entry.Template.ll_ptr2));
break;
case ADD_OP:
case SUBT_OP:
case MULT_OP:
case DIV_OP:
case MINUS_OP:
case VAR_REF:
case INT_VAL:
*p = norm_frm_exp(*p);
break;
default:
fprintf(stderr, "bad case in normal_form %d\n", (*p)->variant);
break;
}
}