📄 scfx_rep.cpp
字号:
m_state = normal; find_sw(); // // two's complement of mantissa if it is negative // if( mant_is_neg ) { m_mant[m_msw] |= -1 << scfx_find_msb( m_mant[m_msw] ); for( int i = m_msw + 1; i < m_mant.size(); ++ i ) m_mant[i] = static_cast<word>( -1 ); complement( m_mant, m_mant, m_mant.size() ); inc( m_mant ); m_sign *= -1; find_sw(); }}#undef SCFX_FAIL_IF_// ----------------------------------------------------------------------------// METHOD : to_double//// Convert from scfx_rep to double.// ----------------------------------------------------------------------------doublescfx_rep::to_double() const { scfx_ieee_double id; // handle special cases if( is_nan() ) { id.set_nan(); return id; } if( is_inf() ) { id.set_inf(); id.negative( m_sign < 0 ); return id; } if( is_zero() ) { id = 0.; id.negative( m_sign < 0 ); return id; } int msb = scfx_find_msb( m_mant[m_msw] ); int exp = (m_msw - m_wp) * bits_in_word + msb; if( exp > SCFX_IEEE_DOUBLE_E_MAX ) { id.set_inf(); id.negative( m_sign < 0 ); return id; } if( exp < SCFX_IEEE_DOUBLE_E_MIN - static_cast<int>( SCFX_IEEE_DOUBLE_M_SIZE ) ) { id = 0.; return id; } int shift = mantissa0_size - msb; unsigned int m0; unsigned int m1 = 0; unsigned int guard = 0; if( shift == 0 ) { m0 = m_mant[m_msw] & ~( 1 << mantissa0_size ); if( m_msw > m_lsw ) { m1 = m_mant[m_msw - 1]; if( m_msw - 1 > m_lsw ) guard = m_mant[m_msw - 2] >> ( bits_in_word - 1 ); } } else if( shift < 0 ) { m0 = ( m_mant[m_msw] >> -shift ) & ~( 1 << mantissa0_size ); m1 = m_mant[m_msw] << ( bits_in_word + shift ); if( m_msw > m_lsw ) { m1 |= m_mant[m_msw - 1] >> -shift; guard = ( m_mant[m_msw - 1] >> ( -shift - 1 ) ) & 1; } } else { m0 = ( m_mant[m_msw] << shift ) & ~( 1 << mantissa0_size ); if( m_msw > m_lsw ) { m0 |= m_mant[m_msw - 1] >> ( bits_in_word - shift ); m1 = m_mant[m_msw - 1] << shift; if( m_msw - 1 > m_lsw ) { m1 |= m_mant[m_msw - 2] >> ( bits_in_word - shift ); guard = ( m_mant[m_msw - 2] >> (bits_in_word - shift - 1) ) & 1; } } } if( exp < SCFX_IEEE_DOUBLE_E_MIN ) { m0 |= ( 1 << mantissa0_size ); int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp; if( subnormal_shift < bits_in_word ) { m1 = m1 >> subnormal_shift | m0 << ( bits_in_word - subnormal_shift ); m0 = m0 >> subnormal_shift; } else { m1 = m0 >> ( subnormal_shift - bits_in_word ); m0 = 0; } guard = 0; exp = SCFX_IEEE_DOUBLE_E_MIN - 1; } id.mantissa0( m0 ); id.mantissa1( m1 ); id.exponent( exp ); id.negative( m_sign < 0 ); double result = id; if( guard != 0 ) result += m_sign * scfx_pow2( exp - SCFX_IEEE_DOUBLE_M_SIZE ); return result;}// ----------------------------------------------------------------------------// METHOD : to_string//// Convert from scfx_rep to character string.// ----------------------------------------------------------------------------voidprint_dec( scfx_string& s, const scfx_rep& num, int w_prefix, sc_fmt fmt ){ if( num.is_neg() ) s += '-'; if( w_prefix == 1 ) { scfx_print_prefix( s, SC_DEC ); } if( num.is_zero() ) { s += '0'; return; } // split 'num' into its integer and fractional part scfx_rep int_part = num; scfx_rep frac_part = num; int i; for( i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i ++ ) int_part.m_mant[i] = 0; int_part.find_sw(); if( int_part.m_wp < int_part.m_lsw ) int_part.resize_to( int_part.size() - int_part.m_wp, -1 ); for( i = frac_part.m_msw; i >= frac_part.m_lsw && i >= frac_part.m_wp; i -- ) frac_part.m_mant[i] = 0; frac_part.find_sw(); if( frac_part.m_msw == frac_part.size() - 1 ) frac_part.resize_to( frac_part.size() + 1, 1 ); // print integer part int int_digits = 0; int int_zeros = 0; if( ! int_part.is_zero() ) { double int_wl = ( int_part.m_msw - int_part.m_wp ) * bits_in_word + scfx_find_msb( int_part.m_mant[int_part.m_msw] ) + 1; int_digits = (int) ceil( int_wl * log10( 2. ) ); int len = s.length(); s.append( int_digits ); bool zero_digits = ( frac_part.is_zero() && fmt != SC_F ); for( i = int_digits + len - 1; i >= len; i-- ) { unsigned int remainder = int_part.divide_by_ten(); s[i] = static_cast<char>( '0' + remainder ); if( zero_digits ) { if( remainder == 0 ) int_zeros ++; else zero_digits = false; } } // discard trailing zeros from int_part s.discard( int_zeros ); if( s[len] == '0' ) { // int_digits was overestimated by one s.remove( len ); -- int_digits; } } // print fractional part int frac_digits = 0; int frac_zeros = 0; if( ! frac_part.is_zero() ) { s += '.'; bool zero_digits = ( int_digits == 0 && fmt != SC_F ); double frac_wl = ( frac_part.m_wp - frac_part.m_msw ) * bits_in_word - scfx_find_msb( frac_part.m_mant[frac_part.m_msw] ) - 1; frac_zeros = (int) floor( frac_wl * log10( 2. ) ); scfx_rep temp; sc_dt::multiply( temp, frac_part, pow10_fx( frac_zeros ) ); frac_part = temp; if( frac_part.m_msw == frac_part.size() - 1 ) frac_part.resize_to( frac_part.size() + 1, 1 ); frac_digits = frac_zeros; if( ! zero_digits ) { for( i = 0; i < frac_zeros; i ++ ) s += '0'; frac_zeros = 0; } while( ! frac_part.is_zero() ) { frac_part.multiply_by_ten(); int n = frac_part.m_mant[frac_part.m_msw + 1]; if( zero_digits ) { if( n == 0 ) frac_zeros ++; else zero_digits = false; } if( ! zero_digits ) s += static_cast<char>( '0' + n ); frac_part.m_mant[frac_part.m_msw + 1] = 0; frac_digits ++; } } // print exponent if( fmt != SC_F ) { if( frac_digits == 0 ) scfx_print_exp( s, int_zeros ); else if( int_digits == 0 ) scfx_print_exp( s, - frac_zeros ); }}voidprint_other( scfx_string& s, const scfx_rep& a, sc_numrep numrep, int w_prefix, sc_fmt fmt, const scfx_params* params ){ scfx_rep b = a; sc_numrep numrep2 = numrep; bool numrep_is_sm = ( numrep == SC_BIN_SM || numrep == SC_OCT_SM || numrep == SC_HEX_SM ); if( numrep_is_sm ) { if( b.is_neg() ) { s += '-'; b = *neg_scfx_rep( a ); } switch( numrep ) { case SC_BIN_SM: numrep2 = SC_BIN_US; break; case SC_OCT_SM: numrep2 = SC_OCT_US; break; case SC_HEX_SM: numrep2 = SC_HEX_US; break; default: ; } } if( w_prefix != 0 ) { scfx_print_prefix( s, numrep ); } numrep = numrep2; int msb, lsb; if( params != 0 ) { msb = params->iwl() - 1; lsb = params->iwl() - params->wl(); if( params->enc() == SC_TC_ && ( numrep == SC_BIN_US || numrep == SC_OCT_US || numrep == SC_HEX_US ) && ! numrep_is_sm && params->wl() > 1 ) -- msb; else if( params->enc() == SC_US_ && ( numrep == SC_BIN || numrep == SC_OCT || numrep == SC_HEX || numrep == SC_CSD ) ) ++ msb; } else { if( b.is_zero() ) { msb = 0; lsb = 0; } else { msb = ( b.m_msw - b.m_wp ) * bits_in_word + scfx_find_msb( b.m_mant[ b.m_msw ] ) + 1; while( b.get_bit( msb ) == b.get_bit( msb - 1 ) ) -- msb; if( numrep == SC_BIN_US || numrep == SC_OCT_US || numrep == SC_HEX_US ) -- msb; lsb = ( b.m_lsw - b.m_wp ) * bits_in_word + scfx_find_lsb( b.m_mant[ b.m_lsw ] ); } } int step; switch( numrep ) { case SC_BIN: case SC_BIN_US: case SC_CSD: step = 1; break; case SC_OCT: case SC_OCT_US: step = 3; break; case SC_HEX: case SC_HEX_US: step = 4; break; default: step = 0; } msb = (int) ceil( double( msb + 1 ) / step ) * step - 1; lsb = (int) floor( double( lsb ) / step ) * step; if( msb < 0 ) { s += '.'; if( fmt == SC_F ) { int sign = ( b.is_neg() ) ? ( 1 << step ) - 1 : 0; for( int i = ( msb + 1 ) / step; i < 0; i ++ ) { if( sign < 10 ) s += static_cast<char>( sign + '0' ); else s += static_cast<char>( sign + 'a' - 10 ); } } } int i = msb; while( i >= lsb ) { int value = 0; for( int j = step - 1; j >= 0; -- j ) { value += static_cast<int>( b.get_bit( i ) ) << j; -- i; } if( value < 10 ) s += static_cast<char>( value + '0' ); else s += static_cast<char>( value + 'a' - 10 ); if( i == -1 ) s += '.'; } if( lsb > 0 && fmt == SC_F ) { for( int i = lsb / step; i > 0; i -- ) s += '0'; } if( s[s.length() - 1] == '.' ) s.discard( 1 ); if( fmt != SC_F ) { if( msb < 0 ) scfx_print_exp( s, ( msb + 1 ) / step ); else if( lsb > 0 ) scfx_print_exp( s, lsb / step ); } if( numrep == SC_CSD ) scfx_tc2csd( s, w_prefix );}const char*scfx_rep::to_string( sc_numrep numrep, int w_prefix, sc_fmt fmt, const scfx_params* params ) const{ static scfx_string s; s.clear(); if( is_nan() ) scfx_print_nan( s ); else if( is_inf() ) scfx_print_inf( s, is_neg() ); else if( is_neg() && ! is_zero() && ( numrep == SC_BIN_US || numrep == SC_OCT_US || numrep == SC_HEX_US ) ) s += "negative"; else if( numrep == SC_DEC || numrep == SC_NOBASE ) sc_dt::print_dec( s, *this, w_prefix, fmt ); else sc_dt::print_other( s, *this, numrep, w_prefix, fmt, params ); return s;}// ----------------------------------------------------------------------------// ADD//// add two mantissas of the same size// result has the same size// returns carry of operation// ----------------------------------------------------------------------------static inlineintadd_mants( int size, scfx_mant& result, const scfx_mant& a, const scfx_mant& b ){ unsigned int carry = 0; int index = 0; do { word x = a[index]; word y = b[index]; y += carry; carry = y < carry; y += x; carry += y < x; result[index] = y; } while( ++ index < size ); return ( carry ? 1 : 0 );}static inlineintsub_mants( int size, scfx_mant& result, const scfx_mant& a, const scfx_mant& b ){ unsigned carry = 0; int index = 0; do { word x = a[index]; word y = b[index]; y += carry; carry = y < carry; y = x - y; carry += y > x; result[index] = y; } while( ++ index < size ); return ( carry ? 1 : 0 );}scfx_rep*add_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int max_wl ){ scfx_rep& result = *new scfx_rep; // // check for special cases // if( lhs.is_nan() || rhs.is_nan() || ( lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign ) ) { result.set_nan(); return &result; } if( lhs.is_inf() ) { result.set_inf( lhs.m_sign ); return &result; } if( rhs.is_inf() ) { result.set_inf( rhs.m_sign ); return &result; } // // align operands if needed // scfx_mant_ref lhs_mant; scfx_mant_ref rhs_mant; int len_mant = lhs.size(); int new_wp = lhs.m_wp; align( lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant ); // // size the result mantissa // result.resize_to( len_mant ); result.m_wp = new_wp; // // do it // if( lhs.m_sign == rhs.m_sign ) { add_mants( len_mant, result.m_mant, lhs_mant, rhs_mant ); result.m_sign = lhs.m_sign; } else { int cmp = compare_abs( lhs, rhs ); if( cmp == 1 ) { sub_mants( len_mant, result.m_mant, lhs_mant, rhs_mant ); result.m_sign = lhs.m_sign; } else if ( cmp == -1 ) { sub_mants( len_mant, result.m_mant, rhs_mant, lhs_mant ); result.m_sign = rhs.m_sign; } else { result.m_mant.clear(); result.m_sign = 1; } } result.find_sw(); result.round( max_wl ); return &result;}// ----------------------------------------------------------------------------// SUB//// sub two word's of the same size// result has the same size// returns carry of operation// ----------------------------------------------------------------------------static inlineintsub_with_index( scfx_mant& a, int a_msw, int a_lsw, const scfx_mant& b, int b_msw, int b_lsw ){ unsigned carry = 0; int size = b_msw - b_lsw; int a_index = a_msw - size; int b_index = b_msw - size; do { word x = a[a_index]; word y = b[b_index]; y += carry; carry = y < carry; y = x - y; carry += y > x; a[a_index] = y; a_index ++; b_index ++; } while( size -- ); if( carry ) { // special case: a[a_msw + 1 ] == 1 a[a_msw + 1] = 0; } return ( carry ? 1 : 0 );}scfx_rep*sub_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int max_wl ){ scfx_rep& result = *new scfx_rep; // // check for special cases // if( lhs.is_nan() || rhs.is_nan() || ( lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign ) ) { result.set_nan(); return &result; } if( lhs.is_inf() ) { result.set_inf( lhs.m_sign ); return &result; } if( rhs.is_inf() ) { result.set_inf( -1 * rhs.m_sign ); return &result; } // // align operands if needed // scfx_mant_ref lhs_mant; scfx_mant_ref rhs_mant; int len_mant = lhs.size(); int new_wp = lhs.m_wp; align( lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant ); // // size the result mantissa // result.resize_to( len_mant ); result.m_wp = new_wp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -