Fix cvtFast and tests

We might still want to change the actual behaviour though,
see the FIXME comments.
This commit is contained in:
Andrew Johnson
2016-03-16 09:44:35 -05:00
parent 4a5a675ef8
commit f97c1a345e
3 changed files with 90 additions and 50 deletions

View File

@@ -38,8 +38,15 @@ int cvtFloatToString(float flt_value, char *pdest,
char *startAddr;
/* can this routine handle this conversion */
if (isnan(flt_value) || precision > 8 || flt_value > 10000000.0 || flt_value < -10000000.0) {
sprintf(pdest,"%12.5e",(double)flt_value);
if (isnan(flt_value) || precision > 8 ||
flt_value > 10000000.0 || flt_value < -10000000.0) {
if (precision > 8 || flt_value >= 1e8 || flt_value <= -1e8) {
if (precision > 12) precision = 12; /* FIXME */
sprintf(pdest, "%*.*e", precision+6, precision, (double) flt_value);
} else {
if (precision > 3) precision = 3; /* FIXME */
sprintf(pdest, "%.*f", precision, (double) flt_value);
}
return((int)strlen(pdest));
}
startAddr = pdest;

View File

@@ -22,30 +22,44 @@ public:
void execute ();
protected:
char _pDst[128];
double _srcVal;
double _srcDbl;
float _srcFlt;
unsigned short _prec;
static unsigned const _nUnrolled = 10;
static const unsigned _uSecPerSec = 1000000;
static unsigned const _nIterations = 10000;
virtual const char *_name(void) = 0;
virtual int _maxPrecision(void) = 0;
virtual void _target () = 0;
void _measure ();
Test ( const Test & );
Test & operator = ( Test & );
};
class TestCvtFastDouble : public Test {
class TestCvtFastFloat : public Test {
protected:
void _target ();
const char *_name (void) { return "cvtFloatToString"; }
int _maxPrecision(void) { return 12; }
};
class TestCvtFastDouble : public Test {
protected:
void _target (void);
const char *_name (void) { return "cvtDoubleToString"; }
int _maxPrecision(void) { return 17; }
};
class TestSNPrintf : public Test {
protected:
void _target ();
const char *_name (void) { return "epicsSnprintf"; }
int _maxPrecision(void) { return 17; }
};
Test ::
Test () :
_srcVal ( 0.0 ), _prec ( 0 )
_srcDbl ( 0.0 ), _prec ( 0 )
{
}
@@ -55,28 +69,31 @@ Test :: ~Test ()
void Test :: execute ()
{
static const unsigned lowPrecision = 2;
static const unsigned highPrecision = DBL_MANT_DIG;
for ( unsigned i = 0; i < 3; i++ ) {
double mVal = rand ();
mVal /= (RAND_MAX + 1.0);
double fEVal = rand ();
fEVal /= (RAND_MAX + 1.0);
fEVal *= DBL_MAX_EXP - DBL_MIN_EXP;
fEVal += DBL_MIN_EXP;
int eVal = static_cast < int > ( fEVal + 0.5 );
_srcVal = ldexp ( mVal, eVal );
for ( _prec = lowPrecision;
_prec <= highPrecision; _prec += 4u ) {
double eVal = rand ();
eVal /= (RAND_MAX + 1.0);
double dVal = eVal;
dVal *= DBL_MAX_EXP - DBL_MIN_EXP;
dVal += DBL_MIN_EXP;
int dEVal = static_cast < int > ( dVal + 0.5 );
float fVal = eVal;
fVal *= FLT_MAX_EXP - FLT_MIN_EXP;
fVal += FLT_MIN_EXP;
int fEVal = static_cast < int > ( fVal + 0.5 );
_srcDbl = ldexp ( mVal, dEVal );
_srcFlt = ldexpf ( mVal, fEVal );
for ( _prec = 0; _prec <= _maxPrecision(); _prec++ ) {
_measure ();
}
_srcVal = rand ();
_srcVal /= (RAND_MAX + 1.0);
_srcVal *= 10.0;
_srcVal -= 5.0;
for ( _prec = lowPrecision;
_prec <= highPrecision; _prec += 4u ) {
_srcDbl = rand ();
_srcDbl /= (RAND_MAX + 1.0);
_srcDbl *= 10.0;
_srcDbl -= 5.0;
_srcFlt = (float) _srcDbl;
for ( _prec = 0; _prec <= _maxPrecision(); _prec++ ) {
_measure ();
}
}
@@ -91,56 +108,72 @@ void Test :: _measure ()
epicsTime end = epicsTime :: getCurrent ();
double elapsed = end - beg;
elapsed /= _nIterations * _nUnrolled;
elapsed *= _uSecPerSec;
printf ( " %4.4f usec, prec=%i, val=%4.4g, for %s\n",
elapsed, _prec, _srcVal, typeid ( *this ).name () );
printf ( "%17s: %12.9f sec, prec=%2i, out=%s\n",
this->_name (), elapsed, _prec, _pDst );
}
void TestCvtFastFloat :: _target ()
{
cvtFloatToString ( _srcFlt, _pDst, _prec );
cvtFloatToString ( _srcFlt, _pDst, _prec );
cvtFloatToString ( _srcFlt, _pDst, _prec );
cvtFloatToString ( _srcFlt, _pDst, _prec );
cvtFloatToString ( _srcFlt, _pDst, _prec );
cvtFloatToString ( _srcFlt, _pDst, _prec );
cvtFloatToString ( _srcFlt, _pDst, _prec );
cvtFloatToString ( _srcFlt, _pDst, _prec );
cvtFloatToString ( _srcFlt, _pDst, _prec );
cvtFloatToString ( _srcFlt, _pDst, _prec );
}
void TestCvtFastDouble :: _target ()
{
cvtDoubleToString ( _srcVal, _pDst, _prec );
cvtDoubleToString ( _srcVal, _pDst, _prec );
cvtDoubleToString ( _srcVal, _pDst, _prec );
cvtDoubleToString ( _srcVal, _pDst, _prec );
cvtDoubleToString ( _srcVal, _pDst, _prec );
cvtDoubleToString ( _srcDbl, _pDst, _prec );
cvtDoubleToString ( _srcDbl, _pDst, _prec );
cvtDoubleToString ( _srcDbl, _pDst, _prec );
cvtDoubleToString ( _srcDbl, _pDst, _prec );
cvtDoubleToString ( _srcDbl, _pDst, _prec );
cvtDoubleToString ( _srcVal, _pDst, _prec );
cvtDoubleToString ( _srcVal, _pDst, _prec );
cvtDoubleToString ( _srcVal, _pDst, _prec );
cvtDoubleToString ( _srcVal, _pDst, _prec );
cvtDoubleToString ( _srcVal, _pDst, _prec );
cvtDoubleToString ( _srcDbl, _pDst, _prec );
cvtDoubleToString ( _srcDbl, _pDst, _prec );
cvtDoubleToString ( _srcDbl, _pDst, _prec );
cvtDoubleToString ( _srcDbl, _pDst, _prec );
cvtDoubleToString ( _srcDbl, _pDst, _prec );
}
void TestSNPrintf :: _target ()
{
epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g",
static_cast < int > ( _prec ), _srcVal );
static_cast < int > ( _prec ), _srcDbl );
epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g",
static_cast < int > ( _prec ), _srcVal );
static_cast < int > ( _prec ), _srcDbl );
epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g",
static_cast < int > ( _prec ), _srcVal );
static_cast < int > ( _prec ), _srcDbl );
epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g",
static_cast < int > ( _prec ), _srcVal );
static_cast < int > ( _prec ), _srcDbl );
epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g",
static_cast < int > ( _prec ), _srcVal );
static_cast < int > ( _prec ), _srcDbl );
epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g",
static_cast < int > ( _prec ), _srcVal );
static_cast < int > ( _prec ), _srcDbl );
epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g",
static_cast < int > ( _prec ), _srcVal );
static_cast < int > ( _prec ), _srcDbl );
epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g",
static_cast < int > ( _prec ), _srcVal );
static_cast < int > ( _prec ), _srcDbl );
epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g",
static_cast < int > ( _prec ), _srcVal );
static_cast < int > ( _prec ), _srcDbl );
epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g",
static_cast < int > ( _prec ), _srcVal );
static_cast < int > ( _prec ), _srcDbl );
}
MAIN(cvtFastPerform)
{
TestCvtFastFloat testCvtFastFloat;
TestCvtFastDouble testCvtFastDouble;
TestSNPrintf testSNPrintf;
testCvtFastFloat.execute ();
testCvtFastDouble.execute ();
testSNPrintf.execute ();

View File

@@ -326,12 +326,12 @@ MAIN(cvtFastTest)
testDiag("------------------------------------------------------");
testDiag("** Positive Float scientific **");
tryFString(Float, 1e+08, 0, 6);
tryFString(Float, 1e+08, 1, 8);
tryFString(Float, 1e+08, 2, 9);
tryFString(Float, 1e+08, 3, 10);
tryFString(Float, 1e+08, 4, 11);
tryFString(Float, 1e+08, 5, 12);
tryFString(Float, 1e+08, 6, 13);
tryFString(Float, 1e+08, 1, 7);
tryFString(Float, 1e+08, 2, 8);
tryFString(Float, 1e+08, 3, 9);
tryFString(Float, 1e+08, 4, 10);
tryFString(Float, 1e+08, 5, 11);
tryFString(Float, 1e+08, 6, 12);
testDiag("------------------------------------------------------");
testDiag("** Positive Double fixed-point **");