Beispiel #1
0
 static int
count(Static *S, ograd **ogp)
{
	int i, rv, nz, *s, *z;
	double t, *x;
	ograd *og, *og1;

	s = s_s;
	x = s_x;
	z = s_z;

	t = 0;
	nz = rv = 0;
	for(og = *ogp; og; og = og1) {
		og1 = og->next;
		if ((i = og->varno) < 0)
			t += og->coef;
		else if (!s[i]++)
			x[z[nz++] = i] = og->coef;
		else
			x[i] += og->coef;
		free_og(S, og);
		}
	while(nz > 0) {
		s[i = z[--nz]] = 0;
		if (x[i]) {
			og = new_og(S, og, i, x[i]);
			rv++;
			}
		}
	if (t)
		og = new_og(S, og, -1, t);
	*ogp = og;
	return rv;
	}
Beispiel #2
0
 static void
free_oglist(Static *S, ograd *og)
{
	ograd *og1;

	for(; og; og = og1) {
		og1 = og->next;
		free_og(S, og);
		}
	}
Beispiel #3
0
 static term *
ewalk(Static *S, expr *e)
{
	term *L, *R, *T;
	ograd *o, *oR;
	expr **ep, **epe;
	int i;
	ASL_fg *asl;

	switch(Intcast e->op) {

	  case OPNUM:
		return new_term(S, new_og(S, 0, -1 , ((expr_n *)e)->v));

	  case OPPLUS:
		return termsum(S, ewalk(S, e->L.e), ewalk(S, e->R.e));

	  case OPMINUS:
		return termsum(S, ewalk(S, e->L.e), scale(S, ewalk(S, e->R.e), -1.));

	  case OPUMINUS:
		return scale(S, ewalk(S, e->L.e), -1.);

	  case OPMULT:
		if (!(L = ewalk(S, e->L.e))
		 || !(R = ewalk(S, e->R.e)))
			break;
		if (L->Q) {
			if (R->Q)
				break;
 qscale:
			o = R->L;
			if (o->next || o->varno >= 0)
				break;
			scale(S, L, o->coef);
			free_og(S, o);
			free_term(S, R);
			return L;
			}
		if (R->Q) {
			T = L;
			L = R;
			R = T;
			goto qscale;
			}
		o = L->L;
		oR = R->L;
		if (o->next || o->varno >= 0) {
			if (oR->next || oR->varno >= 0) {
				L->Q = L->Qe = new_dyad(S, 0,o,oR,1);
				L->L = L->Le = 0;
				}
			else {
				scale(S, L, oR->coef);
				free_og(S, oR);
				}
			free_term(S, R);
			return L;
			}
		scale(S, R, o->coef);
		free_og(S, o);
		free_term(S, L);
		return R;

	  case OPDIV:
		/* only allow division by a constant */
		if (!(R = ewalk(S, e->R.e)))
			break;
		o = R->L;
		if (R->Q || o->next || o->varno >= 0)
			break;
		if (!(L = ewalk(S, e->L.e)))
			break;
		if (!o->coef) {
			zerodiv++;
			L = 0;
			}
		else
			scale(S, L, 1./o->coef);
		free_og(S, o);
		free_term(S, R);
		return L;

	  case OPSUMLIST:
		ep = e->L.ep;
		epe = e->R.ep;
		L = ewalk(S, *ep);
		while(L && ++ep < epe)
			L = termsum(S, L, ewalk(S, *ep));
		return L;

	  case OP2POW:
		L = ewalk(S, e->L.e);
		if (!L || L->Q)
			break;
		o = L->L;
		if (!o->next && o->varno < 0) {
			o->coef *= o->coef;
			return L;
			}
		L->Q = L->Qe = new_dyad(S, 0,o,o,1);
		L->L = L->Le = 0;
		return L;

	  case OPVARVAL:
		asl = S->asl;
		if ((i = (expr_v *)e - var_e) < n_var)
			return new_term(S, new_og(S, 0, i, 1.));
		i -= S->nvinc;
		if (!(L = cterms[i -= n_var])
		 && !(L = cterms[i] = comterm(S, i)))
			return 0;
		return termdup(S, L);
		}
	return 0; /* nonlinear */
	}
Beispiel #4
0
 static ograd *
