scfx_ieee.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2005 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   scfx_ieee.h - 
00021 
00022   Original Author: Martin Janssen, Synopsys, Inc.
00023 
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027 
00028   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00029   changes you are making here.
00030 
00031       Name, Affiliation, Date:
00032   Description of Modification:
00033 
00034  *****************************************************************************/
00035 
00036 #ifndef SCFX_IEEE_H
00037 #define SCFX_IEEE_H
00038 
00039 
00040 #include "sysc/datatypes/fx/sc_fxdefs.h"
00041 
00042 
00043 namespace sc_dt
00044 {
00045 
00046 // classes defined in this module
00047 union ieee_double;
00048 class scfx_ieee_double;
00049 union ieee_float;
00050 class scfx_ieee_float;
00051 
00052 
00053 // ----------------------------------------------------------------------------
00054 //  Little or big endian machine?
00055 // ----------------------------------------------------------------------------
00056 
00057 #if defined( i386 ) || defined(WIN32)
00058 # define SCFX_LITTLE_ENDIAN
00059 #elif defined( __ppc__ ) || defined( sparc ) || defined( __hppa )
00060 # define SCFX_BIG_ENDIAN
00061 #endif
00062 
00063 
00064 // ----------------------------------------------------------------------------
00065 //  UNION : ieee_double
00066 //
00067 //  IEEE 754 double-precision format.
00068 // ----------------------------------------------------------------------------
00069     
00070 union ieee_double
00071 {
00072 
00073     double d;
00074 
00075     struct
00076     {
00077 #if defined( SCFX_BIG_ENDIAN )
00078         unsigned negative:1;
00079         unsigned exponent:11;
00080         unsigned mantissa0:20;
00081         unsigned mantissa1:32;
00082 #elif defined( SCFX_LITTLE_ENDIAN )
00083         unsigned mantissa1:32;
00084         unsigned mantissa0:20;
00085         unsigned exponent:11;
00086         unsigned negative:1;
00087 #endif
00088     } s;
00089 
00090 };
00091 
00092 
00093 const unsigned int SCFX_IEEE_DOUBLE_BIAS   =  1023U;
00094 
00095 const int          SCFX_IEEE_DOUBLE_E_MAX  =  1023;
00096 const int          SCFX_IEEE_DOUBLE_E_MIN  = -1022;
00097 
00098 const unsigned int SCFX_IEEE_DOUBLE_M_SIZE =    52;
00099 
00100 
00101 // ----------------------------------------------------------------------------
00102 //  CLASS : scfx_ieee_double
00103 //
00104 //  Convenient interface to union ieee_double.
00105 // ----------------------------------------------------------------------------
00106 
00107 class scfx_ieee_double
00108 {
00109 
00110     ieee_double m_id;
00111 
00112 public:
00113     
00114     scfx_ieee_double();
00115     scfx_ieee_double( double );
00116     scfx_ieee_double( const scfx_ieee_double& );
00117     
00118     scfx_ieee_double& operator = ( double );
00119     scfx_ieee_double& operator = ( const scfx_ieee_double& );
00120     
00121     operator double() const;
00122 
00123     unsigned int negative() const;
00124     void negative( unsigned int );
00125     int exponent() const;
00126     void exponent( int );
00127     unsigned int mantissa0() const;
00128     void mantissa0( unsigned int );
00129     unsigned int mantissa1() const;
00130     void mantissa1( unsigned int );
00131 
00132     bool is_zero() const;
00133     bool is_subnormal() const;
00134     bool is_normal() const;
00135     bool is_inf() const;
00136     bool is_nan() const;
00137 
00138     void set_inf();
00139     void set_nan();
00140 
00141     int msb() const;            // most significant non-zero bit
00142     int lsb() const;            // least significant non-zero bit
00143 
00144     static const scfx_ieee_double nan();
00145     static const scfx_ieee_double inf( int );
00146 
00147 };
00148 
00149 
00150 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
00151     
00152 inline
00153 scfx_ieee_double::scfx_ieee_double()
00154 {
00155     m_id.d = 0.0;
00156 }
00157 
00158 inline
00159 scfx_ieee_double::scfx_ieee_double( double d )
00160 {
00161     m_id.d = d;
00162 }
00163 
00164 inline
00165 scfx_ieee_double::scfx_ieee_double( const scfx_ieee_double& a )
00166 {
00167     m_id.d = a.m_id.d;
00168 }
00169     
00170 
00171 inline
00172 scfx_ieee_double&
00173 scfx_ieee_double::operator = ( double d )
00174 {
00175     m_id.d = d;
00176     return *this;
00177 }
00178 
00179 inline
00180 scfx_ieee_double&
00181 scfx_ieee_double::operator = ( const scfx_ieee_double& a )
00182 {
00183     m_id.d = a.m_id.d;
00184     return *this;
00185 }
00186     
00187 
00188 inline
00189 scfx_ieee_double::operator double() const
00190 {
00191     return m_id.d;
00192 }
00193 
00194 
00195 inline
00196 unsigned int
00197 scfx_ieee_double::negative() const
00198 {
00199     return m_id.s.negative;
00200 }
00201 
00202 inline
00203 void
00204 scfx_ieee_double::negative( unsigned int a )
00205 {
00206     m_id.s.negative = a;
00207 }
00208 
00209 inline
00210 int
00211 scfx_ieee_double::exponent() const
00212 {
00213     return m_id.s.exponent - SCFX_IEEE_DOUBLE_BIAS;
00214 }
00215 
00216 inline
00217 void
00218 scfx_ieee_double::exponent( int a )
00219 {
00220     m_id.s.exponent = SCFX_IEEE_DOUBLE_BIAS + a;
00221 }
00222 
00223 inline
00224 unsigned int
00225 scfx_ieee_double::mantissa0() const
00226 {
00227     return m_id.s.mantissa0;
00228 }
00229 
00230 inline
00231 void
00232 scfx_ieee_double::mantissa0( unsigned int a )
00233 {
00234     m_id.s.mantissa0 = a;
00235 }
00236 
00237 inline
00238 unsigned int
00239 scfx_ieee_double::mantissa1() const
00240 {
00241     return m_id.s.mantissa1;
00242 }
00243 
00244 inline
00245 void
00246 scfx_ieee_double::mantissa1( unsigned int a )
00247 {
00248     m_id.s.mantissa1 = a;
00249 }
00250 
00251 
00252 inline
00253 bool
00254 scfx_ieee_double::is_zero() const
00255 {
00256     return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 &&
00257              mantissa0() == 0U && mantissa1() == 0U );
00258 }
00259 
00260 inline
00261 bool
00262 scfx_ieee_double::is_subnormal() const
00263 {
00264     return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 &&
00265              ( mantissa0() != 0U || mantissa1() != 0U ) );
00266 }
00267 
00268 inline
00269 bool
00270 scfx_ieee_double::is_normal() const
00271 {
00272     return ( exponent() >= SCFX_IEEE_DOUBLE_E_MIN &&
00273              exponent() <= SCFX_IEEE_DOUBLE_E_MAX );
00274 }
00275 
00276 inline
00277 bool
00278 scfx_ieee_double::is_inf() const
00279 {
00280     return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 &&
00281              mantissa0() == 0U && mantissa1() == 0U );
00282 }
00283 
00284 inline
00285 bool
00286 scfx_ieee_double::is_nan() const
00287 {
00288     return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 &&
00289              ( mantissa0() != 0U || mantissa1() != 0U ) );
00290 }
00291 
00292 
00293 inline
00294 void
00295 scfx_ieee_double::set_inf()
00296 {
00297     exponent( SCFX_IEEE_DOUBLE_E_MAX + 1 );
00298     mantissa0( 0U );
00299     mantissa1( 0U );
00300 }
00301 
00302 inline
00303 void
00304 scfx_ieee_double::set_nan()
00305 {
00306     exponent( SCFX_IEEE_DOUBLE_E_MAX + 1 );
00307     mantissa0( (unsigned int) -1 );
00308     mantissa1( (unsigned int) -1 );
00309 }
00310 
00311 
00312 #define MSB_STATEMENT(x,n) if( x >> n ) { x >>= n; i += n; }
00313 
00314 inline
00315 int
00316 scfx_ieee_double::msb() const
00317 {
00318     unsigned int m0 = mantissa0();
00319     unsigned int m1 = mantissa1();
00320     if( m0 != 0 )
00321     {
00322         int i = 0;
00323         MSB_STATEMENT(m0,16);
00324         MSB_STATEMENT(m0,8);
00325         MSB_STATEMENT(m0,4);
00326         MSB_STATEMENT(m0,2);
00327         MSB_STATEMENT(m0,1);
00328         return ( i - 20 );
00329     }
00330     else if( m1 != 0 )
00331     {
00332         int i = 0;
00333         MSB_STATEMENT(m1,16);
00334         MSB_STATEMENT(m1,8);
00335         MSB_STATEMENT(m1,4);
00336         MSB_STATEMENT(m1,2);
00337         MSB_STATEMENT(m1,1);
00338         return ( i - 52 );
00339     }
00340     else
00341     {
00342         return 0;
00343     }
00344 }
00345 
00346 #undef MSB_STATEMENT
00347 
00348 #define LSB_STATEMENT(x,n) if( x << n ) { x <<= n; i -= n; }
00349 
00350 inline
00351 int
00352 scfx_ieee_double::lsb() const
00353 {
00354     unsigned int m0 = mantissa0();
00355     unsigned int m1 = mantissa1();
00356     if( m1 != 0 )
00357     {
00358         int i = 31;
00359         LSB_STATEMENT(m1,16);
00360         LSB_STATEMENT(m1,8);
00361         LSB_STATEMENT(m1,4);
00362         LSB_STATEMENT(m1,2);
00363         LSB_STATEMENT(m1,1);
00364         return ( i - 52 );
00365     }
00366     else if( m0 != 0 )
00367     {
00368         int i = 31;
00369         LSB_STATEMENT(m0,16);
00370         LSB_STATEMENT(m0,8);
00371         LSB_STATEMENT(m0,4);
00372         LSB_STATEMENT(m0,2);
00373         LSB_STATEMENT(m0,1);
00374         return ( i - 20 );
00375     }
00376     else
00377     {
00378         return 0;
00379     }
00380 }
00381 
00382 #undef LSB_STATEMENT
00383 
00384 
00385 inline
00386 const scfx_ieee_double
00387 scfx_ieee_double::nan()
00388 {
00389     scfx_ieee_double id;
00390     id.set_nan();
00391     return id;
00392 }
00393 
00394 inline
00395 const scfx_ieee_double
00396 scfx_ieee_double::inf( int sign )
00397 {
00398     scfx_ieee_double id( sign );
00399     id.set_inf();
00400     return id;
00401 }
00402 
00403 
00404 // ----------------------------------------------------------------------------
00405 //  UNION : ieee_float
00406 //
00407 //  IEEE 754 single-precision format.
00408 // ----------------------------------------------------------------------------
00409     
00410 union ieee_float
00411 {
00412 
00413     float f;
00414 
00415     struct
00416     {
00417 #if defined( SCFX_BIG_ENDIAN )
00418         unsigned negative:1;
00419         unsigned exponent:8;
00420         unsigned mantissa:23;
00421 #elif defined( SCFX_LITTLE_ENDIAN )
00422         unsigned mantissa:23;
00423         unsigned exponent:8;
00424         unsigned negative:1;
00425 #endif
00426     } s;
00427 
00428 };
00429 
00430 
00431 const unsigned int SCFX_IEEE_FLOAT_BIAS   =  127U;
00432 
00433 const int          SCFX_IEEE_FLOAT_E_MAX  =  127;
00434 const int          SCFX_IEEE_FLOAT_E_MIN  = -126;
00435 
00436 const unsigned int SCFX_IEEE_FLOAT_M_SIZE =   23;
00437 
00438 
00439 // ----------------------------------------------------------------------------
00440 //  CLASS : scfx_ieee_float
00441 //
00442 // Convenient wrapper to union ieee_float.
00443 // ----------------------------------------------------------------------------
00444 
00445 class scfx_ieee_float
00446 {
00447 
00448     ieee_float m_if;
00449 
00450 public:
00451 
00452     scfx_ieee_float();
00453     scfx_ieee_float( float );
00454     scfx_ieee_float( const scfx_ieee_float& );
00455 
00456     scfx_ieee_float& operator = ( float );
00457     scfx_ieee_float& operator = ( const scfx_ieee_float& );
00458 
00459     operator float() const;
00460 
00461     unsigned int negative() const;
00462     void negative( unsigned int );
00463     int exponent() const;
00464     void exponent( int );
00465     unsigned int mantissa() const;
00466     void mantissa( unsigned int );
00467 
00468     bool is_zero() const;
00469     bool is_subnormal() const;
00470     bool is_normal() const;
00471     bool is_inf() const;
00472     bool is_nan() const;
00473 
00474     void set_inf();
00475     void set_nan();
00476 
00477 };
00478 
00479 
00480 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
00481     
00482 inline
00483 scfx_ieee_float::scfx_ieee_float()
00484 {
00485     m_if.f = 0.0;
00486 }
00487 
00488 inline
00489 scfx_ieee_float::scfx_ieee_float( float f )
00490 {
00491     m_if.f = f;
00492 }
00493 
00494 inline
00495 scfx_ieee_float::scfx_ieee_float( const scfx_ieee_float& a )
00496 {
00497     m_if.f = a.m_if.f;
00498 }
00499 
00500 
00501 inline
00502 scfx_ieee_float&
00503 scfx_ieee_float::operator = ( float f )
00504 {
00505     m_if.f = f;
00506     return *this;
00507 }
00508 
00509 inline
00510 scfx_ieee_float&
00511 scfx_ieee_float::operator = ( const scfx_ieee_float& a )
00512 {
00513     m_if.f = a.m_if.f;
00514     return *this;
00515 }
00516     
00517 
00518 inline
00519 scfx_ieee_float::operator float() const
00520 {
00521     return m_if.f;
00522 }
00523 
00524 
00525 inline
00526 unsigned int
00527 scfx_ieee_float::negative() const
00528 {
00529     return m_if.s.negative;
00530 }
00531 
00532 inline
00533 void
00534 scfx_ieee_float::negative( unsigned int a )
00535 {
00536     m_if.s.negative = a;
00537 }
00538 
00539 inline
00540 int
00541 scfx_ieee_float::exponent() const
00542 {
00543     return m_if.s.exponent - SCFX_IEEE_FLOAT_BIAS;
00544 }
00545 
00546 inline
00547 void
00548 scfx_ieee_float::exponent( int a )
00549 {
00550     m_if.s.exponent = SCFX_IEEE_FLOAT_BIAS + a;
00551 }
00552 
00553 inline
00554 unsigned int
00555 scfx_ieee_float::mantissa() const
00556 {
00557     return m_if.s.mantissa;
00558 }
00559 
00560 inline
00561 void
00562 scfx_ieee_float::mantissa( unsigned int a )
00563 {
00564     m_if.s.mantissa = a;
00565 }
00566 
00567 
00568 inline
00569 bool
00570 scfx_ieee_float::is_zero() const
00571 {
00572     return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() == 0U );
00573 }
00574 
00575 inline
00576 bool
00577 scfx_ieee_float::is_subnormal() const
00578 {
00579     return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() != 0U );
00580 }
00581 
00582 inline
00583 bool
00584 scfx_ieee_float::is_normal() const
00585 {
00586     return ( exponent() >= SCFX_IEEE_FLOAT_E_MIN &&
00587              exponent() <= SCFX_IEEE_FLOAT_E_MAX );
00588 }
00589 
00590 inline
00591 bool
00592 scfx_ieee_float::is_inf() const
00593 {
00594     return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() == 0U );
00595 }
00596 
00597 inline
00598 bool
00599 scfx_ieee_float::is_nan() const
00600 {
00601     return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() != 0U );
00602 }
00603 
00604 
00605 inline
00606 void
00607 scfx_ieee_float::set_inf()
00608 {
00609     exponent( SCFX_IEEE_FLOAT_E_MAX + 1 );
00610     mantissa( 0U );
00611 }
00612 
00613 inline
00614 void
00615 scfx_ieee_float::set_nan()
00616 {
00617     exponent( SCFX_IEEE_FLOAT_E_MAX + 1 );
00618     mantissa( (unsigned int) -1 );
00619 }
00620 
00621 
00622 // ----------------------------------------------------------------------------
00623 //  FUNCTION : scfx_pow2
00624 //
00625 //  Computes 2.0**exp in double-precision.
00626 // ----------------------------------------------------------------------------
00627 
00628 inline
00629 double scfx_pow2( int exp )
00630 {
00631     scfx_ieee_double r;
00632     if( exp < SCFX_IEEE_DOUBLE_E_MIN )
00633     {
00634         r = 0.0;
00635         // handle subnormal case
00636         exp -= SCFX_IEEE_DOUBLE_E_MIN;
00637         if( ( exp += 20 ) >= 0 )
00638         {
00639             r.mantissa0( 1U << exp );
00640         }
00641         else if( ( exp += 32 ) >= 0 )
00642         {
00643             r.mantissa1( 1U << exp );
00644         }
00645     }
00646     else if( exp > SCFX_IEEE_DOUBLE_E_MAX )
00647     {
00648         r.set_inf();
00649     }
00650     else
00651     {
00652         r = 1.0;
00653         r.exponent( exp );
00654     }
00655     return r;
00656 }
00657 
00658 
00659 // ----------------------------------------------------------------------------
00660 //  FUNCTION : uint64_to_double
00661 //
00662 //  Platform independent conversion from double uint64 to double.
00663 //  Needed because VC++6 doesn't support this conversion.
00664 // ----------------------------------------------------------------------------
00665 
00666 inline
00667 double
00668 uint64_to_double( uint64 a )
00669 {
00670 #if defined( _MSC_VER )
00671     // conversion from uint64 to double not implemented; use int64
00672     double tmp = static_cast<double>( static_cast<int64>( a ) );
00673     return ( tmp >= 0 ) ? tmp : tmp + sc_dt::scfx_pow2( 64 );
00674 #else
00675     return static_cast<double>( a );
00676 #endif
00677 }
00678 
00679 } // namespace sc_dt
00680 
00681 
00682 #endif
00683 
00684 // Taf!
Generated by
Matthieu Moy <Matthieu.Moy@st.com>
Back to Pinapa Home Page