Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

scfx_rep.cpp

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-2004 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.3 (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_rep.cpp - 
00021 
00022   Original Author: Robert Graulich, Synopsys, Inc.
00023                    Martin Janssen,  Synopsys, Inc.
00024 
00025  *****************************************************************************/
00026 
00027 /*****************************************************************************
00028 
00029   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00030   changes you are making here.
00031 
00032       Name, Affiliation, Date:
00033   Description of Modification:
00034 
00035  *****************************************************************************/
00036 
00037 
00038 #include "systemc/datatypes/fx/scfx_rep.h"
00039 
00040 #include "systemc/datatypes/fx/scfx_ieee.h"
00041 #include "systemc/datatypes/fx/scfx_pow10.h"
00042 #include "systemc/datatypes/fx/scfx_utils.h"
00043 
00044 #include "systemc/datatypes/bit/sc_bv_base.h"
00045 
00046 #include <ctype.h>
00047 #include <math.h>
00048 
00049 
00050 namespace sc_dt
00051 {
00052 
00053 // ----------------------------------------------------------------------------
00054 //  some utilities
00055 // ----------------------------------------------------------------------------
00056 
00057 static scfx_pow10 pow10_fx;
00058 
00059 static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int;
00060 
00061 static inline
00062 int
00063 n_word( int x )
00064 {
00065     return ( x + bits_in_word - 1 ) / bits_in_word;
00066 }
00067 
00068 
00069 // ----------------------------------------------------------------------------
00070 //  CONSTRUCTORS
00071 // ----------------------------------------------------------------------------
00072 
00073 scfx_rep::scfx_rep()
00074 : m_mant( min_mant ), m_r_flag( false )
00075 {
00076     set_zero();
00077 }
00078 
00079 scfx_rep::scfx_rep( int a )
00080 : m_mant( min_mant ), m_r_flag( false )
00081 {
00082     if( a != 0 )
00083     {
00084         m_mant.clear();
00085   m_wp = m_msw = m_lsw = 2;
00086   m_state = normal;
00087   if( a > 0 )
00088   {
00089       m_mant[2] = a;
00090       m_sign = 1;
00091   }
00092   else
00093   {
00094       m_mant[2] = -a;
00095       m_sign = -1;
00096   }
00097     }
00098     else
00099         set_zero();
00100 }
00101 
00102 scfx_rep::scfx_rep( unsigned int a )
00103 : m_mant( min_mant ), m_r_flag( false )
00104 {
00105     if( a != 0 )
00106     {
00107         m_mant.clear();
00108   m_wp = m_msw = m_lsw = 2;
00109   m_state = normal;
00110   m_mant[2] = a;
00111   m_sign = 1;
00112     }
00113     else
00114         set_zero();
00115 }
00116 
00117 scfx_rep::scfx_rep( long a )
00118 : m_mant( min_mant ), m_r_flag( false )
00119 {
00120     if( a != 0 )
00121     {
00122         m_mant.clear();
00123   m_wp = m_msw = m_lsw = 2;
00124   m_state = normal;
00125   if( a > 0 )
00126   {
00127       m_mant[2] = a;
00128       m_sign = 1;
00129   }
00130   else
00131   {
00132       m_mant[2] = -a;
00133       m_sign = -1;
00134   }
00135     }
00136     else
00137         set_zero();
00138 }
00139 
00140 scfx_rep::scfx_rep( unsigned long a )
00141 : m_mant( min_mant ), m_r_flag( false )
00142 {
00143     if( a != 0 )
00144     {
00145         m_mant.clear();
00146   m_wp = m_msw = m_lsw = 2;
00147   m_state = normal;
00148   m_mant[2] = a;
00149   m_sign = 1;
00150     }
00151     else
00152         set_zero();
00153 }
00154 
00155 scfx_rep::scfx_rep( double a )
00156 : m_mant( min_mant ), m_wp( 0 ), m_state( normal ), m_msw( 0 ), m_lsw( 0 ),
00157   m_r_flag( false )
00158 {
00159     m_mant.clear();
00160 
00161     scfx_ieee_double id( a );
00162 
00163     m_sign = id.negative() ? -1 : 1;
00164 
00165     if( id.is_nan() )
00166         m_state = not_a_number;
00167     else if( id.is_inf() )
00168         m_state = infinity;
00169     else if( id.is_subnormal() )
00170     {
00171   m_mant[0] = id.mantissa1();
00172   m_mant[1] = id.mantissa0();
00173   normalize( id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE );
00174     }
00175     else if( id.is_normal() )
00176     {
00177   m_mant[0] = id.mantissa1();
00178   m_mant[1] = id.mantissa0() | ( 1 << mantissa0_size );
00179   normalize( id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE );
00180     }
00181 }
00182 
00183 scfx_rep::scfx_rep( int64 a )
00184 : m_mant( min_mant ), m_r_flag( false )
00185 {
00186     if( a != 0 )
00187     {
00188         m_mant.clear();
00189   m_wp = 1;
00190   m_state = normal;
00191   if( a > 0 )
00192   {
00193       m_mant[1] = static_cast<word>( a );
00194       m_mant[2] = static_cast<word>( a >> bits_in_word );
00195       m_sign = 1;
00196   }
00197   else
00198   {
00199       m_mant[1] = static_cast<word>( -a );
00200       m_mant[2] = static_cast<word>( (-a) >> bits_in_word );
00201       m_sign = -1;
00202   }
00203   find_sw();
00204     }
00205     else
00206         set_zero();
00207 }
00208 
00209 scfx_rep::scfx_rep( uint64 a )
00210 : m_mant( min_mant ), m_r_flag( false )
00211 {
00212     if( a != 0 )
00213     {
00214         m_mant.clear();
00215   m_wp = 1;
00216   m_state = normal;
00217   m_mant[1] = static_cast<word>( a );
00218   m_mant[2] = static_cast<word>( a >> bits_in_word );
00219   m_sign = 1;
00220   find_sw();
00221     }
00222     else
00223         set_zero();
00224 }
00225 
00226 scfx_rep::scfx_rep( const sc_signed& a )
00227 : m_mant( min_mant ), m_r_flag( false )
00228 {
00229     if( a.iszero() )
00230   set_zero();
00231     else
00232     {
00233   int words = n_word( a.length() );
00234   if( words > size() )
00235       resize_to( words );
00236   m_mant.clear();
00237   m_wp = 0;
00238   m_state = normal;
00239   if( a.sign() )
00240   {
00241       sc_signed a2 = -a;
00242       for( int i = 0; i < a2.length(); ++ i )
00243       {
00244     if( a2[i] )
00245     {
00246         scfx_index x = calc_indices( i );
00247         m_mant[x.wi()] |= 1 << x.bi();
00248     }
00249       }
00250       m_sign = -1;
00251   }
00252   else
00253   {
00254       for( int i = 0; i < a.length(); ++ i )
00255       {
00256     if( a[i] )
00257     {
00258         scfx_index x = calc_indices( i );
00259         m_mant[x.wi()] |= 1 << x.bi();
00260     }
00261       }
00262       m_sign = 1;
00263   }
00264   find_sw();
00265     }
00266 }
00267 
00268 scfx_rep::scfx_rep( const sc_unsigned& a )
00269 : m_mant( min_mant ), m_r_flag( false )
00270 {
00271     if( a.iszero() )
00272   set_zero();
00273     else
00274     {
00275   int words = n_word( a.length() );
00276   if( words > size() )
00277       resize_to( words );
00278   m_mant.clear();
00279   m_wp = 0;
00280   m_state = normal;
00281   for( int i = 0; i < a.length(); ++ i )
00282   {
00283       if( a[i] )
00284       {
00285     scfx_index x = calc_indices( i );
00286     m_mant[x.wi()] |= 1 << x.bi();
00287       }
00288   }
00289   m_sign = 1;
00290   find_sw();
00291     }
00292 }
00293 
00294 
00295 // copy constructor
00296 
00297 scfx_rep::scfx_rep( const scfx_rep& a )
00298 : m_mant( a.m_mant ), m_wp( a.m_wp ), m_sign( a.m_sign ), m_state( a.m_state ),
00299   m_msw( a.m_msw ), m_lsw( a.m_lsw ), m_r_flag( false )
00300 {}
00301 
00302 
00303 // ----------------------------------------------------------------------------
00304 //  OPERATORS : new, delete
00305 //
00306 //  Memory management for class scfx_rep.
00307 // ----------------------------------------------------------------------------
00308 
00309 union scfx_rep_node
00310 {
00311     char           data[sizeof( scfx_rep )];
00312     scfx_rep_node* next;
00313 };
00314 
00315 
00316 static scfx_rep_node* list = 0;
00317 
00318 
00319 void*
00320 scfx_rep::operator new( size_t size )
00321 {
00322     const int ALLOC_SIZE = 1024;
00323 
00324     if( size != sizeof( scfx_rep ) )
00325   return ::operator new( size );
00326 
00327     if( ! list )
00328     {
00329   list = new scfx_rep_node[ALLOC_SIZE];
00330   for( int i = 0; i < ALLOC_SIZE - 1; i ++ )
00331       list[i].next = list + i + 1;
00332   list[ALLOC_SIZE - 1].next = 0;
00333     }
00334 
00335     scfx_rep* ptr = reinterpret_cast<scfx_rep*>( list->data );
00336     list = list->next;
00337 
00338     return ptr;
00339 }
00340 
00341 
00342 void scfx_rep::operator delete( void* ptr, size_t size )
00343 {
00344     if( size != sizeof( scfx_rep ) )
00345     {
00346   ::operator delete( ptr );
00347   return;
00348     }
00349 
00350     scfx_rep_node* node = static_cast<scfx_rep_node*>( ptr );
00351     node->next = list;
00352     list = node;
00353 }
00354 
00355 
00356 // ----------------------------------------------------------------------------
00357 //  METHOD : from_string
00358 //
00359 //  Convert from character string to sc_fxrep.
00360 // ----------------------------------------------------------------------------
00361 
00362 #define SCFX_FAIL_IF_(cnd)                                                    \
00363 {                                                                             \
00364     if( ( cnd ) )                                                             \
00365     {                                                                         \
00366         m_state = not_a_number;                                               \
00367   m_mant.clear(); /* to avoid Purify UMRs during assignment */          \
00368         return;                                                               \
00369     }                                                                         \
00370 }
00371 
00372 
00373 void
00374 scfx_rep::from_string( const char* s, int cte_wl )
00375 {
00376     SCFX_FAIL_IF_( s == 0 || *s == 0 );
00377 
00378     scfx_string s2;
00379     s2 += s;
00380     s2 += '\0';
00381 
00382     bool sign_char;
00383     m_sign = scfx_parse_sign( s, sign_char );
00384 
00385     sc_numrep numrep = scfx_parse_prefix( s );
00386 
00387     int base = 0;
00388 
00389     switch( numrep )
00390     {
00391   case SC_DEC:
00392   {
00393       base = 10;
00394       if( scfx_is_nan( s ) )
00395       {   // special case: NaN
00396     m_state = not_a_number;
00397     m_mant.clear(); /* to avoid Purify UMRs during assignment */
00398     return;
00399       }
00400       if( scfx_is_inf( s ) )
00401       {   // special case: Infinity
00402     m_state = infinity;
00403     m_mant.clear(); /* to avoid Purify UMRs during assignment */
00404     return;
00405       }
00406       break;
00407   }
00408   case SC_BIN:
00409   case SC_BIN_US:
00410   {
00411       SCFX_FAIL_IF_( sign_char );
00412       base = 2;
00413       break;
00414   }
00415   
00416   case SC_BIN_SM:
00417   {
00418       base = 2;
00419       break;
00420   }
00421   case SC_OCT:
00422   case SC_OCT_US:
00423   {
00424       SCFX_FAIL_IF_( sign_char );
00425       base = 8;
00426       break;
00427   }
00428   case SC_OCT_SM:
00429   {
00430       base = 8;
00431       break;
00432   }
00433   case SC_HEX:
00434   case SC_HEX_US:
00435   {
00436       SCFX_FAIL_IF_( sign_char );
00437       base = 16;
00438       break;
00439   }
00440   case SC_HEX_SM:
00441   {
00442       base = 16;
00443       break;
00444   }
00445   case SC_CSD:
00446   {
00447       SCFX_FAIL_IF_( sign_char );
00448       base = 2;
00449       scfx_csd2tc( s2 );
00450       s = (const char*) s2 + 4;
00451       numrep = SC_BIN;
00452       break;
00453   }
00454         default:;
00455     }
00456 
00457     //
00458     // find end of mantissa and count the digits and points
00459     //
00460 
00461     const char *end = s;
00462     bool based_point = false;
00463     int int_digits = 0;
00464     int frac_digits = 0;
00465 
00466     while( *end )
00467     {
00468   if( scfx_exp_start( end ) )
00469       break;
00470   
00471   if( *end == '.' )
00472   {
00473       SCFX_FAIL_IF_( based_point );
00474       based_point = true;
00475   }
00476   else
00477   {
00478       SCFX_FAIL_IF_( ! scfx_is_digit( *end, numrep ) );
00479       if( based_point )
00480     frac_digits ++;
00481       else
00482     int_digits ++;
00483   }
00484 
00485   ++ end;
00486     }
00487 
00488     SCFX_FAIL_IF_( int_digits == 0 && frac_digits == 0 );
00489 
00490     // [ exponent ]
00491     
00492     int exponent = 0;
00493 
00494     if( *end )
00495     {
00496   for( const char *e = end + 2; *e; ++ e )
00497       SCFX_FAIL_IF_( ! scfx_is_digit( *e, SC_DEC ) );
00498   exponent = atoi( end + 1 );
00499     }
00500 
00501     //
00502     // check if the mantissa is negative
00503     //
00504 
00505     bool mant_is_neg = false;
00506 
00507     switch( numrep )
00508     {
00509   case SC_BIN:
00510   case SC_OCT:
00511   case SC_HEX:
00512   {
00513       const char* p = s;
00514       if( *p == '.' )
00515     ++ p;
00516 
00517       mant_is_neg = ( scfx_to_digit( *p, numrep ) >= ( base >> 1 ) );
00518 
00519       break;
00520   }
00521   default:
00522       ;
00523     }
00524 
00525     //
00526     // convert the mantissa
00527     //
00528 
00529     switch( base )
00530     {
00531         case 2:
00532   {
00533       int bit_offset = exponent % bits_in_word;
00534       int word_offset = exponent / bits_in_word;
00535 
00536       int_digits += bit_offset;
00537       frac_digits -= bit_offset;
00538 
00539       int words = n_word( int_digits ) + n_word( frac_digits );
00540       if( words > size() )
00541     resize_to( words );
00542       m_mant.clear();
00543 
00544       int j = n_word( frac_digits ) * bits_in_word + int_digits - 1;
00545       
00546       for( ; s < end; s ++ )
00547       {
00548     switch( *s )
00549     {
00550         case '1':
00551             set_bin( j );
00552         case '0':
00553       j --;
00554         case '.':
00555       break;
00556         default:
00557       SCFX_FAIL_IF_( true );  // should not happen
00558     }
00559       }
00560 
00561       m_wp = n_word( frac_digits ) - word_offset;
00562       break;
00563   }
00564         case 8:
00565   {
00566       exponent *= 3;
00567       int_digits *= 3;
00568       frac_digits *= 3;
00569 
00570       int bit_offset = exponent % bits_in_word;
00571       int word_offset = exponent / bits_in_word;
00572 
00573       int_digits += bit_offset;
00574       frac_digits -= bit_offset;
00575 
00576       int words = n_word( int_digits ) + n_word( frac_digits );
00577       if( words > size() )
00578     resize_to( words );
00579       m_mant.clear();
00580 
00581       int j = n_word( frac_digits ) * bits_in_word + int_digits - 3;
00582       
00583       for( ; s < end; s ++ )
00584       {
00585     switch( *s )
00586     {
00587         case '7': case '6': case '5': case '4':
00588         case '3': case '2': case '1':
00589             set_oct( j, *s - '0' );
00590         case '0':
00591       j -= 3;
00592         case '.':
00593       break;
00594         default:
00595       SCFX_FAIL_IF_( true );  // should not happen
00596     }
00597       }
00598 
00599       m_wp = n_word( frac_digits ) - word_offset;
00600       break;
00601   }
00602         case 10:
00603   {
00604       unsigned long carry, temp;
00605       int length = int_digits + frac_digits;
00606       resize_to( sc_max( min_mant, n_word( 4 * length ) ) );
00607 
00608       m_mant.clear();
00609       m_msw = m_lsw = 0;
00610       
00611       for( ; s < end; s ++ )
00612       {
00613     switch( *s )
00614     {
00615         case '9': case '8': case '7': case '6': case '5':
00616         case '4': case '3': case '2': case '1': case '0':
00617             multiply_by_ten();
00618       carry = *s - '0';
00619       for ( int i = 0; carry && i < m_mant.size(); i++ )
00620       {
00621           temp = m_mant[i];
00622                             temp += carry;          
00623           carry = temp < m_mant[i];
00624           m_mant[i] = temp;
00625       }
00626         case '.':
00627       break;
00628         default:
00629       SCFX_FAIL_IF_( true );  // should not happen
00630     }
00631       }
00632       
00633       m_wp = 0;
00634       find_sw();
00635 
00636       int denominator = frac_digits - exponent;
00637       
00638       if( denominator )
00639       {
00640     scfx_rep frac_num = pow10_fx( denominator );
00641     scfx_rep* temp_num =
00642         div_scfx_rep( const_cast<const scfx_rep&>( *this ),
00643            frac_num, cte_wl );
00644     *this = *temp_num;
00645     delete temp_num;
00646       }
00647 
00648       break;
00649   }
00650         case 16:
00651   {
00652       exponent *= 4;
00653       int_digits *= 4;
00654       frac_digits *= 4;
00655 
00656       int bit_offset = exponent % bits_in_word;
00657       int word_offset = exponent / bits_in_word;
00658 
00659       int_digits += bit_offset;
00660       frac_digits -= bit_offset;
00661 
00662       int words = n_word( int_digits ) + n_word( frac_digits );
00663       if( words > size() )
00664     resize_to( words );
00665       m_mant.clear();
00666 
00667       int j = n_word( frac_digits ) * bits_in_word + int_digits - 4;
00668       
00669       for( ; s < end; s ++ )
00670       {
00671     switch( *s )
00672     {
00673         case 'f': case 'e': case 'd': case 'c': case 'b': case 'a':
00674            set_hex( j, *s - 'a' + 10 );
00675            j -= 4;
00676            break;
00677         case 'F': case 'E': case 'D': case 'C': case 'B': case 'A':
00678            set_hex( j, *s - 'A' + 10 );
00679            j -= 4;
00680            break;
00681         case '9': case '8': case '7': case '6': case '5':
00682         case '4': case '3': case '2': case '1':
00683            set_hex( j, *s - '0' );
00684         case '0':
00685            j -= 4;
00686         case '.':
00687            break;
00688        default:
00689            SCFX_FAIL_IF_( true );  // should not happen
00690     }
00691       }
00692 
00693       m_wp = n_word( frac_digits ) - word_offset;
00694       break;
00695   }
00696     }
00697 
00698     m_state = normal;
00699     find_sw();
00700 
00701     //
00702     // two's complement of mantissa if it is negative
00703     //
00704 
00705     if( mant_is_neg )
00706     {
00707   m_mant[m_msw] |=  -1 << scfx_find_msb( m_mant[m_msw] );
00708   for( int i = m_msw + 1; i < m_mant.size(); ++ i )
00709       m_mant[i] = static_cast<word>( -1 );
00710   complement( m_mant, m_mant, m_mant.size() );
00711   inc( m_mant );
00712   m_sign *= -1;
00713   find_sw();
00714     }
00715 }
00716 
00717 
00718 #undef SCFX_FAIL_IF_
00719 
00720 
00721 // ----------------------------------------------------------------------------
00722 //  METHOD : to_double
00723 //
00724 //  Convert from scfx_rep to double.
00725 // ----------------------------------------------------------------------------
00726 
00727 double
00728 scfx_rep::to_double() const 
00729 {
00730     scfx_ieee_double id;
00731 
00732     // handle special cases
00733 
00734     if( is_nan() )
00735     {
00736         id.set_nan();
00737   return id;
00738     }
00739 
00740     if( is_inf() )
00741     {
00742         id.set_inf();
00743   id.negative( m_sign < 0 );
00744   return id;
00745     }
00746 
00747     if( is_zero() )
00748     {
00749   id = 0.;
00750   id.negative( m_sign < 0 );
00751   return id;
00752     }
00753 
00754     int msb = scfx_find_msb( m_mant[m_msw] );
00755 
00756     int exp = (m_msw - m_wp) * bits_in_word + msb;
00757 
00758     if( exp > SCFX_IEEE_DOUBLE_E_MAX )
00759     {
00760   id.set_inf();
00761   id.negative( m_sign < 0 );
00762   return id;
00763     }
00764 
00765     if( exp < SCFX_IEEE_DOUBLE_E_MIN
00766   - static_cast<int>( SCFX_IEEE_DOUBLE_M_SIZE ) )
00767     {
00768   id = 0.;
00769   return id;
00770     }
00771  
00772     int shift = mantissa0_size - msb;
00773 
00774     unsigned int m0;
00775     unsigned int m1 = 0;
00776     unsigned int guard = 0;
00777 
00778     if( shift == 0 )
00779     {
00780         m0 = m_mant[m_msw] & ~( 1 << mantissa0_size );
00781   if( m_msw > m_lsw )
00782   {
00783       m1 = m_mant[m_msw - 1];
00784       if( m_msw - 1 > m_lsw )
00785           guard = m_mant[m_msw - 2] >> ( bits_in_word - 1 );
00786   }
00787     }
00788     else if( shift < 0 )
00789     {
00790   m0 = ( m_mant[m_msw] >> -shift ) & ~( 1 << mantissa0_size );
00791   m1 = m_mant[m_msw] << ( bits_in_word + shift );
00792   if( m_msw > m_lsw )
00793   {
00794       m1 |= m_mant[m_msw - 1] >> -shift;
00795       guard = ( m_mant[m_msw - 1] >> ( -shift - 1 ) ) & 1;
00796   }
00797     }
00798     else
00799     {
00800   m0 = ( m_mant[m_msw] << shift ) & ~( 1 << mantissa0_size );
00801   if( m_msw > m_lsw )
00802   {
00803       m0 |= m_mant[m_msw - 1] >> ( bits_in_word - shift );
00804       m1 = m_mant[m_msw - 1] << shift;
00805       if( m_msw - 1 > m_lsw )
00806       {
00807           m1 |= m_mant[m_msw - 2] >> ( bits_in_word - shift );
00808     guard = ( m_mant[m_msw - 2] >> (bits_in_word - shift - 1) )
00809                       & 1;
00810       }      
00811   }
00812     }
00813 
00814     if( exp < SCFX_IEEE_DOUBLE_E_MIN )
00815     {
00816   m0 |= ( 1 << mantissa0_size );
00817 
00818   int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp;
00819 
00820   if( subnormal_shift < bits_in_word )
00821   {
00822       m1 = m1 >> subnormal_shift
00823          | m0 << ( bits_in_word - subnormal_shift );
00824       m0 = m0 >> subnormal_shift;
00825   }
00826   else
00827   {
00828       m1 = m0 >> ( subnormal_shift - bits_in_word );
00829       m0 = 0;
00830   }
00831 
00832   guard = 0;
00833 
00834   exp = SCFX_IEEE_DOUBLE_E_MIN - 1;
00835     }
00836 
00837     id.mantissa0( m0 );
00838     id.mantissa1( m1 );
00839     id.exponent( exp );
00840     id.negative( m_sign < 0 );
00841 
00842     double result = id;
00843 
00844     if( guard != 0 )
00845         result += m_sign * scfx_pow2( exp - SCFX_IEEE_DOUBLE_M_SIZE );
00846 
00847     return result;
00848 }
00849 
00850 
00851 // ----------------------------------------------------------------------------
00852 //  METHOD : to_string
00853 //
00854 //  Convert from scfx_rep to character string.
00855 // ----------------------------------------------------------------------------
00856 
00857 void
00858 print_dec( scfx_string& s, const scfx_rep& num, int w_prefix, sc_fmt fmt )
00859 {
00860     if( num.is_neg() )
00861   s += '-';
00862 
00863     if( w_prefix == 1 ) {
00864   scfx_print_prefix( s, SC_DEC );
00865     }
00866 
00867     if( num.is_zero() )
00868     {
00869   s += '0';
00870   return;
00871     }
00872 
00873     // split 'num' into its integer and fractional part
00874 
00875     scfx_rep int_part  = num;
00876     scfx_rep frac_part = num;
00877 
00878     int i;
00879     
00880     for( i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i ++ )
00881   int_part.m_mant[i] = 0;
00882     int_part.find_sw();
00883     if( int_part.m_wp < int_part.m_lsw )
00884   int_part.resize_to( int_part.size() - int_part.m_wp, -1 );
00885     
00886     for( i = frac_part.m_msw;
00887    i >= frac_part.m_lsw && i >= frac_part.m_wp;
00888    i -- )
00889   frac_part.m_mant[i] = 0;
00890     frac_part.find_sw();
00891     if( frac_part.m_msw == frac_part.size() - 1 )
00892   frac_part.resize_to( frac_part.size() + 1, 1 );
00893 
00894     // print integer part
00895 
00896     int int_digits = 0;
00897     int int_zeros  = 0;
00898     
00899     if( ! int_part.is_zero() )
00900     {
00901   double int_wl = ( int_part.m_msw - int_part.m_wp ) * bits_in_word
00902                 + scfx_find_msb( int_part.m_mant[int_part.m_msw] ) + 1;
00903   int_digits = (int) ceil( int_wl * log10( 2. ) );
00904 
00905   int len = s.length();
00906   s.append( int_digits );
00907 
00908   bool zero_digits = ( frac_part.is_zero() && fmt != SC_F );
00909 
00910   for( i = int_digits + len - 1; i >= len; i-- )
00911   {
00912       unsigned int remainder = int_part.divide_by_ten();
00913       s[i] = static_cast<char>( '0' + remainder );
00914       
00915       if( zero_digits )
00916       {
00917     if( remainder == 0 )
00918         int_zeros ++;
00919     else
00920         zero_digits = false;
00921       }
00922   }
00923 
00924   // discard trailing zeros from int_part
00925   s.discard( int_zeros );
00926 
00927   if( s[len] == '0' )
00928   {
00929       // int_digits was overestimated by one
00930       s.remove( len );
00931       -- int_digits;
00932   }
00933     }
00934 
00935     // print fractional part
00936 
00937     int frac_digits = 0;
00938     int frac_zeros  = 0;
00939 
00940     if( ! frac_part.is_zero() )
00941     {
00942   s += '.';
00943 
00944   bool zero_digits = ( int_digits == 0 && fmt != SC_F );
00945 
00946   double frac_wl = ( frac_part.m_wp - frac_part.m_msw ) * bits_in_word
00947                  - scfx_find_msb( frac_part.m_mant[frac_part.m_msw] )
00948                        - 1;
00949   frac_zeros = (int) floor( frac_wl * log10( 2. ) );
00950 
00951   scfx_rep temp;
00952   sc_dt::multiply( temp, frac_part, pow10_fx( frac_zeros ) );
00953   frac_part = temp;
00954   if( frac_part.m_msw == frac_part.size() - 1 )
00955       frac_part.resize_to( frac_part.size() + 1, 1 );
00956   
00957   frac_digits = frac_zeros;
00958   if( ! zero_digits )
00959   {
00960       for( i = 0; i < frac_zeros; i ++ )
00961     s += '0';
00962       frac_zeros = 0;
00963   }
00964 
00965   while( ! frac_part.is_zero() )
00966   {
00967       frac_part.multiply_by_ten();
00968       int n = frac_part.m_mant[frac_part.m_msw + 1];
00969   
00970       if( zero_digits )
00971       {
00972     if( n == 0 )
00973         frac_zeros ++;
00974     else
00975         zero_digits = false;
00976       }
00977   
00978       if( ! zero_digits )
00979     s += static_cast<char>( '0' + n );
00980 
00981       frac_part.m_mant[frac_part.m_msw + 1] = 0;
00982       frac_digits ++;
00983   }
00984     }
00985 
00986     // print exponent
00987     
00988     if( fmt != SC_F )
00989     {
00990         if( frac_digits == 0 )
00991       scfx_print_exp( s, int_zeros );
00992   else if( int_digits == 0 )
00993       scfx_print_exp( s, - frac_zeros );
00994     }
00995 }
00996 
00997 void
00998 print_other( scfx_string& s, const scfx_rep& a, sc_numrep numrep, int w_prefix,
00999        sc_fmt fmt, const scfx_params* params )
01000 {
01001     scfx_rep b = a;
01002 
01003     sc_numrep numrep2 = numrep;
01004 
01005     bool numrep_is_sm = ( numrep == SC_BIN_SM ||
01006         numrep == SC_OCT_SM ||
01007         numrep == SC_HEX_SM );
01008 
01009     if( numrep_is_sm )
01010     {
01011   if( b.is_neg() )
01012   {
01013       s += '-';
01014       b = *neg_scfx_rep( a );
01015   }
01016   switch( numrep )
01017   {
01018       case SC_BIN_SM:
01019     numrep2 = SC_BIN_US;
01020     break;
01021       case SC_OCT_SM:
01022     numrep2 = SC_OCT_US;
01023     break;
01024       case SC_HEX_SM:
01025     numrep2 = SC_HEX_US;
01026     break;
01027       default:
01028     ;
01029   }
01030     }
01031     
01032     if( w_prefix != 0 ) {
01033   scfx_print_prefix( s, numrep );
01034     }
01035 
01036     numrep = numrep2;
01037 
01038     int msb, lsb;
01039 
01040     if( params != 0 )
01041     {
01042   msb = params->iwl() - 1;
01043   lsb = params->iwl() - params->wl();
01044 
01045   if( params->enc() == SC_TC_ &&
01046       ( numrep == SC_BIN_US ||
01047         numrep == SC_OCT_US ||
01048         numrep == SC_HEX_US ) &&
01049       ! numrep_is_sm &&
01050       params->wl() > 1 )
01051       -- msb;
01052   else if( params->enc() == SC_US_ &&
01053       ( numrep == SC_BIN ||
01054         numrep == SC_OCT ||
01055         numrep == SC_HEX ||
01056         numrep == SC_CSD ) )
01057       ++ msb;
01058     }
01059     else
01060     {
01061   if( b.is_zero() )
01062   {
01063       msb = 0;
01064       lsb = 0;
01065   }
01066   else
01067   {
01068       msb = ( b.m_msw - b.m_wp ) * bits_in_word
01069     + scfx_find_msb( b.m_mant[ b.m_msw ] ) + 1;
01070       while( b.get_bit( msb ) == b.get_bit( msb - 1 ) )
01071     -- msb;
01072 
01073       if( numrep == SC_BIN_US ||
01074     numrep == SC_OCT_US ||
01075     numrep == SC_HEX_US )
01076     -- msb;
01077 
01078       lsb = ( b.m_lsw - b.m_wp ) * bits_in_word
01079     + scfx_find_lsb( b.m_mant[ b.m_lsw ] );
01080   }
01081     }
01082 
01083     int step;
01084 
01085     switch( numrep )
01086     {
01087   case SC_BIN:
01088   case SC_BIN_US:
01089   case SC_CSD:
01090       step = 1;
01091      break;
01092   case SC_OCT:
01093   case SC_OCT_US:
01094       step = 3;
01095       break;
01096   case SC_HEX:
01097   case SC_HEX_US:
01098       step = 4;
01099       break;
01100   default:
01101       step = 0;
01102     }
01103 
01104     msb = (int) ceil( double( msb + 1 ) / step ) * step - 1;
01105 
01106     lsb = (int) floor( double( lsb ) / step ) * step;
01107 
01108     if( msb < 0 )
01109     {
01110   s += '.';
01111   if( fmt == SC_F )
01112   {
01113       int sign = ( b.is_neg() ) ? ( 1 << step ) - 1 : 0;
01114       for( int i = ( msb + 1 ) / step; i < 0; i ++ )
01115       {
01116     if( sign < 10 )
01117         s += static_cast<char>( sign + '0' );
01118     else
01119         s += static_cast<char>( sign + 'a' - 10 );
01120       }
01121   }
01122     }
01123 
01124     int i = msb;
01125     while( i >= lsb )
01126     {
01127         int value = 0;
01128         for( int j = step - 1; j >= 0; -- j )
01129   {
01130             value += static_cast<int>( b.get_bit( i ) ) << j;
01131             -- i;
01132         }
01133         if( value < 10 )
01134             s += static_cast<char>( value + '0' );
01135   else
01136             s += static_cast<char>( value + 'a' - 10 );
01137   if( i == -1 )
01138       s += '.';
01139     }
01140 
01141     if( lsb > 0 && fmt == SC_F )
01142     {
01143   for( int i = lsb / step; i > 0; i -- )
01144       s += '0';
01145     }
01146 
01147     if( s[s.length() - 1] == '.' )
01148   s.discard( 1 );
01149 
01150     if( fmt != SC_F )
01151     {
01152   if( msb < 0 )
01153       scfx_print_exp( s, ( msb + 1 ) / step );
01154   else if( lsb > 0 )
01155       scfx_print_exp( s, lsb / step );
01156     }
01157 
01158     if( numrep == SC_CSD )
01159   scfx_tc2csd( s, w_prefix );
01160 }
01161 
01162 const char*
01163 scfx_rep::to_string( sc_numrep numrep, int w_prefix,
01164          sc_fmt fmt, const scfx_params* params ) const
01165 {
01166     static scfx_string s;
01167 
01168     s.clear();
01169 
01170     if( is_nan() )
01171         scfx_print_nan( s );
01172     else if( is_inf() )
01173         scfx_print_inf( s, is_neg() );
01174     else if( is_neg() && ! is_zero() &&
01175        ( numrep == SC_BIN_US ||
01176          numrep == SC_OCT_US ||
01177          numrep == SC_HEX_US ) )
01178         s += "negative";
01179     else if( numrep == SC_DEC )
01180         sc_dt::print_dec( s, *this, w_prefix, fmt );
01181     else
01182         sc_dt::print_other( s, *this, numrep, w_prefix, fmt, params );
01183 
01184     return s;
01185 }
01186 
01187 
01188 // ----------------------------------------------------------------------------
01189 //  ADD
01190 //
01191 //  add two mantissas of the same size
01192 //  result has the same size
01193 //  returns carry of operation
01194 // ----------------------------------------------------------------------------
01195 
01196 static inline
01197 int
01198 add_mants( int size, scfx_mant& result,
01199      const scfx_mant& a, const scfx_mant& b )
01200 {
01201     unsigned int carry = 0;
01202 
01203     int index = 0;
01204 
01205     do
01206     {
01207         word x = a[index];
01208   word y = b[index];
01209 
01210   y += carry;
01211   carry = y < carry;
01212   y += x;
01213   carry += y < x;
01214   result[index] = y;
01215     }
01216     while( ++ index < size );
01217 
01218     return ( carry ? 1 : 0 );
01219 }
01220 
01221 
01222 static inline
01223 int
01224 sub_mants( int size, scfx_mant& result,
01225      const scfx_mant& a, const scfx_mant& b )
01226 {
01227     unsigned carry = 0;
01228 
01229     int index = 0;
01230 
01231     do
01232     {
01233   word x = a[index];
01234   word y = b[index];
01235 
01236   y += carry;
01237   carry = y < carry;
01238   y = x - y;
01239   carry += y > x;
01240   result[index] = y;
01241     }
01242     while( ++ index < size );
01243 
01244     return ( carry ? 1 : 0 );
01245 }
01246 
01247 
01248 scfx_rep*
01249 add_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int max_wl )
01250 {
01251     scfx_rep& result = *new scfx_rep;
01252 
01253     //
01254     // check for special cases
01255     //
01256 
01257     if( lhs.is_nan() || rhs.is_nan()
01258     ||  ( lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign ) )
01259     {
01260   result.set_nan();
01261   return &result;
01262     }
01263 
01264     if( lhs.is_inf() )
01265     {
01266   result.set_inf( lhs.m_sign );
01267   return &result;
01268     }
01269 
01270     if( rhs.is_inf() )
01271     {
01272   result.set_inf( rhs.m_sign );
01273   return &result;
01274     }
01275 
01276     //
01277     // align operands if needed
01278     //
01279 
01280     scfx_mant_ref lhs_mant;
01281     scfx_mant_ref rhs_mant;
01282 
01283     int len_mant = lhs.size();
01284     int new_wp = lhs.m_wp;
01285 
01286     align( lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant );
01287 
01288     //
01289     // size the result mantissa
01290     //
01291 
01292     result.resize_to( len_mant );
01293     result.m_wp = new_wp;
01294 
01295     //
01296     // do it
01297     //
01298 
01299     if( lhs.m_sign == rhs.m_sign )
01300     {
01301   add_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
01302   result.m_sign = lhs.m_sign;
01303     }
01304     else
01305     {
01306   int cmp = compare_abs( lhs, rhs );
01307 
01308   if( cmp == 1 )
01309   {
01310       sub_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
01311       result.m_sign = lhs.m_sign;
01312   }
01313   else if ( cmp == -1 )
01314   {
01315       sub_mants( len_mant, result.m_mant, rhs_mant, lhs_mant );
01316       result.m_sign = rhs.m_sign;
01317   }
01318   else
01319   {
01320       result.m_mant.clear();
01321       result.m_sign = 1;
01322   }
01323     }
01324 
01325     result.find_sw();
01326     result.round( max_wl );
01327 
01328     return &result;
01329 }
01330 
01331 
01332 // ----------------------------------------------------------------------------
01333 //  SUB
01334 //
01335 //  sub two word's of the same size
01336 //  result has the same size
01337 //  returns carry of operation
01338 // ----------------------------------------------------------------------------
01339 
01340 static inline
01341 int
01342 sub_with_index(       scfx_mant& a, int a_msw, int a_lsw,
01343     const scfx_mant& b, int b_msw, int b_lsw )
01344 {
01345     unsigned carry = 0;
01346 
01347     int size    = b_msw - b_lsw;
01348     int a_index = a_msw - size;
01349     int b_index = b_msw - size;
01350 
01351     do
01352     {
01353   word x = a[a_index];
01354   word y = b[b_index];
01355 
01356   y += carry;
01357   carry = y < carry;
01358   y = x - y;
01359   carry += y > x;
01360   a[a_index] = y;
01361 
01362   a_index ++;
01363   b_index ++;
01364     }
01365     while( size -- );
01366 
01367     if( carry )
01368     {
01369         // special case: a[a_msw + 1 ] == 1
01370         a[a_msw + 1] = 0;
01371     }
01372 
01373     return ( carry ? 1 : 0 );
01374 }
01375 
01376 
01377 scfx_rep*
01378 sub_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int max_wl )
01379 {
01380     scfx_rep& result = *new scfx_rep;
01381 
01382     //
01383     // check for special cases
01384     //
01385 
01386     if( lhs.is_nan() || rhs.is_nan()
01387     ||  ( lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign ) )
01388     {
01389   result.set_nan();
01390   return &result;
01391     }
01392 
01393     if( lhs.is_inf() )
01394     {
01395   result.set_inf( lhs.m_sign );
01396   return &result;
01397     }
01398 
01399     if( rhs.is_inf() )
01400     {
01401   result.set_inf( -1 * rhs.m_sign );
01402   return &result;
01403     }
01404 
01405     //
01406     // align operands if needed
01407     //
01408 
01409     scfx_mant_ref lhs_mant;
01410     scfx_mant_ref rhs_mant;
01411 
01412     int len_mant = lhs.size();
01413     int new_wp = lhs.m_wp;
01414 
01415     align( lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant );
01416 
01417     //
01418     // size the result mantissa
01419     //
01420 
01421     result.resize_to( len_mant );
01422     result.m_wp = new_wp;
01423 
01424     //
01425     // do it
01426     //
01427 
01428     if( lhs.m_sign != rhs.m_sign )
01429     {
01430   add_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
01431   result.m_sign = lhs.m_sign;
01432     }
01433     else
01434     {
01435   int cmp = compare_abs( lhs, rhs );
01436 
01437   if( cmp == 1 )
01438   {
01439       sub_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
01440       result.m_sign = lhs.m_sign;
01441   }
01442   else if ( cmp == -1 )
01443   {
01444       sub_mants( len_mant, result.m_mant, rhs_mant, lhs_mant );
01445       result.m_sign = -rhs.m_sign;
01446   } else {
01447       result.m_mant.clear();
01448       result.m_sign = 1;
01449   }
01450     }
01451 
01452     result.find_sw();
01453     result.round( max_wl );
01454 
01455     return &result;
01456 }
01457 
01458 
01459 // ----------------------------------------------------------------------------
01460 //  MUL
01461 // ----------------------------------------------------------------------------
01462 
01463 union long_short
01464 {
01465     word l;
01466     struct
01467     {
01468 #if defined( SCFX_BIG_ENDIAN )
01469         half_word u;
01470         half_word l;
01471 #elif defined( SCFX_LITTLE_ENDIAN )
01472         half_word l;
01473         half_word u;
01474 #endif
01475     } s;
01476 };
01477 
01478 
01479 #if defined( SCFX_BIG_ENDIAN )
01480 static const int half_word_incr = -1;
01481 #elif defined( SCFX_LITTLE_ENDIAN )
01482 static const int half_word_incr = 1;
01483 #endif
01484 
01485 
01486 void
01487 multiply( scfx_rep& result, const scfx_rep& lhs, const scfx_rep& rhs,
01488     int max_wl )
01489 {
01490     //
01491     // check for special cases
01492     //
01493 
01494     if( lhs.is_nan() || rhs.is_nan()
01495     ||  lhs.is_inf() && rhs.is_zero()
01496     ||  lhs.is_zero() && rhs.is_inf() )
01497     {
01498   result.set_nan();
01499   return;
01500     }
01501 
01502     if( lhs.is_inf() || rhs.is_inf() )
01503     {
01504   result.set_inf( lhs.m_sign * rhs.m_sign );
01505   return;
01506     }
01507     
01508     if( lhs.is_zero() || rhs.is_zero() ) {
01509   result.set_zero( lhs.m_sign * rhs.m_sign );
01510   return;
01511     }
01512 
01513     //
01514     // do it
01515     //
01516 
01517     int len_lhs = lhs.m_msw - lhs.m_lsw + 1;
01518     int len_rhs = rhs.m_msw - rhs.m_lsw + 1;
01519 
01520     int new_size = sc_max( min_mant, len_lhs + len_rhs );
01521     int new_wp   = ( lhs.m_wp - lhs.m_lsw ) + ( rhs.m_wp - rhs.m_lsw );
01522     int new_sign = lhs.m_sign * rhs.m_sign;
01523 
01524     result.resize_to( new_size );
01525     result.m_mant.clear();
01526     result.m_wp    = new_wp;
01527     result.m_sign  = new_sign;
01528     result.m_state = scfx_rep::normal;
01529 
01530     half_word *s1 = lhs.m_mant.half_addr( lhs.m_lsw );
01531     half_word *s2 = rhs.m_mant.half_addr( rhs.m_lsw );
01532 
01533     half_word *t = result.m_mant.half_addr();
01534 
01535     len_lhs <<= 1;
01536     len_rhs <<= 1;
01537 
01538     int i1, i2;
01539 
01540     for( i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr )
01541     {
01542   register long_short ls;
01543   ls.l = 0;
01544 
01545   half_word v1 = s1[i1];
01546 
01547   for( i2  = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr )
01548   {
01549       ls.l  += v1 * s2[i2];
01550       ls.s.l = ls.s.u + ( ( t[i2] += ls.s.l ) < ls.s.l );
01551       ls.s.u = 0;
01552   }
01553 
01554   t[i2] = ls.s.l;
01555   t += half_word_incr;
01556     }
01557 
01558     result.find_sw();
01559     result.round( max_wl );
01560 }
01561 
01562 
01563 // ----------------------------------------------------------------------------
01564 //  DIV
01565 // ----------------------------------------------------------------------------
01566 
01567 scfx_rep*
01568 div_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int div_wl )
01569 {
01570     scfx_rep& result = *new scfx_rep;
01571 
01572     //
01573     // check for special cases
01574     //
01575 
01576     if( lhs.is_nan() || rhs.is_nan() || lhs.is_inf() && rhs.is_inf() ||
01577   lhs.is_zero() && rhs.is_zero() )
01578     {
01579   result.set_nan();
01580   return &result;
01581     }
01582 
01583     if( lhs.is_inf() || rhs.is_zero() )
01584     {
01585   result.set_inf( lhs.m_sign * rhs.m_sign );
01586   return &result;
01587     }
01588 
01589     if( lhs.is_zero() || rhs.is_inf() )
01590     {
01591   result.set_zero( lhs.m_sign * rhs.m_sign );
01592   return &result;
01593     }
01594 
01595     //
01596     // do it
01597     //
01598 
01599     // compute one bit more for rounding
01600     div_wl ++;
01601 
01602     result.resize_to( sc_max( n_word( div_wl ) + 1, min_mant ) );
01603     result.m_mant.clear();
01604     result.m_sign = lhs.m_sign * rhs.m_sign;
01605 
01606     int msb_lhs = scfx_find_msb( lhs.m_mant[lhs.m_msw] )
01607           + ( lhs.m_msw - lhs.m_wp ) * bits_in_word;
01608     int msb_rhs = scfx_find_msb( rhs.m_mant[rhs.m_msw] )
01609           + ( rhs.m_msw - rhs.m_wp ) * bits_in_word;
01610 
01611     int msb_res = msb_lhs - msb_rhs;
01612     int to_shift = -msb_res % bits_in_word;
01613     int result_index;
01614 
01615     int c = ( msb_res % bits_in_word >= 0 ) ? 1 : 0;
01616 
01617     result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word;
01618     result.m_wp   = (result.size() - c) - msb_res / bits_in_word;
01619 
01620     scfx_rep remainder = lhs;
01621 
01622     // align msb from remainder to msb from rhs
01623     remainder.lshift( to_shift );
01624 
01625     // make sure msw( remainder ) < size - 1
01626     if( remainder.m_msw == remainder.size() - 1 )
01627   remainder.resize_to( remainder.size() + 1, 1 );
01628 
01629     // make sure msw( remainder ) >= msw( rhs )!
01630     int msw_diff = rhs.m_msw - remainder.m_msw;
01631     if (msw_diff > 0)
01632   remainder.resize_to( remainder.size() + msw_diff, -1 );
01633 
01634     int counter;
01635 
01636     for( counter = div_wl; counter && ! remainder.is_zero(); counter -- )
01637     {
01638   if( compare_msw_ff( rhs, remainder ) <= 0 )
01639   {
01640       result.set_bin( result_index );
01641       sub_with_index( remainder.m_mant, remainder.m_msw, remainder.m_lsw,
01642           rhs.m_mant, rhs.m_msw, rhs.m_lsw );
01643   }
01644   result_index --;
01645   remainder.shift_left( 1 );
01646         remainder.m_lsw = remainder.find_lsw();
01647     }
01648 
01649     // perform convergent rounding, if needed
01650     if( counter == 0 )
01651     {
01652   int index = result_index + 1 - result.m_wp * bits_in_word;
01653 
01654   scfx_index x = result.calc_indices( index );
01655   scfx_index x1 = result.calc_indices( index + 1 );
01656 
01657   if( result.o_bit_at( x ) && result.o_bit_at( x1 ) )
01658       result.q_incr( x );
01659 
01660   result.m_r_flag = true;
01661     }
01662 
01663     result.find_sw();
01664 
01665     return &result;
01666 }
01667 
01668 
01669 // ----------------------------------------------------------------------------
01670 //  destructive shift mantissa to the left
01671 // ----------------------------------------------------------------------------
01672 
01673 void
01674 scfx_rep::lshift( int n )
01675 {
01676     if( n == 0 )
01677         return;
01678 
01679     if( n < 0 )
01680     {
01681         rshift( -n );
01682   return;
01683     }
01684 
01685     if( is_normal() )
01686     {
01687         int shift_bits  = n % bits_in_word;
01688   int shift_words = n / bits_in_word;
01689 
01690   // resize if needed
01691   if( m_msw == size() - 1 &&
01692       scfx_find_msb( m_mant[m_msw] ) >= bits_in_word - shift_bits )
01693       resize_to( size() + 1, 1 );
01694 
01695   // do it
01696   m_wp -= shift_words;
01697   shift_left( shift_bits );
01698   find_sw();
01699     }
01700 }
01701 
01702 
01703 // ----------------------------------------------------------------------------
01704 //  destructive shift mantissa to the right
01705 // ----------------------------------------------------------------------------
01706 
01707 void
01708 scfx_rep::rshift( int n )
01709 {
01710     if( n == 0 )
01711         return;
01712 
01713     if( n < 0 )
01714     {
01715         lshift( -n );
01716   return;
01717     }
01718 
01719     if( is_normal() )
01720     {
01721         int shift_bits  = n % bits_in_word;
01722   int shift_words = n / bits_in_word;
01723 
01724   // resize if needed
01725   if( m_lsw == 0 && scfx_find_lsb( m_mant[m_lsw] ) < shift_bits )
01726       resize_to( size() + 1, -1 );
01727 
01728   // do it
01729   m_wp += shift_words;
01730   shift_right( shift_bits );
01731   find_sw();
01732     }
01733 }
01734 
01735 
01736 // ----------------------------------------------------------------------------
01737 //  FRIEND FUNCTION : compare_abs
01738 //
01739 //  Compares the absolute values of two scfx_reps, excluding the special cases.
01740 // ----------------------------------------------------------------------------
01741 
01742 int
01743 compare_abs( const scfx_rep& a, const scfx_rep& b )
01744 {
01745     // check for zero
01746 
01747     word a_word = a.m_mant[a.m_msw];
01748     word b_word = b.m_mant[b.m_msw];
01749   
01750     if( a_word == 0 || b_word == 0 )
01751     {
01752   if( a_word != 0 )
01753       return 1;
01754   if( b_word != 0 )
01755       return -1;
01756   return 0;
01757     }
01758 
01759     // compare msw index
01760 
01761     int a_msw = a.m_msw - a.m_wp;
01762     int b_msw = b.m_msw - b.m_wp;
01763 
01764     if( a_msw > b_msw )
01765   return 1;
01766 
01767     if( a_msw < b_msw )
01768   return -1;
01769 
01770     // compare content
01771 
01772     int a_i = a.m_msw;
01773     int b_i = b.m_msw;
01774 
01775     while( a_i >= a.m_lsw && b_i >= b.m_lsw )
01776     {
01777   a_word = a.m_mant[a_i];
01778   b_word = b.m_mant[b_i];
01779   if( a_word > b_word )
01780       return 1;
01781   if( a_word < b_word )
01782       return -1;
01783   -- a_i;
01784   -- b_i;
01785     }
01786 
01787     bool a_zero = true;
01788     while( a_i >= a.m_lsw )
01789     {
01790   a_zero = a_zero && ( a.m_mant[a_i] == 0 );
01791   -- a_i;
01792     }
01793   
01794     bool b_zero = true;
01795     while( b_i >= b.m_lsw )
01796     {
01797   b_zero = b_zero && ( b.m_mant[b_i] == 0 );
01798   -- b_i;
01799     }
01800 
01801     // assertion: a_zero || b_zero == true
01802 
01803     if( ! a_zero && b_zero )
01804   return 1;
01805 
01806     if( a_zero && ! b_zero )
01807   return -1;
01808 
01809     return 0;
01810 }
01811 
01812 
01813 // ----------------------------------------------------------------------------
01814 //  FRIEND FUNCTION : cmp_scfx_rep
01815 //
01816 //  Compares the values of two scfx_reps, including the special cases.
01817 // ----------------------------------------------------------------------------
01818 
01819 int
01820 cmp_scfx_rep( const scfx_rep& a, const scfx_rep& b )
01821 {
01822     // handle special cases
01823 
01824     if( a.is_nan() || b.is_nan() )
01825     {
01826 #if 0
01827   if( a.is_nan() && b.is_nan() )
01828   {
01829       return 0;
01830   }
01831 #endif
01832   return 2;
01833     }
01834 
01835     if( a.is_inf() || b.is_inf() )
01836     {
01837   if( a.is_inf() )
01838   {
01839       if( ! a.is_neg() )
01840       {
01841     if( b.is_inf() && ! b.is_neg() )
01842     {
01843         return 0;
01844     }
01845     else
01846     {
01847         return 1;
01848     }
01849       }
01850       else
01851       {
01852     if( b.is_inf() && b.is_neg() )
01853     {
01854         return 0;
01855     }
01856     else
01857     {
01858         return -1;
01859     }
01860       }
01861   }
01862   if( b.is_inf() )
01863   {
01864       if( ! b.is_neg() )
01865       {
01866     return -1;
01867       }
01868       else
01869       {
01870     return 1;
01871       }
01872   }
01873     }
01874   
01875     if( a.is_zero() && b.is_zero() )
01876     {
01877   return 0;
01878     }
01879 
01880     // compare sign
01881 
01882     if( a.m_sign != b.m_sign )
01883     {
01884   return a.m_sign;
01885     }
01886 
01887     return ( a.m_sign * compare_abs( a, b ) );
01888 }
01889 
01890 
01891 // ----------------------------------------------------------------------------
01892 //  PRIVATE METHOD : quantization
01893 //
01894 //  Performs destructive quantization.
01895 // ----------------------------------------------------------------------------
01896 
01897 void
01898 scfx_rep::quantization( const scfx_params& params, bool& q_flag )
01899 {
01900     scfx_index x = calc_indices( params.iwl() - params.wl() );
01901 
01902     if( x.wi() < 0 )
01903         return;
01904 
01905     if( x.wi() >= size() )
01906         resize_to( x.wi() + 1, 1 );
01907 
01908     bool qb = q_bit( x );
01909     bool qz = q_zero( x );
01910 
01911     q_flag = ( qb || ! qz );
01912 
01913     if( q_flag )
01914     {
01915         switch( params.q_mode() )
01916   {
01917             case SC_TRN:      // truncation
01918       {
01919           if( is_neg() )
01920         q_incr( x );
01921     break;
01922       }
01923             case SC_RND:      // rounding to plus infinity
01924       {
01925           if( ! is_neg() )
01926     {
01927         if( qb )
01928       q_incr( x );
01929     }
01930     else
01931     {
01932         if( qb && ! qz )
01933       q_incr( x );
01934     }
01935     break;
01936       }
01937             case SC_TRN_ZERO:     // truncation to zero
01938       {
01939           break;
01940       }
01941             case SC_RND_INF:      // rounding to infinity
01942       {
01943           if( qb )
01944         q_incr( x );
01945     break;
01946       }
01947             case SC_RND_CONV:     // convergent rounding
01948       {
01949     if( qb && ! qz || qb && qz && q_odd( x ) )
01950         q_incr( x );
01951     break;
01952       }
01953             case SC_RND_ZERO:     // rounding to zero
01954       {
01955     if( qb && ! qz )
01956         q_incr( x );
01957     break;
01958       }
01959             case SC_RND_MIN_INF:    // rounding to minus infinity
01960       {
01961     if( ! is_neg() )
01962     {
01963         if( qb && ! qz )
01964       q_incr( x );
01965     }
01966     else
01967     {
01968         if( qb )
01969       q_incr( x );
01970     }
01971     break;
01972       }
01973             default:
01974           ;
01975   }
01976   q_clear( x );
01977   
01978   find_sw();
01979     }
01980 }
01981 
01982 
01983 // ----------------------------------------------------------------------------
01984 //  PRIVATE METHOD : overflow
01985 //
01986 //  Performs destructive overflow handling.
01987 // ----------------------------------------------------------------------------
01988 
01989 void
01990 scfx_rep::overflow( const scfx_params& params, bool& o_flag )
01991 {
01992     scfx_index x = calc_indices( params.iwl() - 1 );
01993 
01994     if( x.wi() >= size() )
01995         resize_to( x.wi() + 1, 1 );
01996 
01997     if( x.wi() < 0 )
01998     {
01999         resize_to( size() - x.wi(), -1 );
02000         x.wi( 0 );
02001     }
02002 
02003     bool zero_left = o_zero_left( x );
02004     bool bit_at = o_bit_at( x );
02005     bool zero_right = o_zero_right( x );
02006 
02007     bool under = false;
02008     bool over = false;
02009 
02010     sc_enc enc = params.enc();
02011 
02012     if( enc == SC_TC_ )
02013     {
02014   if( is_neg() )
02015   {
02016       if( params.o_mode() == SC_SAT_SYM )
02017     under = ( ! zero_left || bit_at );
02018       else
02019     under = ( ! zero_left || zero_left && bit_at && ! zero_right );
02020   }
02021   else
02022       over = ( ! zero_left || bit_at );
02023     }
02024     else
02025     {
02026   if( is_neg() )
02027       under = ( ! is_zero() );
02028         else
02029       over = ( ! zero_left );
02030     }
02031 
02032     o_flag = ( under || over );
02033 
02034     if( o_flag )
02035     {
02036   scfx_index x2 = calc_indices( params.iwl() - params.wl() );
02037 
02038   if( x2.wi() < 0 )
02039   {
02040       resize_to( size() - x2.wi(), -1 );
02041       x.wi( x.wi() - x2.wi() );
02042       x2.wi( 0 );
02043   }
02044 
02045   switch( params.o_mode() )
02046   {
02047             case SC_WRAP:     // wrap-around
02048       {
02049     int n_bits = params.n_bits();
02050 
02051     if( n_bits == 0 )
02052     {
02053         // wrap-around all 'wl' bits
02054         toggle_tc();
02055         o_extend( x, enc );
02056         toggle_tc();
02057     }
02058     else if( n_bits < params.wl() )
02059     {
02060         scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits );
02061 
02062         // wrap-around least significant 'wl - n_bits' bits;
02063         // saturate most significant 'n_bits' bits
02064         toggle_tc();
02065         o_set( x, x3, enc, under );
02066         o_extend( x, enc );
02067         toggle_tc();
02068     }
02069     else
02070     {
02071         // saturate all 'wl' bits
02072