linform(LCADJ_Info *lci, expr *e, ograd **oglp)
{
	ASL_fg *asl;
	cexp *ce;
	cexp1 *ce1;
	expr **ep, **epe;
	expr_n *en;
	int i;
	linpart *L, *Le;
	ograd *og, *og1, *og1e, *og2, *og2e, *og2x, **ogp;
	real t;

	switch(Intcast e->op) {

	  case OPNUM:
		return *oglp = new_og(lci, -1, ((expr_n *)e)->v);

	  case OPPLUS:
		if (!(og1 = linform(lci, e->L.e, &og1e)))
			return og1;
		if (!(og2 = linform(lci, e->R.e, &og2e))) {
			free_og(lci, og1, og1e);
			return og2;
			}
 finish_plus:
		if (og1->varno > og2->varno) {
			og = og1;
			og1 = og2;
			og2 = og;
			og = og1e;
			og1e = og2e;
			og2e = og;
			}
		else for(og = og1; og; og = og->next) {
			if (!og2) {
				og2e = og1e;
				break;
				}
			if (og2->varno != og->varno)
				break;
			og->coef += og2->coef;
			og2x = og2->next;
			og2->next = lci->freeog;
			lci->freeog = og2;
			og2 = og2x;
			}
		og1e->next = og2;
		*oglp = og2e;
		return og1;

	  case OPMINUS:
		if (!(og1 = linform(lci, e->L.e, &og1e)))
			return og1;
		if (!(og2 = linform(lci, e->R.e, &og2e))) {
			free_og(lci, og1, og1e);
			return og2;
			}
		for(og = og2; og; og = og->next)
			og->coef = -og->coef;
		goto finish_plus;

	  case OPUMINUS:
		if ((og1 = linform(lci, e->L.e, oglp))) {
			og2 = og1;
			do og2->coef = -og2->coef;
				while((og2 = og2->next));
			}
		return og1;

	  case OPMULT:
		if (!(og1 = linform(lci, e->L.e, &og1e)))
			return og1;
		if (!(og2 = linform(lci, e->R.e, &og2e))) {
			free_og(lci, og1, og1e);
			return og2;
			}
		if (og1->varno < 0 && !og1->next) {
			t = og1->coef;
			free_og(lci, og1, og1e);
			}
		else if (og2->varno < 0 && !og2->next) {
			t = og2->coef;
			free_og(lci, og2, og2e);
			og2 = og1;
			og2e = og1e;
			}
		else {
			free_og(lci, og1, og1e);
			free_og(lci, og2, og2e);
			return 0;
			}
		for(og = og2; og; og = og->next)
			og->coef *= t;
		*oglp = og2e;
		return og2;

	  case OPDIV:
		/* only allow division by a constant */
		if (!(og1 = linform(lci, e->L.e, &og1e)))
			return og1;
		if (!(og2 = linform(lci, e->L.e, &og2e))) {
			free_og(lci, og1, og1e);
			return og2;
			}
		if (og2->varno < 0 && !og2->next) {
			t = og2->coef;
			free_og(lci, og2, og2e);
			}
		else {
			free_og(lci, og1, og1e);
			free_og(lci, og2, og2e);
			return 0;
			}
		for(og = og1; og; og = og->next)
			og->coef /= t;
		*oglp = og1e;
		return og1;

	  case OPSUMLIST:
		ep = e->L.ep;
		epe = e->R.ep;
		if (!(og1 = linform(lci, *ep, &og1e)))
			return og1;
		while(++ep < epe) {
			if (!(og2 = linform(lci, *ep, &og2e))) {
				free_og(lci, og1, og1e);
				return og2;
				}
			if (og1->varno > og2->varno) {
				og = og1;
				og1 = og2;
				og2 = og;
				og = og1e;
				og1e = og2e;
				og2e = og;
				}
			else for(og = og1; og; og = og->next) {
				if (!og2) {
					og2e = og1e;
					break;
					}
				if (og2->varno != og->varno)
					break;
				og->coef += og2->coef;
				og2x = og2->next;
				og2->next = lci->freeog;
				lci->freeog = og2;
				og2 = og2x;
				}
			og1e->next = og2;
			og1e = og2e;
			}
		*oglp = og1e;
		return og1;

	  case OPVARVAL:
		asl = (ASL_fg*)lci->asl;
		if ((i = (expr_v *)e - var_e) < n_var)
			return *oglp = new_og(lci, i, 1.);
		if ((i -= n_var) < ncom0) {
			ce = cexps + i;
			en = (expr_n*)ce->e;
			L =  ce->L;
			Le = L + ce->nlin;
			}
		else {
			ce1 = cexps1 + (i - ncom0);
			en = (expr_n*)ce1->e;
			L = ce1->L;
			Le = L + ce1->nlin;
			}
		if ((Intcast en->op) != OPNUM)
			return 0;
		ogp = &og2;
		if (en->v != 0.) {
			og2 = new_og(lci, -1, en->v);
			ogp = &og2->next;
			}
		for(og = 0; L < Le; L++) {
			i = (expr_v*)((char*)L->v.rp - (char*)voffset_of(expr_v,v)) - var_e;
			og = *ogp = new_og(lci, i, L->fac);
			ogp = &og->next;
			}
		*ogp = 0;
		*oglp = og;
		return og2;
	  }
	return 0;
	}