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

Generated on Wed Jan 21 15:32:08 2009 for SystemC by  doxygen 1.5.5