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