diff --git a/src/libCom/cvtFast/cvtFast.c b/src/libCom/cvtFast/cvtFast.c index 3fb6a3d05..4e04b4515 100644 --- a/src/libCom/cvtFast/cvtFast.c +++ b/src/libCom/cvtFast/cvtFast.c @@ -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; diff --git a/src/libCom/test/cvtFastPerform.cpp b/src/libCom/test/cvtFastPerform.cpp index f8ae7c270..86bbcbd8a 100644 --- a/src/libCom/test/cvtFastPerform.cpp +++ b/src/libCom/test/cvtFastPerform.cpp @@ -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 (); diff --git a/src/libCom/test/cvtFastTest.c b/src/libCom/test/cvtFastTest.c index 48c14d02e..cb7eeaf8a 100644 --- a/src/libCom/test/cvtFastTest.c +++ b/src/libCom/test/cvtFastTest.c @@ -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 **");