Corrected property value merging (again). By the rules of the

re-worked property command, "critical" properties must match
across devices so that all other properties can be combined as
specified (addition, parallel combination, or none).  The code was
still based on the older notion of the "critical" property being
the one to add (and thus preventing multiple properties from being
added in different ways).  This has now been fixed.
This commit is contained in:
Tim Edwards 2019-05-17 11:25:34 -04:00
parent 8e0371e09b
commit f40a50d3b8
1 changed files with 53 additions and 35 deletions

View File

@ -3782,7 +3782,7 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
vl = &(obp->instance.props[p]);
if (vl->type == PROP_ENDLIST) break;
if (vl->key == NULL) continue;
if (!strcmp(vl->key, "S")) {
if ((*matchfunc)(vl->key, "S")) {
sval = vl->value.ival;
sl = vl;
}
@ -3906,7 +3906,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
vl = &(obp->instance.props[p]);
if (vl->type == PROP_ENDLIST) break;
if (vl->key == NULL) continue;
if (!strcmp(vl->key, "M")) {
if ((*matchfunc)(vl->key, "M")) {
mval = vl->value.ival;
ml = vl;
}
@ -3952,7 +3952,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
vl = &(obp->instance.props[p]);
if (vl->type == PROP_ENDLIST) break;
if (vl->key == NULL) continue;
if (!strcmp(vl->key, "M")) {
if ((*matchfunc)(vl->key, "M")) {
mval = vl->value.ival;
ml = vl;
}
@ -3960,7 +3960,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
if (kl == NULL) continue; /* Ignored property */
if (subs_crit == NULL)
subs_crit = vl->key;
if ((subs_crit != NULL) && !strcmp(vl->key, subs_crit)) {
if ((subs_crit != NULL) && (*matchfunc)(vl->key, subs_crit)) {
if ((vl->type == PROP_STRING || vl->type == PROP_EXPRESSION) &&
(kl->type != vl->type))
PromoteProperty(kl, vl);
@ -4338,6 +4338,7 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
{
struct objlist *ob2, *obt;
struct property *kl, *m_rec, **plist;
unsigned char **clist;
struct valuelist ***vlist, *vl, *vl2, *newvlist;
proplinkptr plink, ptop;
int pcount, p, i, j, k, pmatch, ival, crit, ctype;
@ -4363,7 +4364,6 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
ptop = NULL;
pcount = 1;
crit = -1;
ctype = -1;
kl = (struct property *)HashFirst(&(tp->propdict));
while (kl != NULL) {
// Make a linked list so we don't have to iterate through the hash again
@ -4382,13 +4382,9 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
if (series == FALSE) {
if (kl->merge & MERGE_P_CRIT) crit = kl->idx;
if (kl->merge & (MERGE_P_ADD | MERGE_P_PAR))
ctype = kl->merge & (MERGE_P_ADD | MERGE_P_PAR);
}
else if (series == TRUE) {
if (kl->merge & MERGE_S_CRIT) crit = kl->idx;
if (kl->merge & (MERGE_S_ADD | MERGE_S_PAR))
ctype = kl->merge & (MERGE_S_ADD | MERGE_S_PAR);
}
kl = (struct property *)HashNext(&(tp->propdict));
@ -4396,13 +4392,17 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
// Recast the linked list as an array
plist = (struct property **)CALLOC(pcount, sizeof(struct property *));
vlist = (struct valuelist ***)CALLOC(pcount, sizeof(struct valuelist **));
if (m_rec == NULL)
clist = (unsigned char **)CALLOC(pcount, sizeof(unsigned char *));
if (m_rec == NULL) {
vlist[0] = (struct valuelist **)CALLOC(run, sizeof(struct valuelist *));
clist[0] = (unsigned char *)CALLOC(run, sizeof(unsigned char));
}
while (ptop != NULL) {
plist[ptop->prop->idx] = ptop->prop;
vlist[ptop->prop->idx] = (struct valuelist **)CALLOC(run,
sizeof(struct valuelist *));
clist[ptop->prop->idx] = (unsigned char *)CALLOC(run, sizeof(unsigned char));
plink = ptop;
FREE(ptop);
ptop = plink->next;
@ -4436,6 +4436,14 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
}
else if (kl != NULL) {
vlist[kl->idx][i] = vl;
if (series == FALSE) {
if (kl->merge & (MERGE_P_ADD | MERGE_P_PAR))
clist[kl->idx][i] = kl->merge & (MERGE_P_ADD | MERGE_P_PAR);
}
else if (series == TRUE) {
if (kl->merge & (MERGE_S_ADD | MERGE_S_PAR))
clist[kl->idx][i] = kl->merge & (MERGE_S_ADD | MERGE_S_PAR);
}
}
}
if (++i == run) break;
@ -4600,32 +4608,40 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
mult = vlist[0][i]->value.ival;
if (mult > 1) {
changed = 0;
vl = vlist[crit][i];
if ((ctype == MERGE_S_ADD) || (ctype == MERGE_P_ADD)) {
if (vl->type == PROP_INTEGER)
vl->value.ival *= mult;
else if (vl->type == PROP_DOUBLE)
vl->value.dval *= (double)mult;
vlist[0][i]->value.ival = 1;
changed += mult;
}
else if ((ctype == MERGE_S_PAR) || (ctype == MERGE_P_PAR)) {
/* Technically one should check if divide-by-mult */
/* reduces the value to < 1 and promote to double */
/* if so, but that's a very unlikely case. */
if (vl->type == PROP_INTEGER)
vl->value.ival /= mult;
else if (vl->type == PROP_DOUBLE)
vl->value.dval /= (double)mult;
vlist[0][i]->value.ival = 1;
changed += mult;
}
if (changed > 0) {
if (series)
Printf("Combined %d series devices.\n", changed);
else
Printf("Combined %d parallel devices.\n", changed);
/* For all properties that are not M, S, or crit, */
/* combine as specified by the merge type of the property. */
for (p = 1; p < pcount; p++) {
if (p == crit) continue; /* critical properties never combine */
vl = vlist[p][i];
ctype = clist[p][i];
if ((ctype == MERGE_S_ADD) || (ctype == MERGE_P_ADD)) {
if (vl->type == PROP_INTEGER)
vl->value.ival *= mult;
else if (vl->type == PROP_DOUBLE)
vl->value.dval *= (double)mult;
vlist[0][i]->value.ival = 1;
changed += mult;
}
else if ((ctype == MERGE_S_PAR) || (ctype == MERGE_P_PAR)) {
/* Technically one should check if divide-by-mult */
/* reduces the value to < 1 and promote to double */
/* if so, but that's a very unlikely case. */
if (vl->type == PROP_INTEGER)
vl->value.ival /= mult;
else if (vl->type == PROP_DOUBLE)
vl->value.dval /= (double)mult;
vlist[0][i]->value.ival = 1;
changed += mult;
}
if (changed > 0) {
if (series)
Printf("Combined %d series devices.\n", changed);
else
Printf("Combined %d parallel devices.\n", changed);
}
}
}
}
@ -4652,9 +4668,11 @@ cleanup:
kl = (struct property *)plist[p];
if (kl) kl->idx = 0;
FREE(vlist[p]);
FREE(clist[p]);
}
FREE(plist);
FREE(vlist);
FREE(clist);
return changed;
}