- if (nvar == 1 && cval == def)
- {
- /* If there is exactly one nonconstant term and no constant
- terms, replace with the nonconstant term. */
- for (i = 0; i < n->n; i++)
- if (n->arg[i]->type != OP_NUM_CON)
- m = (struct nonterm_node *) n->arg[i];
- else
- free_node (n->arg[i]);
- }
- else
- {
- /* Otherwise consolidate all the nonconstant terms. */
- m = xmalloc (sizeof (struct nonterm_node)
- + ((nvar + (cval != def) - 1)
- * sizeof (union any_node *)));
- for (i = c = 0; i < n->n; i++)
- if (n->arg[i]->type != OP_NUM_CON)
- m->arg[c++] = n->arg[i];
- else
- free_node (n->arg[i]);
-
- if (cval != def)
- {
- m->arg[c] = xmalloc (sizeof (struct num_con_node));
- m->arg[c]->num_con.type = OP_NUM_CON;
- m->arg[c]->num_con.value = cval;
- c++;
- }
-
- m->type = n->type;
- m->n = c;
- }
- free (n);
- n = m;
- }
- else if (n->type == OP_POW)
+static void
+optimize_tree (union any_node **node)
+{
+ struct nonterm_node *n = &(*node)->nonterm;
+
+ /* x+0, x-0, 0+x => x. */
+ if ((n->type == OP_ADD || n->type == OP_SUB) && eq_num_con (n->arg[1], 0.))
+ collapse_node (node, 1);
+ else if (n->type == OP_ADD && eq_num_con (n->arg[0], 0.))
+ collapse_node (node, 0);
+
+ /* x*1, x/1, 1*x => x. */
+ else if ((n->type == OP_MUL || n->type == OP_DIV)
+ && eq_num_con (n->arg[1], 1.))
+ collapse_node (node, 0);
+ else if (n->type == OP_MUL && eq_num_con (n->arg[0], 1.))
+ collapse_node (node, 1);
+
+ /* 0*x, 0/x, x*0, MOD(0,x) => x. */
+ else if (((n->type == OP_MUL || n->type == OP_DIV || n->type == OP_MOD)
+ && eq_num_con (n->arg[0], 0.))
+ || (n->type == OP_MUL && eq_num_con (n->arg[1], 0.)))
+ set_number (node, 0.);
+
+ /* x**1 => x. */
+ else if (n->type == OP_POW && eq_num_con (n->arg[1], 1))
+ collapse_node (node, 0);
+
+ /* x**2 => SQUARE(x). */
+ else if (n->type == OP_POW && eq_num_con (n->arg[2], 2))