Improve handling of NaN values.
In selRecord, replaced the 1e30 'magic number' with NaN and Inf values.
This commit is contained in:
+4
-3
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsMath.h"
|
||||
#include "alarm.h"
|
||||
#include "cvtTable.h"
|
||||
#include "dbAccess.h"
|
||||
@@ -285,7 +286,7 @@ static void checkAlarms(aiRecord *pai)
|
||||
double hyst, lalm, hihi, high, low, lolo;
|
||||
unsigned short hhsv, llsv, hsv, lsv;
|
||||
|
||||
if(pai->udf == TRUE ){
|
||||
if (pai->udf) {
|
||||
recGblSetSevr(pai,UDF_ALARM,INVALID_ALARM);
|
||||
return;
|
||||
}
|
||||
@@ -355,7 +356,7 @@ static void convert(aiRecord *pai)
|
||||
}else{
|
||||
pai->val = val;
|
||||
}
|
||||
pai->udf = FALSE;
|
||||
pai->udf = isnan(pai->val);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -419,7 +420,7 @@ static long readValue(aiRecord *pai)
|
||||
status = dbGetLink(&(pai->siol),DBR_DOUBLE,&(pai->sval),0,0);
|
||||
if (status==0){
|
||||
pai->val=pai->sval;
|
||||
pai->udf=FALSE;
|
||||
pai->udf=isnan(pai->val);
|
||||
}
|
||||
status=2; /* dont convert */
|
||||
} else {
|
||||
|
||||
+5
-4
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "epicsPrint.h"
|
||||
#include "epicsMath.h"
|
||||
#include "alarm.h"
|
||||
#include "cvtTable.h"
|
||||
#include "dbAccess.h"
|
||||
@@ -121,7 +122,7 @@ static long init_record(struct aoRecord *pao, int pass)
|
||||
/* get the initial value if dol is a constant*/
|
||||
if (pao->dol.type == CONSTANT) {
|
||||
if(recGblInitConstantLink(&pao->dol,DBF_DOUBLE,&pao->val))
|
||||
pao->udf = FALSE;
|
||||
pao->udf = isnan(pao->val);
|
||||
}
|
||||
|
||||
/* must have write_ao function defined */
|
||||
@@ -156,7 +157,7 @@ static long init_record(struct aoRecord *pao, int pass)
|
||||
(void *)&pao->pbrk,&pao->lbrk)!=0) break;
|
||||
}
|
||||
pao->val = value;
|
||||
pao->udf=FALSE;
|
||||
pao->udf = isnan(value);
|
||||
break;
|
||||
case(2): /* no convert */
|
||||
break;
|
||||
@@ -193,6 +194,7 @@ static long process(pao)
|
||||
value = pao->val;
|
||||
}
|
||||
if(!status) convert(pao, value);
|
||||
pao->udf = isnan(pao->val);
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
@@ -356,7 +358,7 @@ static void checkAlarms(pao)
|
||||
double hyst, lalm, hihi, high, low, lolo;
|
||||
unsigned short hhsv, llsv, hsv, lsv;
|
||||
|
||||
if(pao->udf == TRUE ){
|
||||
if (pao->udf) {
|
||||
recGblSetSevr(pao,UDF_ALARM,INVALID_ALARM);
|
||||
return;
|
||||
}
|
||||
@@ -413,7 +415,6 @@ static long fetch_value(pao,pvalue)
|
||||
recGblSetSevr(pao,LINK_ALARM,INVALID_ALARM);
|
||||
return(status);
|
||||
}
|
||||
pao->udf = FALSE;
|
||||
|
||||
if (pao->oif == aoOIF_Incremental)
|
||||
*pvalue += pao->val;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "epicsPrint.h"
|
||||
#include "epicsMath.h"
|
||||
#include "alarm.h"
|
||||
#include "dbAccess.h"
|
||||
#include "dbEvent.h"
|
||||
@@ -100,7 +101,7 @@ static long init_record(struct dfanoutRecord *pdfanout, int pass)
|
||||
recGblInitConstantLink(&pdfanout->sell,DBF_USHORT,&pdfanout->seln);
|
||||
/* get the initial value dol is a constant*/
|
||||
if(recGblInitConstantLink(&pdfanout->dol,DBF_DOUBLE,&pdfanout->val))
|
||||
pdfanout->udf=FALSE;
|
||||
pdfanout->udf = isnan(pdfanout->val);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -113,7 +114,7 @@ static long process(struct dfanoutRecord *pdfanout)
|
||||
&& (pdfanout->omsl == menuOmslclosed_loop)){
|
||||
status = dbGetLink(&(pdfanout->dol),DBR_DOUBLE,&(pdfanout->val),0,0);
|
||||
if(pdfanout->dol.type!=CONSTANT && RTN_SUCCESS(status))
|
||||
pdfanout->udf=FALSE;
|
||||
pdfanout->udf = isnan(pdfanout->val);
|
||||
}
|
||||
pdfanout->pact = TRUE;
|
||||
recGblGetTimeStamp(pdfanout);
|
||||
@@ -208,7 +209,7 @@ static void checkAlarms(struct dfanoutRecord *pdfanout)
|
||||
double hyst, lalm, hihi, high, low, lolo;
|
||||
unsigned short hhsv, llsv, hsv, lsv;
|
||||
|
||||
if(pdfanout->udf == TRUE ){
|
||||
if (pdfanout->udf) {
|
||||
recGblSetSevr(pdfanout,UDF_ALARM,INVALID_ALARM);
|
||||
return;
|
||||
}
|
||||
|
||||
+14
-9
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "epicsPrint.h"
|
||||
#include "epicsMath.h"
|
||||
#include "alarm.h"
|
||||
#include "dbAccess.h"
|
||||
#include "dbEvent.h"
|
||||
@@ -89,6 +90,9 @@ static int do_sel();
|
||||
static int fetch_values();
|
||||
static void monitor();
|
||||
|
||||
/* This needed to prevent the MS optimizer from barfing */
|
||||
static double divide(double num, double den) { return num / den; }
|
||||
|
||||
|
||||
static long init_record(psel,pass)
|
||||
struct selRecord *psel;
|
||||
@@ -97,6 +101,7 @@ static long init_record(psel,pass)
|
||||
struct link *plink;
|
||||
int i;
|
||||
double *pvalue;
|
||||
double NaN = divide(0.0, 0.0);
|
||||
|
||||
if (pass==0) return(0);
|
||||
|
||||
@@ -108,7 +113,7 @@ static long init_record(psel,pass)
|
||||
plink = &psel->inpa;
|
||||
pvalue = &psel->a;
|
||||
for(i=0; i<SEL_MAX; i++, plink++, pvalue++) {
|
||||
*pvalue = 1e+30;
|
||||
*pvalue = NaN;
|
||||
if (plink->type==CONSTANT) {
|
||||
recGblInitConstantLink(plink,DBF_DOUBLE,pvalue);
|
||||
}
|
||||
@@ -260,7 +265,7 @@ static void checkAlarms(psel)
|
||||
double hyst, lalm, hihi, high, low, lolo;
|
||||
unsigned short hhsv, llsv, hsv, lsv;
|
||||
|
||||
if(psel->udf == TRUE ){
|
||||
if (psel->udf){
|
||||
recGblSetSevr(psel,UDF_ALARM,INVALID_ALARM);
|
||||
return;
|
||||
}
|
||||
@@ -358,16 +363,16 @@ struct selRecord *psel; /* pointer to selection record */
|
||||
val = *(pvalue+psel->seln);
|
||||
break;
|
||||
case (SELECT_HIGH):
|
||||
val = -1e+30;
|
||||
val = divide(-1.0, 0.0); /* Start at -Inf */
|
||||
for (i = 0; i < SEL_MAX; i++,pvalue++){
|
||||
if (val < *pvalue && *pvalue != 1e+30)
|
||||
if (!isnan(*pvalue) && val < *pvalue)
|
||||
val = *pvalue;
|
||||
}
|
||||
break;
|
||||
case (SELECT_LOW):
|
||||
val = 1e+30;
|
||||
val = divide(1.0, 0.0); /* Start at +Inf */
|
||||
for (i = 0; i < SEL_MAX; i++,pvalue++){
|
||||
if (val > *pvalue && *pvalue != 1e+30)
|
||||
if (!isnan(*pvalue) && val > *pvalue)
|
||||
val = *pvalue;
|
||||
}
|
||||
break;
|
||||
@@ -375,7 +380,7 @@ struct selRecord *psel; /* pointer to selection record */
|
||||
plink = &psel->inpa;
|
||||
order_inx = 0;
|
||||
for (i = 0; i < SEL_MAX; i++,pvalue++,plink++){
|
||||
if (*pvalue != 1e+30){
|
||||
if (!isnan(*pvalue)){
|
||||
j = order_inx;
|
||||
while ((order[j-1] > *pvalue) && (j > 0)){
|
||||
order[j] = order[j-1];
|
||||
@@ -391,9 +396,9 @@ struct selRecord *psel; /* pointer to selection record */
|
||||
recGblSetSevr(psel,SOFT_ALARM,MAJOR_ALARM);
|
||||
return(-1);
|
||||
}
|
||||
if (val != 1e+30 && val != -1e+30 ){
|
||||
if (!isinf(val)){
|
||||
psel->val=val;
|
||||
psel->udf=FALSE;
|
||||
psel->udf=isnan(psel->val);
|
||||
} else {
|
||||
recGblSetSevr(psel,UDF_ALARM,MAJOR_ALARM);
|
||||
/* If UDF is TRUE this alarm will be overwritten by checkAlarms*/
|
||||
|
||||
+3
-2
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "epicsPrint.h"
|
||||
#include "epicsMath.h"
|
||||
#include "registryFunction.h"
|
||||
#include "alarm.h"
|
||||
#include "callback.h"
|
||||
@@ -267,7 +268,7 @@ static void checkAlarms(psub)
|
||||
double hyst, lalm, hihi, high, low, lolo;
|
||||
unsigned short hhsv, llsv, hsv, lsv;
|
||||
|
||||
if(psub->udf == TRUE ){
|
||||
if (psub->udf) {
|
||||
recGblSetSevr(psub,UDF_ALARM,INVALID_ALARM);
|
||||
return;
|
||||
}
|
||||
@@ -378,6 +379,6 @@ struct subRecord *psub; /* pointer to subroutine record */
|
||||
status = (*psubroutine)(psub);
|
||||
if(status < 0){
|
||||
recGblSetSevr(psub,SOFT_ALARM,psub->brsv);
|
||||
} else psub->udf = FALSE;
|
||||
} else psub->udf = isnan(psub->val);
|
||||
return(status);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user