FloatT.h
Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 //  (c) 2006 by Basler Vision Technologies
00003 //  Section: Vision Components
00004 //  Project: GenApi
00005 //  Author:  Alexander Happe
00006 //  $Header$
00007 //
00008 //  License: This file is published under the license of the EMVA GenICam  Standard Group.
00009 //  A text file describing the legal terms is included in  your installation as 'GenICam_license.pdf'.
00010 //  If for some reason you are missing  this file please contact the EMVA or visit the website
00011 //  (http://www.genicam.org) for a full copy.
00012 //
00013 //  THIS SOFTWARE IS PROVIDED BY THE EMVA GENICAM STANDARD GROUP "AS IS"
00014 //  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
00015 //  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00016 //  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE EMVA GENICAM STANDARD  GROUP
00017 //  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  SPECIAL,
00018 //  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  LIMITED TO,
00019 //  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  DATA, OR PROFITS;
00020 //  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  THEORY OF LIABILITY,
00021 //  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)
00022 //  ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00023 //  POSSIBILITY OF SUCH DAMAGE.
00024 //-----------------------------------------------------------------------------
00031 #ifndef GENAPI_FLOATT_H
00032 #define GENAPI_FLOATT_H
00033 
00034 
00035 #include "../NodeCallback.h"
00036 #include "INodePrivate.h"
00037 #include "../Synch.h"
00038 #include "../Counter.h"
00039 #include "Value2String.h"
00040 #include "GenApi/impl/Log.h"
00041 #include <limits>
00042 #include <cmath>
00043 #include <cstdlib>
00044 #include <algorithm>
00045 #include "Exception.h"
00046 #include "AutovectorImpl.h"
00047 
00048 #pragma warning( disable : 4706 ) // assignment within conditional expression
00049 
00050 namespace GENAPI_NAMESPACE
00051 {
00055     template<class Base>
00056     class FloatT : public Base
00057     {
00058     public:
00059 
00061         FloatT< Base >() :
00062             Base(),
00063             m_ImposedMax( (std::numeric_limits<double>::max)() ),
00064             m_ImposedMin( -(std::numeric_limits<double>::max)() )
00065         {
00066         }
00067 
00069         virtual void SetValue(double Value, bool Verify = true)
00070         {
00071 
00072             // a list of callbacks to fire held outside(!) the autolock on the stack(!)
00073             std::list<CNodeCallback*> CallbacksToFire;
00074             {
00075                 AutoLock l(Base::GetLock());
00076                 typename Base::EntryMethodFinalizer E( this, meSetValue );
00077 
00078                 GCLOGINFOPUSH( Base::m_pValueLog, "SetValue( %f )...", Value );
00079 
00080                 if( Verify )
00081                 {
00082                     if( !IsWritable( this ) )
00083                         throw ACCESS_EXCEPTION_NODE("Node is not writable.");
00084 
00085                     CHECK_RANGE_FLT_NODE(Value, Base::InternalGetMin(), Base::InternalGetMax());
00086                 }
00087 
00088                 {
00089                     typename Base::PostSetValueFinalizer PostSetValueCaller(this, CallbacksToFire);  // dtor calls Base::PostSetValue
00090 
00091                     // invalidates all nodes if this is the first call in a chain of SetValue calls
00092                     Base::PreSetValue();
00093 
00094                     // sets the value
00095                     Base::InternalSetValue(Value, Verify);
00096 
00097                     if( Verify )
00098                         Base::InternalCheckError();
00099 
00100                     #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
00101                         // Fill cache
00102                         if( WriteThrough == static_cast<INode *>(this)->GetCachingMode() )
00103                         {
00104                             m_ValueCache = Value;
00105                             Base::m_ValueCacheValid = true;
00106                             Base::m_DontDeleteThisCache = true;
00107                         }
00108                     #endif
00109 
00110                 }
00111 
00112                 GCLOGINFOPOP( Base::m_pValueLog, "...SetValue" );
00113 
00114                 // fire callbacks inside the lock
00115                 std::list<CNodeCallback*>::iterator ptrCallback;
00116                 for( ptrCallback = CallbacksToFire.begin(); ptrCallback != CallbacksToFire.end(); ptrCallback++ )
00117                 {
00118                     (*ptrCallback)->operator ()(cbPostInsideLock);
00119                 }
00120             }
00121 
00122             // fire callbacks outside the lock
00123             std::list<CNodeCallback*>::iterator ptrCallback;
00124             for( ptrCallback = CallbacksToFire.begin(); ptrCallback != CallbacksToFire.end(); ptrCallback++ )
00125             {
00126                 (*ptrCallback)->operator ()(cbPostOutsideLock);
00127             }
00128         }
00129 
00131         virtual IFloat& operator=(double Value)
00132         {
00133             SetValue(Value);
00134 
00135             return *this;
00136         }
00137 
00138         /* This is a helper function used in the method ToString (see below)
00139            It parses a floating point number given in a buffer s and creates a correction value used for correct rounding
00140            
00141            If the number in s is given in fixed point notation like
00142                123.4567
00143            the correction is
00144                  0.00005
00145            that is it has zeros for all trailing digits of the number followed by a '5'
00146 
00147            In case of scientific notation like
00148                1.1234e-12
00149            the correction number is
00150                0.00005e-12
00151            that is it has zeros for all trailing digits of the number followed by a '5' plus it has 
00152            the same exponent as the original number.
00153 
00154            The use of the correction number is explained below in the method ToString
00155 
00156            The code is inspired from from http://www.hackchina.com/en/r/185703/ATOF.C__html
00157         */
00158         double Correction( const char *s )
00159         {
00160             // note that while parsing the parsed value is composed even if that is not necessary
00161             // nevertheless the code is left as is for clarification and verification purposes
00162             bool sign;
00163             char c;
00164 
00165             // eat white space 
00166             while( isspace(c = *s) )
00167                 s++;
00168 
00169             // handle sign
00170             if ((sign = (c == '-')))
00171                 s++;
00172             else if (c == '+')
00173                 s++;
00174 
00175             // read digits before decimal point
00176             double v = 0.0;
00177             while( isdigit(*s) )
00178                 v = 10.0 * v + (*s++ - '0');
00179 
00180             double Cor = 0.5;
00181             if( *s == '.' )
00182             {
00183                 s++;
00184 
00185                 // eat digits after decimal point
00186                 double fr = 10.0;
00187                 while( isdigit(*s) )
00188                 {
00189                     v += (*s++ - '0') / fr;
00190                     Cor *= 0.1;
00191                     fr *= 10.0;
00192                 }
00193             }
00194 
00195             // handle exponent
00196             double exp = 1.0;
00197             if (tolower(*s) == 'e')
00198             {
00199                 int i = atoi(s);
00200                 exp = pow(10.0, i);
00201             }
00202 
00203             //v *= exp;
00204             //v = sign ? -v : v;
00205 
00206             Cor *= exp;
00207 
00208             return Cor;
00209         }
00210 
00212         virtual GENICAM_NAMESPACE::gcstring InternalToString(bool Verify = false, bool IgnoreCache = false)
00213         {
00214             AutoLock l(Base::GetLock());
00215             
00216             std::stringstream Buffer;
00217             std::ostringstream CorrectedBuffer;
00218 
00219             // set DisplayNotation
00220             switch( Base::InternalGetDisplayNotation() )
00221             {
00222             case fnAutomatic:
00223                 // default
00224                 break;
00225             case fnFixed:
00226                 Buffer.setf(std::ios::fixed, std::ios::floatfield);
00227                 CorrectedBuffer.setf(std::ios::fixed, std::ios::floatfield);
00228                 break;
00229             case fnScientific:
00230                 Buffer.setf(std::ios::scientific, std::ios::floatfield);
00231                 CorrectedBuffer.setf(std::ios::scientific, std::ios::floatfield);
00232                 break;
00233             #pragma BullseyeCoverage off
00234             default:
00235                 assert(false);
00236             #pragma BullseyeCoverage on
00237             }
00238 
00239             // set DisplayPrecision
00240             int Precision = (int)GetDisplayPrecision();
00241             Buffer.precision( Precision ); 
00242             CorrectedBuffer.precision( Precision ); 
00243 
00244             // output
00245             double Value = GetValue( Verify, IgnoreCache );
00246             Buffer << Value;
00247 
00248             // Make sure FromString will work with the result
00249             // for details see the test code in FloatTestSuite::TestTicket785
00250 
00251             // read back the created string
00252             double VerifyValue;
00253             Buffer >> VerifyValue;
00254 
00255             double CorrectedValue = Value;
00256             bool LimitsExceeded = false;
00257             
00258             // the string may be too large due to rounding issues
00259             if( VerifyValue > Base::InternalGetMax() )
00260             {
00261                 CorrectedValue = Value - Correction( Buffer.str().c_str() );
00262                 LimitsExceeded = true;
00263             }
00264             else if( VerifyValue < Base::InternalGetMin() )
00265             {
00266                 CorrectedValue = Value + Correction( Buffer.str().c_str() );
00267                 LimitsExceeded = true;
00268             }
00269             
00270             GENICAM_NAMESPACE::gcstring valueString;
00271             if( LimitsExceeded )
00272             {
00273                 CorrectedBuffer << CorrectedValue;
00274                 valueString = CorrectedBuffer.str().c_str();
00275             }
00276             else
00277             {
00278                 valueString = Buffer.str().c_str();
00279             }
00280             return valueString;
00281         }
00282 
00284         virtual double GetValue(bool Verify = false, bool IgnoreCache = false)
00285         {
00286             AutoLock l(Base::GetLock());
00287             typename Base::EntryMethodFinalizer E( this, meGetValue, IgnoreCache );
00288 
00289             // Note that readability is tested regardless of Verify
00290             if( !IsReadable( this ) )
00291                 throw ACCESS_EXCEPTION_NODE("Node is not readable.");
00292 
00293             #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
00294                 // Use cache
00295                 if (!IgnoreCache && Base::m_ValueCacheValid && !Verify)
00296                 {
00297                     GCLOGINFO( Base::m_pValueLog, "GetValue = %f  (from cache)", m_ValueCache );
00298 
00299                     return m_ValueCache;
00300                 }
00301             #endif
00302 
00303             GCLOGINFOPUSH( Base::m_pValueLog, "GetValue...");
00304 
00305             const double Value( Base::InternalGetValue(Verify, IgnoreCache) );
00306 
00307             GCLOGINFOPOP( Base::m_pValueLog, "...GetValue = %f", Value );
00308 
00309             if( Verify )
00310             {
00311                 CHECK_RANGE_FLT_NODE(Value, Base::InternalGetMin(), Base::InternalGetMax());
00312                 Base::InternalCheckError();
00313             }
00314 
00315             #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
00316                 // Fill cache
00317                 const ECachingMode CachingMode(static_cast<INode *>(this)->GetCachingMode());
00318                 if(    WriteThrough == CachingMode
00319                     || WriteAround  == CachingMode  )
00320                 {
00321                     m_ValueCache = Value;
00322                     Base::m_ValueCacheValid = true;                            
00323                 }
00324             #endif
00325 
00326             return Value;
00327 
00328         }
00329 
00331         virtual double operator()()
00332         {
00333             return GetValue();
00334         }
00335 
00337         virtual double operator*()
00338         {
00339             return GetValue();
00340         }
00341 
00343         virtual void InternalFromString(const GENICAM_NAMESPACE::gcstring& ValueStr, bool Verify = true)
00344         {
00345             double value;
00346             if (!String2Value(ValueStr,&value))
00347                 throw INVALID_ARGUMENT_EXCEPTION_NODE("Node '%s' : cannot convert string '%s' to double.", Base::m_Name.c_str(),  ValueStr.c_str() );
00348 
00349             SetValue(value, Verify);
00350         }
00351 
00352 
00354         virtual double GetMin()
00355         {
00356             AutoLock l(Base::GetLock());
00357             typename Base::EntryMethodFinalizer E( this, meGetMin );
00358 
00359             GCLOGINFOPUSH( Base::m_pRangeLog, "GetMin..." );
00360 
00361             double Minimum = Base::InternalGetMin();
00362             Minimum = (std::max)(Minimum, m_ImposedMin);
00363 
00364             GCLOGINFOPOP( Base::m_pRangeLog, "...GetMin = %f", Minimum );
00365 
00366             return Minimum;
00367 
00368         }
00369 
00371         virtual double GetMax()
00372         {
00373             AutoLock l(Base::GetLock());
00374             typename Base::EntryMethodFinalizer E( this, meGetMax );
00375 
00376             GCLOGINFOPUSH( Base::m_pRangeLog, "GetMax...");
00377 
00378             double Maximum(Base::InternalGetMax());
00379             Maximum = (std::min)( Maximum, m_ImposedMax );
00380 
00381             GCLOGINFOPOP( Base::m_pRangeLog, "...GetMax = %f", Maximum );
00382 
00383             return Maximum;
00384 
00385         }
00386 
00388         virtual bool HasInc()
00389         {
00390             AutoLock l(Base::GetLock());
00391 
00392             GCLOGINFOPUSH( Base::m_pRangeLog, "HasInc...");
00393 
00394             bool HasInc( Base::InternalHasInc() );
00395 #pragma BullseyeCoverage off
00396             GCLOGINFOPOP( Base::m_pRangeLog, "...HasInc = " + (HasInc ? GENICAM_NAMESPACE::gcstring("true") : GENICAM_NAMESPACE::gcstring("false")));
00397 #pragma BullseyeCoverage on
00398 
00399             return HasInc;
00400 
00401         }
00402 
00403         virtual EIncMode GetIncMode()
00404         {
00405             AutoLock l(Base::GetLock());
00406             typename Base::EntryMethodFinalizer E( this, meGetIncMode );
00407 
00408             GCLOGINFOPUSH( Base::m_pRangeLog, "GetIncMode...");
00409 
00410             if( ! Base::m_ListOfValidValuesCacheValid )
00411             {
00412                m_CurentValidValueSet = Base::InternalGetListOfValidValues();
00413                Base::m_ListOfValidValuesCacheValid = true;
00414             }
00415 
00416             EIncMode incMode( (m_CurentValidValueSet.size())? listIncrement: Base::InternalHasInc()? fixedIncrement : noIncrement  );
00417 
00418             GCLOGINFOPOP( Base::m_pRangeLog, "...GetIncMode" );
00419 
00420             return incMode;
00421         }
00422 
00424         virtual double GetInc()
00425         {
00426             AutoLock l(Base::GetLock());
00427             typename Base::EntryMethodFinalizer E( this, meGetInc );
00428 
00429             if( !Base::InternalHasInc() )
00430                 throw RUNTIME_EXCEPTION_NODE("node does not have an increment." );
00431 
00432             GCLOGINFOPUSH( Base::m_pRangeLog, "GetInc...");
00433 
00434             double Inc( Base::InternalGetInc() );
00435 
00436             GCLOGINFOPOP( Base::m_pRangeLog, "...GetInc = %f", Inc );
00437 
00438             return Inc;
00439         }
00440 
00442         virtual double_autovector_t GetListOfValidValues(bool bounded = true)
00443         {
00444             AutoLock l(Base::GetLock());
00445             typename Base::EntryMethodFinalizer E( this, meGetListOfValidValues );
00446 
00447             GCLOGINFOPUSH( Base::m_pRangeLog, "GetListOfValidValues...");
00448             if( ! Base::m_ListOfValidValuesCacheValid )
00449             {
00450                m_CurentValidValueSet = Base::InternalGetListOfValidValues();
00451                Base::m_ListOfValidValuesCacheValid = true;
00452             }
00453 
00454             double_autovector_t list( ( bounded)? m_CurentValidValueSet.duplicate( Base::InternalGetMin(), Base::InternalGetMax()) : m_CurentValidValueSet);
00455 
00456 
00457             GCLOGINFOPOP( Base::m_pRangeLog, "...GetListOfValidValues" );
00458             return list;
00459 
00460 
00461         }
00462 
00463 
00465         virtual  ERepresentation GetRepresentation()
00466         {
00467             AutoLock l(Base::GetLock());
00468             return Base::InternalGetRepresentation();
00469         }
00470 
00472         virtual GENICAM_NAMESPACE::gcstring GetUnit() const
00473         {
00474             AutoLock l(Base::GetLock());
00475             return Base::InternalGetUnit();
00476         }
00477 
00479         virtual EDisplayNotation GetDisplayNotation() const
00480         {
00481             AutoLock l(Base::GetLock());
00482             return Base::InternalGetDisplayNotation();
00483         }
00484 
00486         virtual int64_t GetDisplayPrecision() const
00487         {
00488             AutoLock l(Base::GetLock());
00489 
00490             int64_t Precision = Base::InternalGetDisplayPrecision();
00491 
00492             if( Precision == -1 )
00493             {
00494                 // determine built in precision
00495                 std::stringstream Buffer;
00496                 switch( Base::InternalGetDisplayNotation() )
00497                 {
00498                 case fnFixed:
00499                     Buffer.setf(std::ios::fixed, std::ios::floatfield);
00500                     break;
00501                 case fnScientific:
00502                     Buffer.setf(std::ios::scientific, std::ios::floatfield);
00503                     break;
00504                 case fnAutomatic:
00505                     // default
00506                     break;
00507             #pragma BullseyeCoverage off
00508                 default:
00509                     assert(false);
00510             #pragma BullseyeCoverage on
00511                  }
00512 
00513                 Precision = Buffer.precision();
00514             }
00515 
00516             return Precision;
00517         }
00518 
00520         virtual void ImposeMin(double Value)
00521         {
00522             m_ImposedMin = Value;
00523             Base::SetInvalid(INodePrivate::simAll);
00524         }
00525 
00527         virtual void ImposeMax(double Value)
00528         {
00529             m_ImposedMax = Value;
00530             Base::SetInvalid(INodePrivate::simAll);
00531         }
00532 
00533     protected:
00535         double m_ValueCache;
00536 
00538         double m_ImposedMax;
00539 
00541         double m_ImposedMin;
00542 
00544         double_autovector_impl m_CurentValidValueSet;
00545     };
00546 }
00547 
00548 #endif // GENAPI_FLOATT_H


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:02