There is a problem with break-point table conversion from engineering to
raw values ( function cvtEngToRawBpt in file cvtBpt.c).
The function returns incorrect results, if the breakpoint table has
negative slopes, i.e. if engineering values decrease with increasing
raw values.
The faulty routine and one possible fix are attached below.
Here is the printout from a test program, which converts raw values to
engineering values and back to raw values:
Breakpoint Table:
0 -- 186 475 slope -0.203488
1 -- 358 440 slope -0.196078
2 -- 562 400 slope -0.199601
3 -- 1063 300 slope -0.207612
4 -- 1641 180 slope -0.22409
5 -- 1998 100 slope -0.257732
6 -- 2192 50 slope -0.266667
7 -- 2267 30 slope -0.101695
8 -- 2326 24 slope -0.0261438
9 -- 2632 16 slope -0.0217391
10 -- 2908 10 slope -0.0139373
11 -- 3195 6 slope -0.0152672
raw eng raw
bit: 500 ==> 412.157 ==> 494.829 (index 1 0)
bit: 800 ==> 352.495 ==> 788.025 (index 2 0)
bit: 1100 ==> 292.318 ==> 1083.75 (index 3 0)
bit: 1400 ==> 230.035 ==> 1389.83 (index 3 0)
bit: 1700 ==> 166.779 ==> 1700.69 (index 4 0)
bit: 2000 ==> 99.4845 ==> 2031.39 (index 5 0)
bit: 2300 ==> 26.6441 ==> 2389.35 (index 7 0)
bit: 2600 ==> 16.8366 ==> 2437.55 (index 8 0)
bit: 2900 ==> 10.1739 ==> 2470.29 (index 9 0)
>>>>>>>>>>>>>> faulty function
long cvtEngToRawBpt(double *pval,short linr,short init,
void **ppbrk,short *plbrk)
{ double val=*pval;
long status=0;
brkTable *pbrkTable;
brkInt *pInt; brkInt *pnxtInt;
short lbrk;
int number;
if(linr < 2) return(-1);
if(init==TRUE || *ppbrk == NULL) { /*must find breakpoint table*/
pbrkTable = findBrkTable(linr);
if(!pbrkTable) return(S_dbLib_badField);
*ppbrk = (void *)pbrkTable;
/* Just start at the beginning */
*plbrk=0;
}
pbrkTable = (struct brkTable *)*ppbrk;
number = pbrkTable->number;
lbrk = *plbrk;
/*make sure we dont go off end of table*/
if( (lbrk+1) >= number ) lbrk--;
pInt = pbrkTable->papBrkInt[lbrk];
pnxtInt = pbrkTable->papBrkInt[lbrk+1];
/* find entry for increased value */
while( (pnxtInt->eng) <= val ) {
lbrk++;
pInt = pbrkTable->papBrkInt[lbrk];
if( lbrk >= number-1) {
status=1;
break;
}
pnxtInt = pbrkTable->papBrkInt[lbrk+1];
}
while( (pInt->eng) > val) {
if(lbrk==0) {
status=1;
break;
}
lbrk--;
pInt = pbrkTable->papBrkInt[lbrk];
}
if(pInt->slope!=0){
*plbrk = lbrk;
*pval = pInt->raw + (val - pInt->eng) / pInt->slope;
}
else {
return(status);
}
return(0);
}
*>>>>>>>>>>>>>> possible fix*
long cvtEngToRawBpt(double *pval,short linr,short init,
void **ppbrk,short *plbrk)
{ double val=*pval;
long status=0;
brkTable *pbrkTable;
brkInt *pInt; brkInt *pnxtInt;
short lbrk;
int number;
if(linr < 2) return(-1);
if(init==TRUE || *ppbrk == NULL) { /*must find breakpoint table*/
pbrkTable = findBrkTable(linr);
if(!pbrkTable) return(S_dbLib_badField);
*ppbrk = (void *)pbrkTable;
/* Just start at the beginning */
*plbrk=0;
}
pbrkTable = (struct brkTable *)*ppbrk;
number = pbrkTable->number;
lbrk = *plbrk;
/*make sure we dont go off end of table*/
if( (lbrk+1) >= number ) lbrk--;
pInt = pbrkTable->papBrkInt[lbrk];
pnxtInt = pbrkTable->papBrkInt[lbrk+1];
if (pInt->slope > 0) { /* positive slopes */
/* find entry for increased value */
while( (pnxtInt->eng) <= val ) {
lbrk++;
pInt = pbrkTable->papBrkInt[lbrk];
if( lbrk >= number-1) {
status=1;
break;
}
pnxtInt = pbrkTable->papBrkInt[lbrk+1];
}
while( (pInt->eng) > val) {
if(lbrk==0) {
status=1;
break;
}
lbrk--;
pInt = pbrkTable->papBrkInt[lbrk];
}
} else { /* negative slopes */
/* find entry for decreased value */
while( (pnxtInt->eng) >= val ) {
lbrk++;
pInt = pbrkTable->papBrkInt[lbrk];
if( lbrk >= number-1) {
status=1;
break;
}
pnxtInt = pbrkTable->papBrkInt[lbrk];
}
while( (pInt->eng) < val) {
if(lbrk==0) {
status=1;
break;
}
lbrk--;
pInt = pbrkTable->papBrkInt[lbrk];
}
}
if(pInt->slope!=0){
*plbrk = lbrk;
*pval = pInt->raw + (val - pInt->eng) / pInt->slope;
}
else {
return(status);
}
return(0);
}