📄 scfx_rep.cpp
字号:
// // 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;}// ----------------------------------------------------------------------------// MUL// ----------------------------------------------------------------------------union word_short{ word l; struct {#if defined( SC_BIG_ENDIAN ) half_word u; half_word l;#elif defined( SC_LITTLE_ENDIAN ) half_word l; half_word u;#endif } s;};#if defined( SC_BIG_ENDIAN )static const int half_word_incr = -1;#elif defined( SC_LITTLE_ENDIAN )static const int half_word_incr = 1;#endifvoidmultiply( scfx_rep& result, const scfx_rep& lhs, const scfx_rep& rhs, int max_wl ){ // // check for special cases // if( lhs.is_nan() || rhs.is_nan() || lhs.is_inf() && rhs.is_zero() || lhs.is_zero() && rhs.is_inf() ) { result.set_nan(); return; } if( lhs.is_inf() || rhs.is_inf() ) { result.set_inf( lhs.m_sign * rhs.m_sign ); return; } if( lhs.is_zero() || rhs.is_zero() ) { result.set_zero( lhs.m_sign * rhs.m_sign ); return; } // // do it // int len_lhs = lhs.m_msw - lhs.m_lsw + 1; int len_rhs = rhs.m_msw - rhs.m_lsw + 1; int new_size = sc_max( min_mant, len_lhs + len_rhs ); int new_wp = ( lhs.m_wp - lhs.m_lsw ) + ( rhs.m_wp - rhs.m_lsw ); int new_sign = lhs.m_sign * rhs.m_sign; result.resize_to( new_size ); result.m_mant.clear(); result.m_wp = new_wp; result.m_sign = new_sign; result.m_state = scfx_rep::normal; half_word *s1 = lhs.m_mant.half_addr( lhs.m_lsw ); half_word *s2 = rhs.m_mant.half_addr( rhs.m_lsw ); half_word *t = result.m_mant.half_addr(); len_lhs <<= 1; len_rhs <<= 1; int i1, i2; for( i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr ) { register word_short ls; ls.l = 0; half_word v1 = s1[i1]; for( i2 = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr ) { ls.l += v1 * s2[i2]; ls.s.l = ls.s.u + ( ( t[i2] += ls.s.l ) < ls.s.l ); ls.s.u = 0; } t[i2] = ls.s.l; t += half_word_incr; } result.find_sw(); result.round( max_wl );}// ----------------------------------------------------------------------------// DIV// ----------------------------------------------------------------------------scfx_rep*div_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int div_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.is_zero() && rhs.is_zero() ) { result.set_nan(); return &result; } if( lhs.is_inf() || rhs.is_zero() ) { result.set_inf( lhs.m_sign * rhs.m_sign ); return &result; } if( lhs.is_zero() || rhs.is_inf() ) { result.set_zero( lhs.m_sign * rhs.m_sign ); return &result; } // // do it // // compute one bit more for rounding div_wl ++; result.resize_to( sc_max( n_word( div_wl ) + 1, min_mant ) ); result.m_mant.clear(); result.m_sign = lhs.m_sign * rhs.m_sign; int msb_lhs = scfx_find_msb( lhs.m_mant[lhs.m_msw] ) + ( lhs.m_msw - lhs.m_wp ) * bits_in_word; int msb_rhs = scfx_find_msb( rhs.m_mant[rhs.m_msw] ) + ( rhs.m_msw - rhs.m_wp ) * bits_in_word; int msb_res = msb_lhs - msb_rhs; int to_shift = -msb_res % bits_in_word; int result_index; int c = ( msb_res % bits_in_word >= 0 ) ? 1 : 0; result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word; result.m_wp = (result.size() - c) - msb_res / bits_in_word; scfx_rep remainder = lhs; // align msb from remainder to msb from rhs remainder.lshift( to_shift ); // make sure msw( remainder ) < size - 1 if( remainder.m_msw == remainder.size() - 1 ) remainder.resize_to( remainder.size() + 1, 1 ); // make sure msw( remainder ) >= msw( rhs )! int msw_diff = rhs.m_msw - remainder.m_msw; if (msw_diff > 0) remainder.resize_to( remainder.size() + msw_diff, -1 ); int counter; for( counter = div_wl; counter && ! remainder.is_zero(); counter -- ) { if( compare_msw_ff( rhs, remainder ) <= 0 ) { result.set_bin( result_index ); sub_with_index( remainder.m_mant, remainder.m_msw, remainder.m_lsw, rhs.m_mant, rhs.m_msw, rhs.m_lsw ); } result_index --; remainder.shift_left( 1 ); remainder.m_lsw = remainder.find_lsw(); } // perform convergent rounding, if needed if( counter == 0 ) { int index = result_index + 1 - result.m_wp * bits_in_word; scfx_index x = result.calc_indices( index ); scfx_index x1 = result.calc_indices( index + 1 ); if( result.o_bit_at( x ) && result.o_bit_at( x1 ) ) result.q_incr( x ); result.m_r_flag = true; } result.find_sw(); return &result;}// ----------------------------------------------------------------------------// destructive shift mantissa to the left// ----------------------------------------------------------------------------voidscfx_rep::lshift( int n ){ if( n == 0 ) return; if( n < 0 ) { rshift( -n ); return; } if( is_normal() ) { int shift_bits = n % bits_in_word; int shift_words = n / bits_in_word; // resize if needed if( m_msw == size() - 1 && scfx_find_msb( m_mant[m_msw] ) >= bits_in_word - shift_bits ) resize_to( size() + 1, 1 ); // do it m_wp -= shift_words; shift_left( shift_bits ); find_sw(); }}// ----------------------------------------------------------------------------// destructive shift mantissa to the right// ----------------------------------------------------------------------------voidscfx_rep::rshift( int n ){ if( n == 0 ) return; if( n < 0 ) { lshift( -n ); return; } if( is_normal() ) { int shift_bits = n % bits_in_word; int shift_words = n / bits_in_word; // resize if needed if( m_lsw == 0 && scfx_find_lsb( m_mant[m_lsw] ) < shift_bits ) resize_to( size() + 1, -1 ); // do it m_wp += shift_words; shift_right( shift_bits ); find_sw(); }}// ----------------------------------------------------------------------------// FRIEND FUNCTION : compare_abs//// Compares the absolute values of two scfx_reps, excluding the special cases.// ----------------------------------------------------------------------------intcompare_abs( const scfx_rep& a, const scfx_rep& b ){ // check for zero word a_word = a.m_mant[a.m_msw]; word b_word = b.m_mant[b.m_msw]; if( a_word == 0 || b_word == 0 ) { if( a_word != 0 ) return 1; if( b_word != 0 ) return -1; return 0; } // compare msw index int a_msw = a.m_msw - a.m_wp; int b_msw = b.m_msw - b.m_wp; if( a_msw > b_msw ) return 1; if( a_msw < b_msw ) return -1; // compare content int a_i = a.m_msw; int b_i = b.m_msw; while( a_i >= a.m_lsw && b_i >= b.m_lsw ) { a_word = a.m_mant[a_i]; b_word = b.m_mant[b_i]; if( a_word > b_word ) return 1; if( a_word < b_word ) return -1; -- a_i; -- b_i; } bool a_zero = true; while( a_i >= a.m_lsw ) { a_zero = a_zero && ( a.m_mant[a_i] == 0 ); -- a_i; } bool b_zero = true; while( b_i >= b.m_lsw ) { b_zero = b_zero && ( b.m_mant[b_i] == 0 ); -- b_i; } // assertion: a_zero || b_zero == true if( ! a_zero && b_zero ) return 1; if( a_zero && ! b_zero ) return -1; return 0;}// ----------------------------------------------------------------------------// FRIEND FUNCTION : cmp_scfx_rep//// Compares the values of two scfx_reps, including the special cases.// ----------------------------------------------------------------------------intcmp_scfx_rep( const scfx_rep& a, const scfx_rep& b ){ // handle special cases if( a.is_nan() || b.is_nan() ) {#if 0 if( a.is_nan() && b.is_nan() ) { return 0; }#endif return 2; } if( a.is_inf() || b.is_inf() ) { if( a.is_inf() ) { if( ! a.is_neg() ) { if( b.is_inf() && ! b.is_neg() ) { return 0; } else { return 1; } } else { if( b.is_inf() && b.is_neg() ) { return 0; } else { return -1; } } } if( b.is_inf() ) { if( ! b.is_neg() ) { return -1; } else { return 1; } } } if( a.is_zero() && b.is_zero() ) { return 0; } // compare sign if( a.m_sign != b.m_sign ) { return a.m_sign; } return ( a.m_sign * compare_abs( a, b ) );}// ----------------------------------------------------------------------------// PRIVATE METHOD : quantization//// Performs destructive quantization.// ----------------------------------------------------------------------------voidscfx_rep::quantization( const scfx_params& params, bool& q_flag ){ scfx_index x = calc_indices( params.iwl() - params.wl() ); if( x.wi() < 0 ) return; if( x.wi() >= size() ) resize_to( x.wi() + 1, 1 ); bool qb = q_bit( x ); bool qz = q_zero( x ); q_flag = ( qb || ! qz ); if( q_flag ) { switch( params.q_mode() ) { case SC_TRN: // truncation { if( is_neg() ) q_incr( x ); break; } case SC_RND: // rounding to plus infinity { if( ! is_neg() ) { if( qb ) q_incr( x ); } else { if( qb && ! qz ) q_incr( x ); } break; } case SC_TRN_ZERO: // truncation to zero { break; } case SC_RND_INF: // rounding to infinity { if( qb ) q_incr( x ); break; } case SC_RND_CONV: // convergent rounding { if( qb && ! qz || qb && qz && q_odd( x ) ) q_incr( x ); break; } case SC_RND_ZERO: // rounding to zero { if( qb && ! qz ) q_incr( x ); break; } case SC_RND_MIN_INF: // rounding to minus infinity { if( ! is_neg() ) { if( qb && ! qz ) q_incr( x ); } else { if( qb ) q_incr( x ); } break; } default: ; } q_clear( x ); find_sw(); }}// ----------------------------------------------------------------------------// PRIVATE METHOD : overflow//// Performs destructive overflow handling.// ----------------------------------------------------------------------------voidscfx_rep::overflow( const scfx_params& params, bool& o_flag ){ scfx_index x = calc_indices( params.iwl() - 1 ); if( x.wi() >= size() ) resize_to( x.wi() + 1, 1 ); if( x.wi() < 0 ) { resize_to( size() - x.wi(), -1 ); x.wi( 0 ); } bool zero_left = o_zero_left( x ); bool bit_at = o_bit_at( x ); bool zero_right = o_zero_right( x ); bool under = false; bool over = false; sc_enc enc = params.enc(); if( enc == SC_TC_ ) { if( is_neg() ) { if( params.o_mode() == SC_SAT_SYM ) under = ( ! zero_left || bit_at ); else under = ( ! zero_left || zero_left && bit_at && ! zero_right ); } else over = ( ! zero_left || bit_at ); } else { if( is_neg() ) under = ( ! is_zero() ); else over = ( ! zero_left ); } o_flag = ( under || over ); if( o_flag ) { scfx_index x2 = calc_indices( params.iwl() - params.wl() ); if( x2.wi() < 0 ) { resize_to( size() - x2.wi(), -1 ); x.wi( x.wi() - x2.wi() ); x2.wi( 0 ); } switch( params.o_mode() ) { case SC_WRAP: // wrap-around { int n_bits = params.n_bits(); if( n_bits == 0 ) { // wrap-around all 'wl' bits toggle_tc(); o_extend( x, enc ); toggle_tc(); } else if( n_bits < params.wl() ) { scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits ); // wrap-around least significant 'wl - n_bits' bits; // saturate most significant 'n_bits' bits toggle_tc(); o_set( x, x3, enc, under ); o_extend( x, enc ); toggle_tc(); } else { // saturate all 'wl' bits if( under ) o_set_low( x, enc ); else o_set_high( x, x2, enc ); } break; } case SC_SAT: // saturation { if( under ) o_set_low( x, enc ); else o_set_high( x, x2, enc ); break; } case SC_SAT_SYM: // symmetrical saturation { if( under ) { if( enc == SC_TC_ ) o_set_high( x, x2, SC_TC_, -1 ); else o_set_low( x, SC_US_ ); } else o_set_high( x, x2, enc ); break; } case SC_SAT_ZERO: // saturation to zero { set_zero(); break; } case SC_WRAP_SM: // sign magnitude wrap-around { SC_ERROR_IF_( enc == SC_US_, sc_core::SC_ID_WRAP_SM_NOT_DEFINED_ ); int n_bits = params.n_bits(); if( n_bits == 0 ) { scfx_index x4 = calc_indices( params.iwl() ); if( x4.wi() >= size() ) resize_to( x4.wi() + 1, 1 ); toggle_tc(); if( o_bit_at( x4 ) != o_bit_at( x ) ) o_invert( x2 ); o_extend( x, SC_TC_ ); toggle_tc(); } else if( n_bits == 1 ) { toggle_tc(); if( is_neg() != o_bit_at( x ) ) o_invert( x2 ); o_extend( x, SC_TC_ ); toggle_tc(); } else if( n_bits < params.wl() ) { scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits ); scfx_index x4 = calc_indices( params.iwl() - n_bits ); // wrap-around least significant 'wl - n_bits' bits; // saturate most significant 'n_bits' bits toggle_tc(); if( is_neg() == o_bit_at( x4 ) ) o_invert( x2 ); o_set( x, x3, SC_TC_, under ); o_extend( x, SC_TC_ ); toggle_tc(); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -