00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <ctype.h>
00038 #include <math.h>
00039 #include <float.h>
00040
00041 #include "systemc/datatypes/fx/sc_fxval.h"
00042
00043
00044 namespace sc_dt
00045 {
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 const sc_string
00056 sc_fxval::to_string() const
00057 {
00058 return sc_string( m_rep->to_string( SC_DEC, -1, SC_E ) );
00059 }
00060
00061 const sc_string
00062 sc_fxval::to_string( sc_numrep numrep ) const
00063 {
00064 return sc_string( m_rep->to_string( numrep, -1, SC_E ) );
00065 }
00066
00067 const sc_string
00068 sc_fxval::to_string( sc_numrep numrep, bool w_prefix ) const
00069 {
00070 return sc_string( m_rep->to_string( numrep, (w_prefix ? 1 : 0), SC_E ) );
00071 }
00072
00073 const sc_string
00074 sc_fxval::to_string( sc_fmt fmt ) const
00075 {
00076 return sc_string( m_rep->to_string( SC_DEC, -1, fmt ) );
00077 }
00078
00079 const sc_string
00080 sc_fxval::to_string( sc_numrep numrep, sc_fmt fmt ) const
00081 {
00082 return sc_string( m_rep->to_string( numrep, -1, fmt ) );
00083 }
00084
00085 const sc_string
00086 sc_fxval::to_string( sc_numrep numrep, bool w_prefix, sc_fmt fmt ) const
00087 {
00088 return sc_string( m_rep->to_string( numrep, (w_prefix ? 1 : 0), fmt ) );
00089 }
00090
00091
00092 const sc_string
00093 sc_fxval::to_dec() const
00094 {
00095 return sc_string( m_rep->to_string( SC_DEC, -1, SC_E ) );
00096 }
00097
00098 const sc_string
00099 sc_fxval::to_bin() const
00100 {
00101 return sc_string( m_rep->to_string( SC_BIN, -1, SC_E ) );
00102 }
00103
00104 const sc_string
00105 sc_fxval::to_oct() const
00106 {
00107 return sc_string( m_rep->to_string( SC_OCT, -1, SC_E ) );
00108 }
00109
00110 const sc_string
00111 sc_fxval::to_hex() const
00112 {
00113 return sc_string( m_rep->to_string( SC_HEX, -1, SC_E ) );
00114 }
00115
00116
00117
00118
00119 void
00120 sc_fxval::print( ostream& os ) const
00121 {
00122 m_rep->print( os );
00123 }
00124
00125 void
00126 sc_fxval::scan( istream& is )
00127 {
00128 sc_string s;
00129 is >> s;
00130 *this = s.c_str();
00131 }
00132
00133 void
00134 sc_fxval::dump( ostream& os ) const
00135 {
00136 os << "sc_fxval" << endl;
00137 os << "(" << endl;
00138 os << "rep = ";
00139 m_rep->dump( os );
00140
00141
00142
00143
00144
00145
00146
00147 os << ")" << endl;
00148 }
00149
00150
00151
00152
00153 sc_fxval_observer*
00154 sc_fxval::lock_observer() const
00155 {
00156 SC_ASSERT_( m_observer != 0, "lock observer failed" );
00157 sc_fxval_observer* tmp = m_observer;
00158 m_observer = 0;
00159 return tmp;
00160 }
00161
00162 void
00163 sc_fxval::unlock_observer( sc_fxval_observer* observer_ ) const
00164 {
00165 SC_ASSERT_( observer_ != 0, "unlock observer failed" );
00166 m_observer = observer_;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176 static
00177 void
00178 print_dec( scfx_string& s, scfx_ieee_double id, int w_prefix, sc_fmt fmt )
00179 {
00180 if( id.negative() != 0 )
00181 {
00182 id.negative( 0 );
00183 s += '-';
00184 }
00185
00186 if( w_prefix == 1 ) {
00187 scfx_print_prefix( s, SC_DEC );
00188 }
00189
00190 if( id.is_zero() )
00191 {
00192 s += '0';
00193 return;
00194 }
00195
00196
00197
00198 double int_part;
00199 double frac_part = modf( static_cast<double>( id ), &int_part );
00200
00201 int i;
00202
00203
00204
00205 int int_digits = 0;
00206 int int_zeros = 0;
00207
00208 if( int_part != 0.0 )
00209 {
00210 int_digits = (int) ceil( log10( int_part + 1.0 ) );
00211
00212 int len = s.length();
00213 s.append( int_digits );
00214
00215 bool zero_digits = ( frac_part == 0.0 && fmt != SC_F );
00216
00217 for( i = int_digits + len - 1; i >= len; i-- )
00218 {
00219 unsigned int remainder = (unsigned int) fmod( int_part, 10.0 );
00220 s[i] = static_cast<char>( '0' + remainder );
00221
00222 if( zero_digits )
00223 {
00224 if( remainder == 0 )
00225 int_zeros ++;
00226 else
00227 zero_digits = false;
00228 }
00229
00230 int_part /= 10.0;
00231 }
00232
00233
00234 s.discard( int_zeros );
00235
00236 if( s[len] == '0' )
00237 {
00238
00239 s.remove( len );
00240 -- int_digits;
00241 }
00242 }
00243
00244
00245
00246 int frac_digits = 0;
00247 int frac_zeros = 0;
00248
00249 if( frac_part != 0.0 )
00250 {
00251 s += '.';
00252
00253 bool zero_digits = ( int_digits == 0 && fmt != SC_F );
00254
00255 frac_zeros = (int) floor( - log10( frac_part + DBL_EPSILON ) );
00256
00257 frac_part *= pow( 10.0, frac_zeros );
00258
00259 frac_digits = frac_zeros;
00260 if( ! zero_digits )
00261 {
00262 for( i = 0; i < frac_zeros; i ++ )
00263 s += '0';
00264 frac_zeros = 0;
00265 }
00266
00267 while( frac_part != 0.0 )
00268 {
00269 frac_part *= 10.0;
00270 int n = static_cast<int>( frac_part );
00271
00272 if( zero_digits )
00273 {
00274 if( n == 0 )
00275 frac_zeros ++;
00276 else
00277 zero_digits = false;
00278 }
00279
00280 if( ! zero_digits )
00281 s += static_cast<char>( '0' + n );
00282
00283 frac_part -= n;
00284 frac_digits ++;
00285 }
00286 }
00287
00288
00289
00290 if( fmt != SC_F )
00291 {
00292 if( frac_digits == 0 )
00293 scfx_print_exp( s, int_zeros );
00294 else if( int_digits == 0 )
00295 scfx_print_exp( s, - frac_zeros );
00296 }
00297 }
00298
00299
00300 static
00301 void
00302 print_other( scfx_string& s, const scfx_ieee_double& id, sc_numrep numrep,
00303 int w_prefix, sc_fmt fmt, const scfx_params* params )
00304 {
00305 scfx_ieee_double id2 = id;
00306
00307 sc_numrep numrep2 = numrep;
00308
00309 bool numrep_is_sm = ( numrep == SC_BIN_SM ||
00310 numrep == SC_OCT_SM ||
00311 numrep == SC_HEX_SM );
00312
00313 if( numrep_is_sm )
00314 {
00315 if( id2.negative() != 0 )
00316 {
00317 s += '-';
00318 id2.negative( 0 );
00319 }
00320 switch( numrep )
00321 {
00322 case SC_BIN_SM:
00323 numrep2 = SC_BIN_US;
00324 break;
00325 case SC_OCT_SM:
00326 numrep2 = SC_OCT_US;
00327 break;
00328 case SC_HEX_SM:
00329 numrep2 = SC_HEX_US;
00330 break;
00331 default:
00332 ;
00333 }
00334 }
00335
00336 if( w_prefix != 0 ) {
00337 scfx_print_prefix( s, numrep );
00338 }
00339
00340 numrep = numrep2;
00341
00342 sc_fxval_fast a( id2 );
00343
00344 int msb, lsb;
00345
00346 if( params != 0 )
00347 {
00348 msb = params->iwl() - 1;
00349 lsb = params->iwl() - params->wl();
00350
00351 if( params->enc() == SC_TC_ &&
00352 ( numrep == SC_BIN_US ||
00353 numrep == SC_OCT_US ||
00354 numrep == SC_HEX_US ) &&
00355 ! numrep_is_sm &&
00356 params->wl() > 1 )
00357 -- msb;
00358 else if( params->enc() == SC_US_ &&
00359 ( numrep == SC_BIN ||
00360 numrep == SC_OCT ||
00361 numrep == SC_HEX ||
00362 numrep == SC_CSD ) )
00363 ++ msb;
00364 }
00365 else
00366 {
00367 if( a.is_zero() )
00368 {
00369 msb = 0;
00370 lsb = 0;
00371 }
00372 else
00373 {
00374 msb = id2.exponent() + 1;
00375 while( a.get_bit( msb ) == a.get_bit( msb - 1 ) )
00376 -- msb;
00377
00378 if( numrep == SC_BIN_US ||
00379 numrep == SC_OCT_US ||
00380 numrep == SC_HEX_US )
00381 -- msb;
00382
00383 lsb = id2.exponent() - 52;
00384 while( ! a.get_bit( lsb ) )
00385 ++ lsb;
00386 }
00387 }
00388
00389 int step;
00390
00391 switch( numrep )
00392 {
00393 case SC_BIN:
00394 case SC_BIN_US:
00395 case SC_CSD:
00396 step = 1;
00397 break;
00398 case SC_OCT:
00399 case SC_OCT_US:
00400 step = 3;
00401 break;
00402 case SC_HEX:
00403 case SC_HEX_US:
00404 step = 4;
00405 break;
00406 default:
00407 step = 0;
00408 }
00409
00410 msb = (int) ceil( double( msb + 1 ) / step ) * step - 1;
00411
00412 lsb = (int) floor( double( lsb ) / step ) * step;
00413
00414 if( msb < 0 )
00415 {
00416 s += '.';
00417 if( fmt == SC_F )
00418 {
00419 int sign = ( id2.negative() != 0 ) ? ( 1 << step ) - 1 : 0;
00420 for( int i = ( msb + 1 ) / step; i < 0; i ++ )
00421 {
00422 if( sign < 10 )
00423 s += static_cast<char>( sign + '0' );
00424 else
00425 s += static_cast<char>( sign + 'a' - 10 );
00426 }
00427 }
00428 }
00429
00430 int i = msb;
00431 while( i >= lsb )
00432 {
00433 int value = 0;
00434 for( int j = step - 1; j >= 0; -- j )
00435 {
00436 value += static_cast<int>( a.get_bit( i ) ) << j;
00437 -- i;
00438 }
00439 if( value < 10 )
00440 s += static_cast<char>( value + '0' );
00441 else
00442 s += static_cast<char>( value + 'a' - 10 );
00443 if( i == -1 )
00444 s += '.';
00445 }
00446
00447 if( lsb > 0 && fmt == SC_F )
00448 {
00449 for( int i = lsb / step; i > 0; i -- )
00450 s += '0';
00451 }
00452
00453 if( s[s.length() - 1] == '.' )
00454 s.discard( 1 );
00455
00456 if( fmt != SC_F )
00457 {
00458 if( msb < 0 )
00459 scfx_print_exp( s, ( msb + 1 ) / step );
00460 else if( lsb > 0 )
00461 scfx_print_exp( s, lsb / step );
00462 }
00463
00464 if( numrep == SC_CSD )
00465 scfx_tc2csd( s, w_prefix );
00466 }
00467
00468
00469 const char*
00470 to_string( const scfx_ieee_double& id, sc_numrep numrep, int w_prefix,
00471 sc_fmt fmt, const scfx_params* params = 0 )
00472 {
00473 static scfx_string s;
00474
00475 s.clear();
00476
00477 if( id.is_nan() )
00478 scfx_print_nan( s );
00479 else if( id.is_inf() )
00480 scfx_print_inf( s, static_cast<bool>( id.negative() ) );
00481 else if( id.negative() && ! id.is_zero() &&
00482 ( numrep == SC_BIN_US ||
00483 numrep == SC_OCT_US ||
00484 numrep == SC_HEX_US ) )
00485 s += "negative";
00486 else if( numrep == SC_DEC )
00487 sc_dt::print_dec( s, id, w_prefix, fmt );
00488 else
00489 sc_dt::print_other( s, id, numrep, w_prefix, fmt, params );
00490
00491 return s;
00492 }
00493
00494
00495
00496
00497 const sc_string
00498 sc_fxval_fast::to_string() const
00499 {
00500 return sc_string( sc_dt::to_string( m_val, SC_DEC, -1, SC_E ) );
00501 }
00502
00503 const sc_string
00504 sc_fxval_fast::to_string( sc_numrep numrep ) const
00505 {
00506 return sc_string( sc_dt::to_string( m_val, numrep, -1, SC_E ) );
00507 }
00508
00509 const sc_string
00510 sc_fxval_fast::to_string( sc_numrep numrep, bool w_prefix ) const
00511 {
00512 return sc_string( sc_dt::to_string( m_val, numrep, (w_prefix ? 1 : 0),
00513 SC_E ) );
00514 }
00515
00516 const sc_string
00517 sc_fxval_fast::to_string( sc_fmt fmt ) const
00518 {
00519 return sc_string( sc_dt::to_string( m_val, SC_DEC, -1, fmt ) );
00520 }
00521
00522 const sc_string
00523 sc_fxval_fast::to_string( sc_numrep numrep, sc_fmt fmt ) const
00524 {
00525 return sc_string( sc_dt::to_string( m_val, numrep, -1, fmt ) );
00526 }
00527
00528 const sc_string
00529 sc_fxval_fast::to_string( sc_numrep numrep, bool w_prefix, sc_fmt fmt ) const
00530 {
00531 return sc_string( sc_dt::to_string( m_val, numrep, (w_prefix ? 1 : 0),
00532 fmt ) );
00533 }
00534
00535
00536 const sc_string
00537 sc_fxval_fast::to_dec() const
00538 {
00539 return sc_string( sc_dt::to_string( m_val, SC_DEC, -1, SC_E ) );
00540 }
00541
00542 const sc_string
00543 sc_fxval_fast::to_bin() const
00544 {
00545 return sc_string( sc_dt::to_string( m_val, SC_BIN, -1, SC_E ) );
00546 }
00547
00548 const sc_string
00549 sc_fxval_fast::to_oct() const
00550 {
00551 return sc_string( sc_dt::to_string( m_val, SC_OCT, -1, SC_E ) );
00552 }
00553
00554 const sc_string
00555 sc_fxval_fast::to_hex() const
00556 {
00557 return sc_string( sc_dt::to_string( m_val, SC_HEX, -1, SC_E ) );
00558 }
00559
00560
00561
00562
00563 void
00564 sc_fxval_fast::print( ostream& os ) const
00565 {
00566 os << sc_dt::to_string( m_val, SC_DEC, -1, SC_E );
00567 }
00568
00569 void
00570 sc_fxval_fast::scan( istream& is )
00571 {
00572 sc_string s;
00573 is >> s;
00574 *this = s.c_str();
00575 }
00576
00577 void
00578 sc_fxval_fast::dump( ostream& os ) const
00579 {
00580 os << "sc_fxval_fast" << endl;
00581 os << "(" << endl;
00582 os << "val = " << m_val << endl;
00583
00584
00585
00586
00587
00588
00589
00590 os << ")" << endl;
00591 }
00592
00593
00594
00595 bool
00596 sc_fxval_fast::get_bit( int i ) const
00597 {
00598 scfx_ieee_double id( m_val );
00599 if( id.is_zero() || id.is_nan() || id.is_inf() )
00600 return false;
00601
00602
00603
00604 unsigned int m0 = id.mantissa0();
00605 unsigned int m1 = id.mantissa1();
00606
00607 if( id.is_normal() )
00608 m0 += 1U << 20;
00609
00610 if( id.negative() != 0 )
00611 {
00612 m0 = ~ m0;
00613 m1 = ~ m1;
00614 unsigned int tmp = m1;
00615 m1 += 1U;
00616 if( m1 <= tmp )
00617 m0 += 1U;
00618 }
00619
00620
00621
00622 int j = i - id.exponent();
00623 if( ( j += 20 ) >= 32 )
00624 return ( ( m0 & 1U << 31 ) != 0 );
00625 else if( j >= 0 )
00626 return ( ( m0 & 1U << j ) != 0 );
00627 else if( ( j += 32 ) >= 0 )
00628 return ( ( m1 & 1U << j ) != 0 );
00629 else
00630 return false;
00631 }
00632
00633
00634
00635
00636 sc_fxval_fast_observer*
00637 sc_fxval_fast::lock_observer() const
00638 {
00639 SC_ASSERT_( m_observer != 0, "lock observer failed" );
00640 sc_fxval_fast_observer* tmp = m_observer;
00641 m_observer = 0;
00642 return tmp;
00643 }
00644
00645 void
00646 sc_fxval_fast::unlock_observer( sc_fxval_fast_observer* observer_ ) const
00647 {
00648 SC_ASSERT_( observer_ != 0, "unlock observer failed" );
00649 m_observer = observer_;
00650 }
00651
00652
00653 #define SCFX_FAIL_IF_(cnd) \
00654 { \
00655 if( ( cnd ) ) \
00656 return static_cast<double>( scfx_ieee_double::nan() ); \
00657 }
00658
00659 double
00660 sc_fxval_fast::from_string( const char* s )
00661 {
00662 SCFX_FAIL_IF_( s == 0 || *s == 0 );
00663
00664 scfx_string s2;
00665 s2 += s;
00666 s2 += '\0';
00667
00668 bool sign_char;
00669 int sign = scfx_parse_sign( s, sign_char );
00670
00671 sc_numrep numrep = scfx_parse_prefix( s );
00672
00673 int base = 0;
00674
00675 switch( numrep )
00676 {
00677 case SC_DEC:
00678 {
00679 base = 10;
00680 if( scfx_is_nan( s ) )
00681 return static_cast<double>( scfx_ieee_double::nan() );
00682 if( scfx_is_inf( s ) )
00683 return static_cast<double>( scfx_ieee_double::inf( sign ) );
00684 break;
00685 }
00686 case SC_BIN:
00687 case SC_BIN_US:
00688 {
00689 SCFX_FAIL_IF_( sign_char );
00690 base = 2;
00691 break;
00692 }
00693
00694 case SC_BIN_SM:
00695 {
00696 base = 2;
00697 break;
00698 }
00699 case SC_OCT:
00700 case SC_OCT_US:
00701 {
00702 SCFX_FAIL_IF_( sign_char );
00703 base = 8;
00704 break;
00705 }
00706 case SC_OCT_SM:
00707 {
00708 base = 8;
00709 break;
00710 }
00711 case SC_HEX:
00712 case SC_HEX_US:
00713 {
00714 SCFX_FAIL_IF_( sign_char );
00715 base = 16;
00716 break;
00717 }
00718 case SC_HEX_SM:
00719 {
00720 base = 16;
00721 break;
00722 }
00723 case SC_CSD:
00724 {
00725 SCFX_FAIL_IF_( sign_char );
00726 base = 2;
00727 scfx_csd2tc( s2 );
00728 s = (const char*) s2 + 4;
00729 numrep = SC_BIN;
00730 break;
00731 }
00732 default:;
00733 }
00734
00735
00736
00737
00738
00739 const char *end = s;
00740 bool based_point = false;
00741 int int_digits = 0;
00742 int frac_digits = 0;
00743
00744 while( *end )
00745 {
00746 if( scfx_exp_start( end ) )
00747 break;
00748
00749 if( *end == '.' )
00750 {
00751 SCFX_FAIL_IF_( based_point );
00752 based_point = true;
00753 }
00754 else
00755 {
00756 SCFX_FAIL_IF_( ! scfx_is_digit( *end, numrep ) );
00757 if( based_point )
00758 frac_digits ++;
00759 else
00760 int_digits ++;
00761 }
00762
00763 end ++;
00764 }
00765
00766 SCFX_FAIL_IF_( int_digits == 0 && frac_digits == 0 );
00767
00768
00769
00770 int exponent = 0;
00771
00772 if( *end )
00773 {
00774 for( const char *e = end + 2; *e; e ++ )
00775 SCFX_FAIL_IF_( ! scfx_is_digit( *e, SC_DEC ) );
00776 exponent = atoi( end + 1 );
00777 }
00778
00779
00780
00781
00782
00783 double integer = 0.0;
00784
00785 if( int_digits != 0 )
00786 {
00787
00788 bool first_digit = true;
00789
00790 for( ; s < end; s ++ )
00791 {
00792 if( *s == '.' )
00793 break;
00794
00795 if( first_digit )
00796 {
00797 integer = scfx_to_digit( *s, numrep );
00798 switch( numrep )
00799 {
00800 case SC_BIN:
00801 case SC_OCT:
00802 case SC_HEX:
00803 {
00804 if( integer >= ( base >> 1 ) )
00805 integer -= base;
00806 break;
00807 }
00808 default:
00809 ;
00810 }
00811 first_digit = false;
00812 }
00813 else
00814 {
00815 integer *= base;
00816 integer += scfx_to_digit( *s, numrep );
00817 }
00818 }
00819 }
00820
00821
00822
00823 double fraction = 0.0;
00824
00825 if( frac_digits != 0 )
00826 {
00827 s ++;
00828
00829 bool first_digit = ( int_digits == 0 );
00830
00831 double scale = 1.0;
00832
00833 for( ; s < end; s ++ )
00834 {
00835 scale /= base;
00836
00837 if( first_digit )
00838 {
00839 fraction = scfx_to_digit( *s, numrep );
00840 switch( numrep )
00841 {
00842 case SC_BIN:
00843 case SC_OCT:
00844 case SC_HEX:
00845 {
00846 if( fraction >= ( base >> 1 ) )
00847 fraction -= base;
00848 break;
00849 }
00850 default:
00851 ;
00852 }
00853 fraction *= scale;
00854 first_digit = false;
00855 }
00856 else
00857 fraction += scfx_to_digit( *s, numrep ) * scale;
00858 }
00859 }
00860
00861 double exp = ( exponent != 0 ) ? pow( (double) base, (double) exponent )
00862 : 1;
00863
00864 return ( sign * ( integer + fraction ) * exp );
00865 }
00866
00867 #undef SCFX_FAIL_IF_
00868
00869 }
00870
00871
00872