Permit breakpoint tables to run any direction as long as the slope doesn't

change sign. Reduced memory requirement by making the table a contiguous
array rather than an array of pointers to intervals. Improved error reporting.
This commit is contained in:
Andrew Johnson
2006-10-26 16:05:23 +00:00
parent 5c7fa0e3be
commit 7dc2eec5aa
4 changed files with 219 additions and 157 deletions
+1 -1
View File
@@ -65,7 +65,7 @@ typedef struct brkTable { /* breakpoint table */
ELLNODE node;
char *name; /*breakpoint table name */
long number; /*number of brkInt in this table*/
struct brkInt **papBrkInt; /* ptr to array of ptr to brkInt */
struct brkInt *paBrkInt; /* ptr to array of brkInts */
}brkTable;
typedef struct dbFldDes{ /* field description */
+51 -44
View File
@@ -823,77 +823,84 @@ static void dbBreakHead(char *name)
static void dbBreakItem(char *value)
{
if(duplicate) return;
double dummy;
if (duplicate) return;
if (epicsScanDouble(value, &dummy) != 1) {
yyerrorAbort("Non-numeric value in breaktable");
}
allocTemp(epicsStrDup(value));
}
static void dbBreakBody(void)
{
brkTable *pnewbrkTable;
brkInt *paBrkInt;
brkTable *pbrkTable;
int number;
int number, down=0;
int i,choice;
GPHENTRY *pgphentry;
if(duplicate) {
if (duplicate) {
duplicate = FALSE;
return;
}
pnewbrkTable = (brkTable *)popFirstTemp();
pnewbrkTable->number = number = ellCount(&tempList)/2;
if(number*2 != ellCount(&tempList))
yyerrorAbort("dbBreakBody: Odd number of values");
pnewbrkTable->papBrkInt = dbCalloc(number,sizeof(brkInt));
for(i=0; i<number; i++) {
double raw,eng;
char *praw;
char *peng;
number = ellCount(&tempList);
if (number % 2) {
yyerrorAbort("breaktable: Raw value missing");
return;
}
number /= 2;
if (number < 2) {
yyerrorAbort("breaktable: Must have at least two points!");
return;
}
pnewbrkTable->number = number;
pnewbrkTable->paBrkInt = paBrkInt = dbCalloc(number, sizeof(brkInt));
for (i=0; i<number; i++) {
double val;
char *str;
praw = (char *)popFirstTemp();
peng = (char *)popFirstTemp();
if((epicsScanDouble(praw, &raw)!=1) || (sscanf(peng,"%lf",&eng)!=1) ) {
yyerrorAbort("dbbrkTable: Illegal table value");
}
free((void *)praw);
free((void *)peng);
pnewbrkTable->papBrkInt[i] = dbCalloc(1,sizeof(brkInt));
pnewbrkTable->papBrkInt[i]->raw = raw;
pnewbrkTable->papBrkInt[i]->eng = eng;
str = (char *)popFirstTemp();
epicsScanDouble(str, &paBrkInt[i].raw);
free(str);
str = (char *)popFirstTemp();
epicsScanDouble(str, &paBrkInt[i].eng);
free(str);
}
/* Compute slopes */
for(i=0; i<number-1; i++) {
pnewbrkTable->papBrkInt[i]->slope =
(pnewbrkTable->papBrkInt[i+1]->eng - pnewbrkTable->papBrkInt[i]->eng)/
(pnewbrkTable->papBrkInt[i+1]->raw - pnewbrkTable->papBrkInt[i]->raw);
}
if(number>1) {
pnewbrkTable->papBrkInt[number-1]->slope =
pnewbrkTable->papBrkInt[number-2]->slope;
for (i=0; i<number-1; i++) {
double slope =
(paBrkInt[i+1].eng - paBrkInt[i].eng)/
(paBrkInt[i+1].raw - paBrkInt[i].raw);
if (i == 0) {
down = (slope < 0);
} else if (down != (slope < 0)) {
yyerrorAbort("breaktable: curve slope changes sign");
return;
}
paBrkInt[i].slope = slope;
}
/* Continue with last slope beyond the final point */
paBrkInt[number-1].slope = paBrkInt[number-2].slope;
/* Add brkTable in sorted order */
pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
while(pbrkTable) {
choice = strcmp(pbrkTable->name,pnewbrkTable->name);
if(choice==0) {
ellInsert(&pdbbase->bptList,ellPrevious((ELLNODE *)pbrkTable),
(ELLNODE *)pnewbrkTable);
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
ellDelete(&pdbbase->bptList,(ELLNODE *)pbrkTable);
break;
} else if(choice>0) {
ellInsert(&pdbbase->bptList,ellPrevious((ELLNODE *)pbrkTable),
while (pbrkTable) {
if (strcmp(pbrkTable->name, pnewbrkTable->name) > 0) {
ellInsert(&pdbbase->bptList, ellPrevious((ELLNODE *)pbrkTable),
(ELLNODE *)pnewbrkTable);
break;
}
pbrkTable = (brkTable *)ellNext(&pbrkTable->node);
}
if (!pbrkTable) ellAdd(&pdbbase->bptList, &pnewbrkTable->node);
pgphentry = gphAdd(pdbbase->pgpHash,pnewbrkTable->name,&pdbbase->bptList);
if(!pgphentry) {
yyerrorAbort("gphAdd failed");
} else {
pgphentry->userPvt = pnewbrkTable;
if (!pgphentry) {
yyerrorAbort("dbBreakBody: gphAdd failed");
return;
}
if(!pbrkTable) ellAdd(&pdbbase->bptList,&pnewbrkTable->node);
pgphentry->userPvt = pnewbrkTable;
}
static void dbRecordHead(char *recordType,char *name, int visible)
+16 -13
View File
@@ -716,8 +716,7 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase)
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
ellDelete(&pdbbase->bptList,&pbrkTable->node);
free(pbrkTable->name);
for(i=0; i<pbrkTable->number; i++)
free((void *)(pbrkTable->papBrkInt[i]));
free((void *)pbrkTable->paBrkInt);
free((void *)pbrkTable);
pbrkTable = pbrkTableNext;
}
@@ -1225,18 +1224,20 @@ long epicsShareAPI dbWriteBreaktableFP(DBBASE *pdbbase,FILE *fp)
{
brkTable *pbrkTable;
brkInt *pbrkInt;
int ind;
int i;
if(!pdbbase) {
if (!pdbbase) {
fprintf(stderr,"pdbbase not specified\n");
return(-1);
}
for(pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
pbrkTable; pbrkTable = (brkTable *)ellNext(&pbrkTable->node)) {
for (pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
pbrkTable;
pbrkTable = (brkTable *)ellNext(&pbrkTable->node)) {
fprintf(fp,"breaktable(%s) {\n",pbrkTable->name);
for(ind=0; ind<pbrkTable->number; ind++) {
pbrkInt = pbrkTable->papBrkInt[ind];
fprintf(fp,"\t%e %e\n",pbrkInt->raw,pbrkInt->eng);
pbrkInt = pbrkTable->paBrkInt;
for(i=0; i < pbrkTable->number; i++) {
fprintf(fp,"\t%e, %e\n",pbrkInt->raw,pbrkInt->eng);
pbrkInt++;
}
fprintf(fp,"}\n");
}
@@ -3856,11 +3857,13 @@ void epicsShareAPI dbDumpBreaktable(DBBASE *pdbbase,const char *name)
}
for(pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
pbrkTable; pbrkTable = (brkTable *)ellNext(&pbrkTable->node)) {
if(name && strcmp(name,pbrkTable->name)!=0) continue;
if (name && strcmp(name,pbrkTable->name)!=0) continue;
printf("breaktable(%s) {\n",pbrkTable->name);
for(ind=0; ind<pbrkTable->number; ind++) {
pbrkInt = pbrkTable->papBrkInt[ind];
printf("\t%f %e %f\n",pbrkInt->raw,pbrkInt->slope,pbrkInt->eng);
pbrkInt = pbrkTable->paBrkInt;
for(ind=0; ind < pbrkTable->number; ind++) {
printf("\traw=%f slope=%e eng=%f\n",
pbrkInt->raw, pbrkInt->slope, pbrkInt->eng);
pbrkInt++;
}
printf("}\n");
}