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-2006 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.4 (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 // $Log: scfx_rep.cpp,v $
00039 // Revision 1.1.1.1  2006/12/15 20:31:36  acg
00040 // SystemC 2.2
00041 //
00042 // Revision 1.3  2006/01/13 18:53:58  acg
00043 // Andy Goodrich: added $Log command so that CVS comments are reproduced in
00044 // the source.
00045 //
00046 
00047 #include "sysc/utils/sc_machine.h"
00048 #include "sysc/datatypes/fx/scfx_rep.h"
00049 
00050 #include "sysc/datatypes/fx/scfx_ieee.h"
00051 #include "sysc/datatypes/fx/scfx_pow10.h"
00052 #include "sysc/datatypes/fx/scfx_utils.h"
00053 
00054 #include "sysc/datatypes/bit/sc_bv_base.h"
00055 
00056 #include <ctype.h>
00057 #include <math.h>
00058 
00059 
00060 namespace sc_dt
00061 {
00062 
00063 // ----------------------------------------------------------------------------
00064 //  some utilities
00065 // ----------------------------------------------------------------------------
00066 
00067 static scfx_pow10 pow10_fx;
00068 
00069 static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int;
00070 
00071 static inline
00072 int
00073 n_word( int x )
00074 {
00075     return ( x + bits_in_word - 1 ) / bits_in_word;
00076 }
00077 
00078 
00079 // ----------------------------------------------------------------------------
00080 //  CONSTRUCTORS
00081 // ----------------------------------------------------------------------------
00082 
00083 scfx_rep::scfx_rep()
00084 : m_mant( min_mant ), m_r_flag( false )
00085 {
00086     set_zero();
00087 }
00088 
00089 scfx_rep::scfx_rep( int a )
00090 : m_mant( min_mant ), m_r_flag( false )
00091 {
00092     if( a != 0 )
00093     {
00094         m_mant.clear();
00095     m_wp = m_msw = m_lsw = 2;
00096     m_state = normal;
00097     if( a > 0 )
00098     {
00099         m_mant[2] = a;
00100         m_sign = 1;
00101     }
00102     else
00103     {
00104         m_mant[2] = -a;
00105         m_sign = -1;
00106     }
00107     }
00108     else
00109         set_zero();
00110 }
00111 
00112 scfx_rep::scfx_rep( unsigned int a )
00113 : m_mant( min_mant ), m_r_flag( false )
00114 {
00115     if( a != 0 )
00116     {
00117         m_mant.clear();
00118     m_wp = m_msw = m_lsw = 2;
00119     m_state = normal;
00120     m_mant[2] = a;
00121     m_sign = 1;
00122     }
00123     else
00124         set_zero();
00125 }
00126 
00127 scfx_rep::scfx_rep( long a )
00128 : m_mant( min_mant ), m_r_flag( false )
00129 {
00130     if( a != 0 )
00131     {
00132         m_mant.clear();
00133     m_state = normal;
00134         if ( a > 0 )
00135         {
00136         m_sign = 1;
00137         }
00138         else
00139         {
00140             a = -a;
00141             m_sign = -1;
00142         } 
00143 #       if defined(SC_LONG_64)
00144             m_wp = 1;
00145             m_mant[1] = static_cast<word>( a );
00146             m_mant[2] = static_cast<word>( a >> bits_in_word );
00147         find_sw();
00148 #       else
00149             m_wp = 2;
00150             m_msw = 2;
00151             m_lsw = 2;
00152             m_mant[2] = a;
00153 #       endif
00154 
00155     }
00156     else
00157         set_zero();
00158 }
00159 
00160 scfx_rep::scfx_rep( unsigned long a )
00161 : m_mant( min_mant ), m_r_flag( false )
00162 {
00163     if( a != 0 )
00164     {
00165         m_mant.clear();
00166     m_wp = m_msw = m_lsw = 2;
00167     m_state = normal;
00168 #       if defined(SC_LONG_64)
00169         m_wp = 1;
00170         m_mant[1] = static_cast<word>( a );
00171         m_mant[2] = static_cast<word>( a >> bits_in_word );
00172         find_sw();
00173 #       else
00174         m_wp = 2;
00175         m_msw = 2;
00176         m_lsw = 2;
00177         m_mant[2] = a;
00178 #   endif
00179     m_sign = 1;
00180     }
00181     else
00182         set_zero();
00183 }
00184 
00185 scfx_rep::scfx_rep( double a )
00186 : m_mant( min_mant ), m_wp( 0 ), m_state( normal ), m_msw( 0 ), m_lsw( 0 ),
00187   m_r_flag( false )
00188 {
00189     m_mant.clear();
00190 
00191     scfx_ieee_double id( a );
00192 
00193     m_sign = id.negative() ? -1 : 1;
00194 
00195     if( id.is_nan() )
00196         m_state = not_a_number;
00197     else if( id.is_inf() )
00198         m_state = infinity;
00199     else if( id.is_subnormal() )
00200     {
00201     m_mant[0] = id.mantissa1();
00202     m_mant[1] = id.mantissa0();
00203     normalize( id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE );
00204     }
00205     else if( id.is_normal() )
00206     {
00207     m_mant[0] = id.mantissa1();
00208     m_mant[1] = id.mantissa0() | ( 1 << mantissa0_size );
00209     normalize( id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE );
00210     }
00211 }
00212 
00213 scfx_rep::scfx_rep( int64 a )
00214 : m_mant( min_mant ), m_r_flag( false )
00215 {
00216     if( a != 0 )
00217     {
00218         m_mant.clear();
00219     m_wp = 1;
00220     m_state = normal;
00221     if( a > 0 )
00222     {
00223         m_mant[1] = static_cast<word>( a );
00224         m_mant[2] = static_cast<word>( a >> bits_in_word );
00225         m_sign = 1;
00226     }
00227     else
00228     {
00229         m_mant[1] = static_cast<word>( -a );
00230         m_mant[2] = static_cast<word>( (-a) >> bits_in_word );
00231         m_sign = -1;
00232     }
00233     find_sw();
00234     }
00235     else
00236         set_zero();
00237 }
00238 
00239 scfx_rep::scfx_rep( uint64 a )
00240 : m_mant( min_mant ), m_r_flag( false )
00241 {
00242     if( a != 0 )
00243     {
00244         m_mant.clear();
00245     m_wp = 1;
00246     m_state = normal;
00247     m_mant[1] = static_cast<word>( a );
00248     m_mant[2] = static_cast<word>( a >> bits_in_word );
00249     m_sign = 1;
00250     find_sw();
00251     }
00252     else
00253         set_zero();
00254 }
00255 
00256 scfx_rep::scfx_rep( const sc_signed& a )
00257 : m_mant( min_mant ), m_r_flag( false )
00258 {
00259     if( a.iszero() )
00260     set_zero();
00261     else
00262     {
00263     int words = n_word( a.length() );
00264     if( words > size() )
00265         resize_to( words );
00266     m_mant.clear();
00267     m_wp = 0;
00268     m_state = normal;
00269     if( a.sign() )
00270     {
00271         sc_signed a2 = -a;
00272         for( int i = 0; i < a2.length(); ++ i )
00273         {
00274         if( a2[i] )
00275         {
00276             scfx_index x = calc_indices( i );
00277             m_mant[x.wi()] |= 1 << x.bi();
00278         }
00279         }
00280         m_sign = -1;
00281     }
00282     else
00283     {
00284         for( int i = 0; i < a.length(); ++ i )
00285         {
00286         if( a[i] )
00287         {
00288             scfx_index x = calc_indices( i );
00289             m_mant[x.wi()] |= 1 << x.bi();
00290         }
00291         }
00292         m_sign = 1;
00293     }
00294     find_sw();
00295     }
00296 }
00297 
00298 scfx_rep::scfx_rep( const sc_unsigned& a )
00299 : m_mant( min_mant ), m_r_flag( false )
00300 {
00301     if( a.iszero() )
00302     set_zero();
00303     else
00304     {
00305     int words = n_word( a.length() );
00306     if( words > size() )
00307         resize_to( words );
00308     m_mant.clear();
00309     m_wp = 0;
00310     m_state = normal;
00311     for( int i = 0; i < a.length(); ++ i )
00312     {
00313         if( a[i] )
00314         {
00315         scfx_index x = calc_indices( i );
00316         m_mant[x.wi()] |= 1 << x.bi();
00317         }
00318     }
00319     m_sign = 1;
00320     find_sw();
00321     }
00322 }
00323 
00324 
00325 // copy constructor
00326 
00327 scfx_rep::scfx_rep( const scfx_rep& a )
00328 : m_mant( a.m_mant ), m_wp( a.m_wp ), m_sign( a.m_sign ), m_state( a.m_state ),
00329   m_msw( a.m_msw ), m_lsw( a.m_lsw ), m_r_flag( false )
00330 {}
00331 
00332 
00333 // ----------------------------------------------------------------------------
00334 //  OPERATORS : new, delete
00335 //
00336 //  Memory management for class scfx_rep.
00337 // ----------------------------------------------------------------------------
00338 
00339 union scfx_rep_node
00340 {
00341     char           data[sizeof( scfx_rep )];
00342     scfx_rep_node* next;
00343 };
00344 
00345 
00346 static scfx_rep_node* list = 0;
00347 
00348 
00349 void*
00350 scfx_rep::operator new( std::size_t size )
00351 {
00352     const int ALLOC_SIZE = 1024;
00353 
00354     if( size != sizeof( scfx_rep ) )
00355     return ::operator new( size );
00356 
00357     if( ! list )
00358     {
00359     list = new scfx_rep_node[ALLOC_SIZE];
00360     for( int i = 0; i < ALLOC_SIZE - 1; i ++ )
00361         list[i].next = list + i + 1;
00362     list[ALLOC_SIZE - 1].next = 0;
00363     }
00364 
00365     scfx_rep* ptr = reinterpret_cast<scfx_rep*>( list->data );
00366     list = list->next;
00367 
00368     return ptr;
00369 }
00370 
00371 
00372 void scfx_rep::operator delete( void* ptr, std::size_t size )
00373 {
00374     if( size != sizeof( scfx_rep ) )
00375     {
00376     ::operator delete( ptr );
00377     return;
00378     }
00379 
00380     scfx_rep_node* node = static_cast<scfx_rep_node*>( ptr );
00381     node->next = list;
00382     list = node;
00383 }
00384 
00385 
00386 // ----------------------------------------------------------------------------
00387 //  METHOD : from_string
00388 //
00389 //  Convert from character string to sc_fxrep.
00390 // ----------------------------------------------------------------------------
00391 
00392 #define SCFX_FAIL_IF_(cnd)                                                    \
00393 {                                                                             \
00394     if( ( cnd ) )                                                             \
00395     {                                                                         \
00396         m_state = not_a_number;                                               \
00397     m_mant.clear(); /* to avoid Purify UMRs during assignment */          \
00398         return;                                                               \
00399     }                                                                         \
00400 }
00401 
00402 
00403 void
00404 scfx_rep::from_string( const char* s, int cte_wl )
00405 {
00406     SCFX_FAIL_IF_( s == 0 || *s == 0 );
00407 
00408     scfx_string s2;
00409     s2 += s;
00410     s2 += '\0';
00411 
00412     bool sign_char;
00413     m_sign = scfx_parse_sign( s, sign_char );
00414 
00415     sc_numrep numrep = scfx_parse_prefix( s );
00416 
00417     int base = 0;
00418 
00419     switch( numrep )
00420     {
00421     case SC_DEC:
00422     {
00423         base = 10;
00424         if( scfx_is_nan( s ) )
00425         {   // special case: NaN
00426         m_state = not_a_number;
00427         m_mant.clear(); /* to avoid Purify UMRs during assignment */
00428         return;
00429         }
00430         if( scfx_is_inf( s ) )
00431         {   // special case: Infinity
00432         m_state = infinity;
00433         m_mant.clear(); /* to avoid Purify UMRs during assignment */
00434         return;
00435         }
00436         break;
00437     }
00438     case SC_BIN:
00439     case SC_BIN_US:
00440     {
00441         SCFX_FAIL_IF_( sign_char );
00442         base = 2;
00443         break;
00444     }
00445     
00446     case SC_BIN_SM:
00447     {
00448         base = 2;
00449         break;
00450     }
00451     case SC_OCT:
00452     case SC_OCT_US:
00453     {
00454         SCFX_FAIL_IF_( sign_char );
00455         base = 8;
00456         break;
00457     }
00458     case SC_OCT_SM:
00459     {
00460         base = 8;
00461         break;
00462     }
00463     case SC_HEX:
00464     case SC_HEX_US:
00465     {
00466         SCFX_FAIL_IF_( sign_char );
00467         base = 16;
00468         break;
00469     }
00470     case SC_HEX_SM:
00471     {
00472         base = 16;
00473         break;
00474     }
00475     case SC_CSD:
00476     {
00477         SCFX_FAIL_IF_( sign_char );
00478         base = 2;
00479         scfx_csd2tc( s2 );
00480         s = (const char*) s2 + 4;
00481         numrep = SC_BIN;
00482         break;
00483     }
00484         default:;
00485     }
00486 
00487     //
00488     // find end of mantissa and count the digits and points
00489     //
00490 
00491     const char *end = s;
00492     bool based_point = false;
00493     int int_digits = 0;
00494     int frac_digits = 0;
00495 
00496     while( *end )
00497     {
00498     if( scfx_exp_start( end ) )
00499         break;
00500     
00501     if( *end == '.' )
00502     {
00503         SCFX_FAIL_IF_( based_point );
00504         based_point = true;
00505     }
00506     else
00507     {
00508         SCFX_FAIL_IF_( ! scfx_is_digit( *end, numrep ) );
00509         if( based_point )
00510         frac_digits ++;
00511         else
00512         int_digits ++;
00513     }
00514 
00515     ++ end;
00516     }
00517 
00518     SCFX_FAIL_IF_( int_digits == 0 && frac_digits == 0 );
00519 
00520     // [ exponent ]
00521     
00522     int exponent = 0;
00523 
00524     if( *end )
00525     {
00526     for( const char *e = end + 2; *e; ++ e )
00527         SCFX_FAIL_IF_( ! scfx_is_digit( *e, SC_DEC ) );
00528     exponent = atoi( end + 1 );
00529     }
00530 
00531     //
00532     // check if the mantissa is negative
00533     //
00534 
00535     bool mant_is_neg = false;
00536 
00537     switch( numrep )
00538     {
00539     case SC_BIN:
00540     case SC_OCT:
00541     case SC_HEX:
00542     {
00543         const char* p = s;
00544         if( *p == '.' )
00545         ++ p;
00546 
00547         mant_is_neg = ( scfx_to_digit( *p, numrep ) >= ( base >> 1 ) );
00548 
00549         break;
00550     }
00551     default:
00552         ;
00553     }
00554 
00555     //
00556     // convert the mantissa
00557     //
00558 
00559     switch( base )
00560     {
00561         case 2:
00562     {
00563         int bit_offset = exponent % bits_in_word;
00564         int word_offset = exponent / bits_in_word;
00565 
00566         int_digits += bit_offset;
00567         frac_digits -= bit_offset;
00568 
00569         int words = n_word( int_digits ) + n_word( frac_digits );
00570         if( words > size() )
00571         resize_to( words );
00572         m_mant.clear();
00573 
00574         int j = n_word( frac_digits ) * bits_in_word + int_digits - 1;
00575         
00576         for( ; s < end; s ++ )
00577         {
00578         switch( *s )
00579         {
00580             case '1':
00581                 set_bin( j );
00582             case '0':
00583             j --;
00584             case '.':
00585             break;
00586             default:
00587             SCFX_FAIL_IF_( true );  // should not happen
00588         }
00589         }
00590 
00591         m_wp = n_word( frac_digits ) - word_offset;
00592         break;
00593     }
00594         case 8:
00595     {
00596         exponent *= 3;
00597         int_digits *= 3;
00598         frac_digits *= 3;
00599 
00600         int bit_offset = exponent % bits_in_word;
00601         int word_offset = exponent / bits_in_word;
00602 
00603         int_digits += bit_offset;
00604         frac_digits -= bit_offset;
00605 
00606         int words = n_word( int_digits ) + n_word( frac_digits );
00607         if( words > size() )
00608         resize_to( words );
00609         m_mant.clear();
00610 
00611         int j = n_word( frac_digits ) * bits_in_word + int_digits - 3;
00612         
00613         for( ; s < end; s ++ )
00614         {
00615         switch( *s )
00616         {
00617             case '7': case '6': case '5': case '4':
00618             case '3': case '2': case '1':
00619                 set_oct( j, *s - '0' );
00620             case '0':
00621             j -= 3;
00622             case '.':
00623             break;
00624             default:
00625             SCFX_FAIL_IF_( true );  // should not happen
00626         }
00627         }
00628 
00629         m_wp = n_word( frac_digits ) - word_offset;
00630         break;
00631     }
00632         case 10:
00633     {
00634         word carry, temp;
00635         int length = int_digits + frac_digits;
00636         resize_to( sc_max( min_mant, n_word( 4 * length ) ) );
00637 
00638         m_mant.clear();
00639         m_msw = m_lsw = 0;
00640         
00641         for( ; s < end; s ++ )
00642         {
00643         switch( *s )
00644         {
00645             case '9': case '8': case '7': case '6': case '5':
00646             case '4': case '3': case '2': case '1': case '0':
00647                 multiply_by_ten();
00648             carry = *s - '0';
00649             for ( int i = 0; carry && i < m_mant.size(); i++ )
00650             {
00651                 temp = m_mant[i];
00652                             temp += carry;              
00653                 carry = temp < m_mant[i];
00654                 m_mant[i] = temp;
00655             }
00656             case '.':
00657             break;
00658             default:
00659             SCFX_FAIL_IF_( true );  // should not happen
00660         }
00661         }
00662         
00663         m_wp = 0;
00664         find_sw();
00665 
00666         int denominator = frac_digits - exponent;
00667         
00668         if( denominator )
00669         {
00670         scfx_rep frac_num = pow10_fx( denominator );
00671         scfx_rep* temp_num =
00672             div_scfx_rep( const_cast<const scfx_rep&>( *this ),
00673                    frac_num, cte_wl );
00674         *this = *temp_num;
00675         delete temp_num;
00676         }
00677 
00678         break;
00679     }
00680         case 16:
00681     {
00682         exponent *= 4;
00683         int_digits *= 4;
00684         frac_digits *= 4;
00685 
00686         int bit_offset = exponent % bits_in_word;
00687         int word_offset = exponent / bits_in_word;
00688 
00689         int_digits += bit_offset;
00690         frac_digits -= bit_offset;
00691 
00692         int words = n_word( int_digits ) + n_word( frac_digits );
00693         if( words > size() )
00694         resize_to( words );
00695         m_mant.clear();
00696 
00697         int j = n_word( frac_digits ) * bits_in_word + int_digits - 4;
00698         
00699         for( ; s < end; s ++ )
00700         {
00701         switch( *s )
00702         {
00703             case 'f': case 'e': case 'd': case 'c': case 'b': case 'a':
00704                set_hex( j, *s - 'a' + 10 );
00705                j -= 4;
00706                break;
00707             case 'F': case 'E': case 'D': case 'C': case 'B': case 'A':
00708                set_hex( j, *s - 'A' + 10 );
00709                j -= 4;
00710                break;
00711             case '9': case '8': case '7': case '6': case '5':
00712             case '4': case '3': case '2': case '1':
00713                set_hex( j, *s - '0' );
00714             case '0':
00715                j -= 4;
00716             case '.':
00717                break;
00718            default:
00719                SCFX_FAIL_IF_( true );  // should not happen
00720         }
00721         }
00722 
00723         m_wp = n_word( frac_digits ) - word_offset;
00724         break;
00725     }
00726     }
00727 
00728     m_state = normal;
00729     find_sw();
00730 
00731     //
00732     // two's complement of mantissa if it is negative
00733     //
00734 
00735     if( mant_is_neg )
00736     {
00737     m_mant[m_msw] |=  -1 << scfx_find_msb( m_mant[m_msw] );
00738     for( int i = m_msw + 1; i < m_mant.size(); ++ i )
00739         m_mant[i] = static_cast<word>( -1 );
00740     complement( m_mant, m_mant, m_mant.size() );
00741     inc( m_mant );
00742     m_sign *= -1;
00743     find_sw();
00744     }
00745 }
00746 
00747 
00748 #undef SCFX_FAIL_IF_
00749 
00750 
00751 // ----------------------------------------------------------------------------
00752 //  METHOD : to_double
00753 //
00754 //  Convert from scfx_rep to double.
00755 // ----------------------------------------------------------------------------
00756 
00757 double
00758 scfx_rep::to_double() const 
00759 {
00760     scfx_ieee_double id;
00761 
00762     // handle special cases
00763 
00764     if( is_nan() )
00765     {
00766         id.set_nan();
00767     return id;
00768     }
00769 
00770     if( is_inf() )
00771     {
00772         id.set_inf();
00773     id.negative( m_sign < 0 );
00774     return id;
00775     }
00776 
00777     if( is_zero() )
00778     {
00779     id = 0.;
00780     id.negative( m_sign < 0 );
00781     return id;
00782     }
00783 
00784     int msb = scfx_find_msb( m_mant[m_msw] );
00785 
00786     int exp = (m_msw - m_wp) * bits_in_word + msb;
00787 
00788     if( exp > SCFX_IEEE_DOUBLE_E_MAX )
00789     {
00790     id.set_inf();
00791     id.negative( m_sign < 0 );
00792     return id;
00793     }
00794 
00795     if( exp < SCFX_IEEE_DOUBLE_E_MIN
00796     - static_cast<int>( SCFX_IEEE_DOUBLE_M_SIZE ) )
00797     {
00798     id = 0.;
00799     return id;
00800     }
00801  
00802     int shift = mantissa0_size - msb;
00803 
00804     unsigned int m0;
00805     unsigned int m1 = 0;
00806     unsigned int guard = 0;
00807 
00808     if( shift == 0 )
00809     {
00810         m0 = m_mant[m_msw] & ~( 1 << mantissa0_size );
00811     if( m_msw > m_lsw )
00812     {
00813         m1 = m_mant[m_msw - 1];
00814         if( m_msw - 1 > m_lsw )
00815             guard = m_mant[m_msw - 2] >> ( bits_in_word - 1 );
00816     }
00817     }
00818     else if( shift < 0 )
00819     {
00820     m0 = ( m_mant[m_msw] >> -shift ) & ~( 1 << mantissa0_size );
00821     m1 = m_mant[m_msw] << ( bits_in_word + shift );
00822     if( m_msw > m_lsw )
00823     {
00824         m1 |= m_mant[m_msw - 1] >> -shift;
00825         guard = ( m_mant[m_msw - 1] >> ( -shift - 1 ) ) & 1;
00826     }
00827     }
00828     else
00829     {
00830     m0 = ( m_mant[m_msw] << shift ) & ~( 1 << mantissa0_size );
00831     if( m_msw > m_lsw )
00832     {
00833         m0 |= m_mant[m_msw - 1] >> ( bits_in_word - shift );
00834         m1 = m_mant[m_msw - 1] << shift;
00835         if( m_msw - 1 > m_lsw )
00836         {
00837             m1 |= m_mant[m_msw - 2] >> ( bits_in_word - shift );
00838         guard = ( m_mant[m_msw - 2] >> (bits_in_word - shift - 1) )
00839                       & 1;
00840         }      
00841     }
00842     }
00843 
00844     if( exp < SCFX_IEEE_DOUBLE_E_MIN )
00845     {
00846     m0 |= ( 1 << mantissa0_size );
00847 
00848     int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp;
00849 
00850     if( subnormal_shift < bits_in_word )
00851     {
00852         m1 = m1 >> subnormal_shift
00853            | m0 << ( bits_in_word - subnormal_shift );
00854         m0 = m0 >> subnormal_shift;
00855     }
00856     else
00857     {
00858         m1 = m0 >> ( subnormal_shift - bits_in_word );
00859         m0 = 0;
00860     }
00861 
00862     guard = 0;
00863 
00864     exp = SCFX_IEEE_DOUBLE_E_MIN - 1;
00865     }
00866 
00867     id.mantissa0( m0 );
00868     id.mantissa1( m1 );
00869     id.exponent( exp );
00870     id.negative( m_sign < 0 );
00871 
00872     double result = id;
00873 
00874     if( guard != 0 )
00875         result += m_sign * scfx_pow2( exp - SCFX_IEEE_DOUBLE_M_SIZE );
00876 
00877     return result;
00878 }
00879 
00880 
00881 // ----------------------------------------------------------------------------
00882 //  METHOD : to_string
00883 //
00884 //  Convert from scfx_rep to character string.
00885 // ----------------------------------------------------------------------------
00886 
00887 void
00888 print_dec( scfx_string& s, const scfx_rep& num, int w_prefix, sc_fmt fmt )
00889 {
00890     if( num.is_neg() )
00891     s += '-';
00892 
00893     if( w_prefix == 1 ) {
00894     scfx_print_prefix( s, SC_DEC );
00895     }
00896 
00897     if( num.is_zero() )
00898     {
00899     s += '0';
00900     return;
00901     }
00902 
00903     // split 'num' into its integer and fractional part
00904 
00905     scfx_rep int_part  = num;
00906     scfx_rep frac_part = num;
00907 
00908     int i;
00909     
00910     for( i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i ++ )
00911     int_part.m_mant[i] = 0;
00912     int_part.find_sw();
00913     if( int_part.m_wp < int_part.m_lsw )
00914     int_part.resize_to( int_part.size() - int_part.m_wp, -1 );
00915     
00916     for( i = frac_part.m_msw;
00917      i >= frac_part.m_lsw && i >= frac_part.m_wp;
00918      i -- )
00919     frac_part.m_mant[i] = 0;
00920     frac_part.find_sw();
00921     if( frac_part.m_msw == frac_part.size() - 1 )
00922     frac_part.resize_to( frac_part.size() + 1, 1 );
00923 
00924     // print integer part
00925 
00926     int int_digits = 0;
00927     int int_zeros  = 0;
00928     
00929     if( ! int_part.is_zero() )
00930     {
00931     double int_wl = ( int_part.m_msw - int_part.m_wp ) * bits_in_word
00932                   + scfx_find_msb( int_part.m_mant[int_part.m_msw] ) + 1;
00933     int_digits = (int) ceil( int_wl * log10( 2. ) );
00934 
00935     int len = s.length();
00936     s.append( int_digits );
00937 
00938     bool zero_digits = ( frac_part.is_zero() && fmt != SC_F );
00939 
00940     for( i = int_digits + len - 1; i >= len; i-- )
00941     {
00942         unsigned int remainder = int_part.divide_by_ten();
00943         s[i] = static_cast<char>( '0' + remainder );
00944         
00945         if( zero_digits )
00946         {
00947         if( remainder == 0 )
00948             int_zeros ++;
00949         else
00950             zero_digits = false;
00951         }
00952     }
00953 
00954     // discard trailing zeros from int_part
00955     s.discard( int_zeros );
00956 
00957     if( s[len] == '0' )
00958     {
00959         // int_digits was overestimated by one
00960         s.remove( len );
00961         -- int_digits;
00962     }
00963     }
00964 
00965     // print fractional part
00966 
00967     int frac_digits = 0;
00968     int frac_zeros  = 0;
00969 
00970     if( ! frac_part.is_zero() )
00971     {
00972     s += '.';
00973 
00974     bool zero_digits = ( int_digits == 0 && fmt != SC_F );
00975 
00976     double frac_wl = ( frac_part.m_wp - frac_part.m_msw ) * bits_in_word
00977                    - scfx_find_msb( frac_part.m_mant[frac_part.m_msw] )
00978                        - 1;
00979     frac_zeros = (int) floor( frac_wl * log10( 2. ) );
00980 
00981     scfx_rep temp;
00982     sc_dt::multiply( temp, frac_part, pow10_fx( frac_zeros ) );
00983     frac_part = temp;
00984     if( frac_part.m_msw == frac_part.size() - 1 )
00985         frac_part.resize_to( frac_part.size() + 1, 1 );
00986     
00987     frac_digits = frac_zeros;
00988     if( ! zero_digits )
00989     {
00990         for( i = 0; i < frac_zeros; i ++ )
00991         s += '0';
00992         frac_zeros = 0;
00993     }
00994 
00995     while( ! frac_part.is_zero() )
00996     {
00997         frac_part.multiply_by_ten();
00998         int n = frac_part.m_mant[frac_part.m_msw + 1];
00999     
01000         if( zero_digits )
01001         {
01002         if( n == 0 )
01003             frac_zeros ++;
01004         else
01005             zero_digits = false;
01006         }
01007     
01008         if( ! zero_digits )
01009         s += static_cast<char>( '0' + n );
01010 
01011         frac_part.m_mant[frac_part.m_msw + 1] = 0;
01012         frac_digits ++;
01013     }
01014     }
01015 
01016     // print exponent
01017     
01018     if( fmt != SC_F )
01019     {
01020         if( frac_digits == 0 )
01021         scfx_print_exp( s, int_zeros );
01022     else if( int_digits == 0 )
01023         scfx_print_exp( s, - frac_zeros );
01024     }
01025 }
01026 
01027 void
01028 print_other( scfx_string& s, const scfx_rep& a, sc_numrep numrep, int w_prefix,
01029          sc_fmt fmt, const scfx_params* params )
01030 {
01031     scfx_rep b = a;
01032 
01033     sc_numrep numrep2 = numrep;
01034 
01035     bool numrep_is_sm = ( numrep == SC_BIN_SM ||
01036               numrep == SC_OCT_SM ||
01037               numrep == SC_HEX_SM );
01038 
01039     if( numrep_is_sm )
01040     {
01041     if( b.is_neg() )
01042     {
01043         s += '-';
01044         b = *neg_scfx_rep( a );
01045     }
01046     switch( numrep )
01047     {
01048         case SC_BIN_SM:
01049         numrep2 = SC_BIN_US;
01050         break;
01051         case SC_OCT_SM:
01052         numrep2 = SC_OCT_US;
01053         break;
01054         case SC_HEX_SM:
01055         numrep2 = SC_HEX_US;
01056         break;
01057         default:
01058         ;
01059     }
01060     }
01061     
01062     if( w_prefix != 0 ) {
01063     scfx_print_prefix( s, numrep );
01064     }
01065 
01066     numrep = numrep2;
01067 
01068     int msb, lsb;
01069 
01070     if( params != 0 )
01071     {
01072     msb = params->iwl() - 1;
01073     lsb = params->iwl() - params->wl();
01074 
01075     if( params->enc() == SC_TC_ &&
01076         ( numrep == SC_BIN_US ||
01077           numrep == SC_OCT_US ||
01078           numrep == SC_HEX_US ) &&
01079         ! numrep_is_sm &&
01080         params->wl() > 1 )
01081         -- msb;
01082     else if( params->enc() == SC_US_ &&
01083         ( numrep == SC_BIN ||
01084           numrep == SC_OCT ||
01085           numrep == SC_HEX ||
01086           numrep == SC_CSD ) )
01087         ++ msb;
01088     }
01089     else
01090     {
01091     if( b.is_zero() )
01092     {
01093         msb = 0;
01094         lsb = 0;
01095     }
01096     else
01097     {
01098         msb = ( b.m_msw - b.m_wp ) * bits_in_word
01099         + scfx_find_msb( b.m_mant[ b.m_msw ] ) + 1;
01100         while( b.get_bit( msb ) == b.get_bit( msb - 1 ) )
01101         -- msb;
01102 
01103         if( numrep == SC_BIN_US ||
01104         numrep == SC_OCT_US ||
01105         numrep == SC_HEX_US )
01106         -- msb;
01107 
01108         lsb = ( b.m_lsw - b.m_wp ) * bits_in_word
01109         + scfx_find_lsb( b.m_mant[ b.m_lsw ] );
01110     }
01111     }
01112 
01113     int step;
01114 
01115     switch( numrep )
01116     {
01117     case SC_BIN:
01118     case SC_BIN_US:
01119     case SC_CSD:
01120         step = 1;
01121        break;
01122     case SC_OCT:
01123     case SC_OCT_US:
01124         step = 3;
01125         break;
01126     case SC_HEX:
01127     case SC_HEX_US:
01128         step = 4;
01129         break;
01130     default:
01131         step = 0;
01132     }
01133 
01134     msb = (int) ceil( double( msb + 1 ) / step ) * step - 1;
01135 
01136     lsb = (int) floor( double( lsb ) / step ) * step;
01137 
01138     if( msb < 0 )
01139     {
01140     s += '.';
01141     if( fmt == SC_F )
01142     {
01143         int sign = ( b.is_neg() ) ? ( 1 << step ) - 1 : 0;
01144         for( int i = ( msb + 1 ) / step; i < 0; i ++ )
01145         {
01146         if( sign < 10 )
01147             s += static_cast<char>( sign + '0' );
01148         else
01149             s += static_cast<char>( sign + 'a' - 10 );
01150         }
01151     }
01152     }
01153 
01154     int i = msb;
01155     while( i >= lsb )
01156     {
01157         int value = 0;
01158         for( int j = step - 1; j >= 0; -- j )
01159     {
01160             value += static_cast<int>( b.get_bit( i ) ) << j;
01161             -- i;
01162         }
01163         if( value < 10 )
01164             s += static_cast<char>( value + '0' );
01165     else
01166             s += static_cast<char>( value + 'a' - 10 );
01167     if( i == -1 )
01168         s += '.';
01169     }
01170 
01171     if( lsb > 0 && fmt == SC_F )
01172     {
01173     for( int i = lsb / step; i > 0; i -- )
01174         s += '0';
01175     }
01176 
01177     if( s[s.length() - 1] == '.' )
01178     s.discard( 1 );
01179 
01180     if( fmt != SC_F )
01181     {
01182     if( msb < 0 )
01183         scfx_print_exp( s, ( msb + 1 ) / step );
01184     else if( lsb > 0 )
01185         scfx_print_exp( s, lsb / step );
01186     }
01187 
01188     if( numrep == SC_CSD )
01189     scfx_tc2csd( s, w_prefix );
01190 }
01191 
01192 const char*
01193 scfx_rep::to_string( sc_numrep numrep, int w_prefix,
01194              sc_fmt fmt, const scfx_params* params ) const
01195 {
01196     static scfx_string s;
01197 
01198     s.clear();
01199 
01200     if( is_nan() )
01201         scfx_print_nan( s );
01202     else if( is_inf() )
01203         scfx_print_inf( s, is_neg() );
01204     else if( is_neg() && ! is_zero() &&
01205          ( numrep == SC_BIN_US ||
01206            numrep == SC_OCT_US ||
01207            numrep == SC_HEX_US ) )
01208         s += "negative";
01209     else if( numrep == SC_DEC || numrep == SC_NOBASE )
01210         sc_dt::print_dec( s, *this, w_prefix, fmt );
01211     else
01212         sc_dt::print_other( s, *this, numrep, w_prefix, fmt, params );
01213 
01214     return s;
01215 }
01216 
01217 
01218 // ----------------------------------------------------------------------------
01219 //  ADD
01220 //
01221 //  add two mantissas of the same size
01222 //  result has the same size
01223 //  returns carry of operation
01224 // ----------------------------------------------------------------------------
01225 
01226 static inline
01227 int
01228 add_mants( int size, scfx_mant& result,
01229        const scfx_mant& a, const scfx_mant& b )
01230 {
01231     unsigned int carry = 0;
01232 
01233     int index = 0;
01234 
01235     do
01236     {
01237         word x = a[index];
01238     word y = b[index];
01239 
01240     y += carry;
01241     carry = y < carry;
01242     y += x;
01243     carry += y < x;
01244     result[index] = y;
01245     }
01246     while( ++ index < size );
01247 
01248     return ( carry ? 1 : 0 );
01249 }
01250 
01251 
01252 static inline
01253 int
01254 sub_mants( int size, scfx_mant& result,
01255        const scfx_mant& a, const scfx_mant& b )
01256 {
01257     unsigned carry = 0;
01258 
01259     int index = 0;
01260 
01261     do
01262     {
01263     word x = a[index];
01264     word y = b[index];
01265 
01266     y += carry;
01267     carry = y < carry;
01268     y = x - y;
01269     carry += y > x;
01270     result[index] = y;
01271     }
01272     while( ++ index < size );
01273 
01274     return ( carry ? 1 : 0 );
01275 }
01276 
01277 
01278 scfx_rep*
01279 add_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int max_wl )
01280 {
01281     scfx_rep& result = *new scfx_rep;
01282 
01283     //
01284     // check for special cases
01285     //
01286 
01287     if( lhs.is_nan() || rhs.is_nan()
01288     ||  ( lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign ) )
01289     {
01290     result.set_nan();
01291     return &result;
01292     }
01293 
01294     if( lhs.is_inf() )
01295     {
01296     result.set_inf( lhs.m_sign );
01297     return &result;
01298     }
01299 
01300     if( rhs.is_inf() )
01301     {
01302     result.set_inf( rhs.m_sign );
01303     return &result;
01304     }
01305 
01306     //
01307     // align operands if needed
01308     //
01309 
01310     scfx_mant_ref lhs_mant;
01311     scfx_mant_ref rhs_mant;
01312 
01313     int len_mant = lhs.size();
01314     int new_wp = lhs.m_wp;
01315 
01316     align( lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant );
01317 
01318     //
01319     // size the result mantissa
01320     //
01321 
01322     result.resize_to( len_mant );
01323     result.m_wp = new_wp;
01324 
01325     //
01326     // do it
01327     //
01328 
01329     if( lhs.m_sign == rhs.m_sign )
01330     {
01331     add_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
01332     result.m_sign = lhs.m_sign;
01333     }
01334     else
01335     {
01336     int cmp = compare_abs( lhs, rhs );
01337 
01338     if( cmp == 1 )
01339     {
01340         sub_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
01341         result.m_sign = lhs.m_sign;
01342     }
01343     else if ( cmp == -1 )
01344     {
01345         sub_mants( len_mant, result.m_mant, rhs_mant, lhs_mant );
01346         result.m_sign = rhs.m_sign;
01347     }
01348     else
01349     {
01350         result.m_mant.clear();
01351         result.m_sign = 1;
01352     }
01353     }
01354 
01355     result.find_sw();
01356     result.round( max_wl );
01357 
01358     return &result;
01359 }
01360 
01361 
01362 // ----------------------------------------------------------------------------
01363 //  SUB
01364 //
01365 //  sub two word's of the same size
01366 //  result has the same size
01367 //  returns carry of operation
01368 // ----------------------------------------------------------------------------
01369 
01370 static inline
01371 int
01372 sub_with_index(       scfx_mant& a, int a_msw, int a_lsw,
01373         const scfx_mant& b, int b_msw, int b_lsw )
01374 {
01375     unsigned carry = 0;
01376 
01377     int size    = b_msw - b_lsw;
01378     int a_index = a_msw - size;
01379     int b_index = b_msw - size;
01380 
01381     do
01382     {
01383     word x = a[a_index];
01384     word y = b[b_index];
01385 
01386     y += carry;
01387     carry = y < carry;
01388     y = x - y;
01389     carry += y > x;
01390     a[a_index] = y;
01391 
01392     a_index ++;
01393     b_index ++;
01394     }
01395     while( size -- );
01396 
01397     if( carry )
01398     {
01399         // special case: a[a_msw + 1 ] == 1
01400         a[a_msw + 1] = 0;
01401     }
01402 
01403     return ( carry ? 1 : 0 );
01404 }
01405 
01406 
01407 scfx_rep*
01408 sub_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int max_wl )
01409 {
01410     scfx_rep& result = *new scfx_rep;
01411 
01412     //
01413     // check for special cases
01414     //
01415 
01416     if( lhs.is_nan() || rhs.is_nan()
01417     ||  ( lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign ) )
01418     {
01419     result.set_nan();
01420     return &result;
01421     }
01422 
01423     if( lhs.is_inf() )
01424     {
01425     result.set_inf( lhs.m_sign );
01426     return &result;
01427     }
01428 
01429     if( rhs.is_inf() )
01430     {
01431     result.set_inf( -1 * rhs.m_sign );
01432     return &result;
01433     }
01434 
01435     //
01436     // align operands if needed
01437     //
01438 
01439     scfx_mant_ref lhs_mant;
01440     scfx_mant_ref rhs_mant;
01441 
01442     int len_mant = lhs.size();
01443     int new_wp = lhs.m_wp;
01444 
01445     align( lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant );
01446 
01447     //
01448     // size the result mantissa
01449     //
01450 
01451     result.resize_to( len_mant );
01452     result.m_wp = new_wp;
01453 
01454     //
01455     // do it
01456     //
01457 
01458     if( lhs.m_sign != rhs.m_sign )
01459     {
01460     add_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
01461     result.m_sign = lhs.m_sign;
01462     }
01463     else
01464     {
01465     int cmp = compare_abs( lhs, rhs );
01466 
01467     if( cmp == 1 )
01468     {
01469         sub_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
01470         result.m_sign = lhs.m_sign;
01471     }
01472     else if ( cmp == -1 )
01473     {
01474         sub_mants( len_mant, result.m_mant, rhs_mant, lhs_mant );
01475         result.m_sign = -rhs.m_sign;
01476     } else {
01477         result.m_mant.clear();
01478         result.m_sign = 1;
01479     }
01480     }
01481 
01482     result.find_sw();
01483     result.round( max_wl );
01484 
01485     return &result;
01486 }
01487 
01488 
01489 // ----------------------------------------------------------------------------
01490 //  MUL
01491 // ----------------------------------------------------------------------------
01492 
01493 union word_short
01494 {
01495     word l;
01496     struct
01497     {
01498 #if defined( SC_BIG_ENDIAN )
01499         half_word u;
01500         half_word l;
01501 #elif defined( SC_LITTLE_ENDIAN )
01502         half_word l;
01503         half_word u;
01504 #endif
01505     } s;
01506 };
01507 
01508 
01509 #if defined( SC_BIG_ENDIAN )
01510 static const int half_word_incr = -1;
01511 #elif defined( SC_LITTLE_ENDIAN )
01512 static const int half_word_incr = 1;
01513 #endif
01514 
01515 
01516 void
01517 multiply( scfx_rep& result, const scfx_rep& lhs, const scfx_rep& rhs,
01518       int max_wl )
01519 {
01520     //
01521     // check for special cases
01522     //
01523 
01524     if( lhs.is_nan() || rhs.is_nan()
01525     ||  lhs.is_inf() && rhs.is_zero()
01526     ||  lhs.is_zero() && rhs.is_inf() )
01527     {
01528     result.set_nan();
01529     return;
01530     }
01531 
01532     if( lhs.is_inf() || rhs.is_inf() )
01533     {
01534     result.set_inf( lhs.m_sign * rhs.m_sign );
01535     return;
01536     }
01537     
01538     if( lhs.is_zero() || rhs.is_zero() ) {
01539     result.set_zero( lhs.m_sign * rhs.m_sign );
01540     return;
01541     }
01542 
01543     //
01544     // do it
01545     //
01546 
01547     int len_lhs = lhs.m_msw - lhs.m_lsw + 1;
01548     int len_rhs = rhs.m_msw - rhs.m_lsw + 1;
01549 
01550     int new_size = sc_max( min_mant, len_lhs + len_rhs );
01551     int new_wp   = ( lhs.m_wp - lhs.m_lsw ) + ( rhs.m_wp - rhs.m_lsw );
01552     int new_sign = lhs.m_sign * rhs.m_sign;
01553 
01554     result.resize_to( new_size );
01555     result.m_mant.clear();
01556     result.m_wp    = new_wp;
01557     result.m_sign  = new_sign;
01558     result.m_state = scfx_rep::normal;
01559 
01560     half_word *s1 = lhs.m_mant.half_addr( lhs.m_lsw );
01561     half_word *s2 = rhs.m_mant.half_addr( rhs.m_lsw );
01562 
01563     half_word *t = result.m_mant.half_addr();
01564 
01565     len_lhs <<= 1;
01566     len_rhs <<= 1;
01567 
01568     int i1, i2;
01569 
01570     for( i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr )
01571     {
01572     register word_short ls;
01573     ls.l = 0;
01574 
01575     half_word v1 = s1[i1];
01576 
01577     for( i2  = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr )
01578     {
01579         ls.l  += v1 * s2[i2];
01580         ls.s.l = ls.s.u + ( ( t[i2] += ls.s.l ) < ls.s.l );
01581         ls.s.u = 0;
01582     }
01583 
01584     t[i2] = ls.s.l;
01585     t += half_word_incr;
01586     }
01587 
01588     result.find_sw();
01589     result.round( max_wl );
01590 }
01591 
01592 
01593 // ----------------------------------------------------------------------------
01594 //  DIV
01595 // ----------------------------------------------------------------------------
01596 
01597 scfx_rep*
01598 div_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int div_wl )
01599 {
01600     scfx_rep& result = *new scfx_rep;
01601 
01602     //
01603     // check for special cases
01604     //
01605 
01606     if( lhs.is_nan() || rhs.is_nan() || lhs.is_inf() && rhs.is_inf() ||
01607     lhs.is_zero() && rhs.is_zero() )
01608     {
01609     result.set_nan();
01610     return &result;
01611     }
01612 
01613     if( lhs.is_inf() || rhs.is_zero() )
01614     {
01615     result.set_inf( lhs.m_sign * rhs.m_sign );
01616     return &result;
01617     }
01618 
01619     if( lhs.is_zero() || rhs.is_inf() )
01620     {
01621     result.set_zero( lhs.m_sign * rhs.m_sign );
01622     return &result;
01623     }
01624 
01625     //
01626     // do it
01627     //
01628 
01629     // compute one bit more for rounding
01630     div_wl ++;
01631 
01632     result.resize_to( sc_max( n_word( div_wl ) + 1, min_mant ) );
01633     result.m_mant.clear();
01634     result.m_sign = lhs.m_sign * rhs.m_sign;
01635 
01636     int msb_lhs = scfx_find_msb( lhs.m_mant[lhs.m_msw] )
01637             + ( lhs.m_msw - lhs.m_wp ) * bits_in_word;
01638     int msb_rhs = scfx_find_msb( rhs.m_mant[rhs.m_msw] )
01639             + ( rhs.m_msw - rhs.m_wp ) * bits_in_word;
01640 
01641     int msb_res = msb_lhs - msb_rhs;
01642     int to_shift = -msb_res % bits_in_word;
01643     int result_index;
01644 
01645     int c = ( msb_res % bits_in_word >= 0 ) ? 1 : 0;
01646 
01647     result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word;
01648     result.m_wp   = (result.size() - c) - msb_res / bits_in_word;
01649 
01650     scfx_rep remainder = lhs;
01651 
01652     // align msb from remainder to msb from rhs
01653     remainder.lshift( to_shift );
01654 
01655     // make sure msw( remainder ) < size - 1
01656     if( remainder.m_msw == remainder.size() - 1 )
01657     remainder.resize_to( remainder.size() + 1, 1 );
01658 
01659     // make sure msw( remainder ) >= msw( rhs )!
01660     int msw_diff = rhs.m_msw - remainder.m_msw;
01661     if (msw_diff > 0)
01662     remainder.resize_to( remainder.size() + msw_diff, -1 );
01663 
01664     int counter;
01665 
01666     for( counter = div_wl; counter && ! remainder.is_zero(); counter -- )
01667     {
01668     if( compare_msw_ff( rhs, remainder ) <= 0 )
01669     {
01670         result.set_bin( result_index );
01671         sub_with_index( remainder.m_mant, remainder.m_msw, remainder.m_lsw,
01672                 rhs.m_mant, rhs.m_msw, rhs.m_lsw );
01673     }
01674     result_index --;
01675     remainder.shift_left( 1 );
01676         remainder.m_lsw = remainder.find_lsw();
01677     }
01678 
01679     // perform convergent rounding, if needed
01680     if( counter == 0 )
01681     {
01682     int index = result_index + 1 - result.m_wp * bits_in_word;
01683 
01684     scfx_index x = result.calc_indices( index );
01685     scfx_index x1 = result.calc_indices( index + 1 );
01686 
01687     if( result.o_bit_at( x ) && result.o_bit_at( x1 ) )
01688         result.q_incr( x );
01689 
01690     result.m_r_flag = true;
01691     }
01692 
01693     result.find_sw();
01694 
01695     return &result;
01696 }
01697 
01698 
01699 // ----------------------------------------------------------------------------
01700 //  destructive shift mantissa to the left
01701 // ----------------------------------------------------------------------------
01702 
01703 void
01704 scfx_rep::lshift( int n )
01705 {
01706     if( n == 0 )
01707         return;
01708 
01709     if( n < 0 )
01710     {
01711         rshift( -n );
01712     return;
01713     }
01714 
01715     if( is_normal() )
01716     {
01717         int shift_bits  = n % bits_in_word;
01718     int shift_words = n / bits_in_word;
01719 
01720     // resize if needed
01721     if( m_msw == size() - 1 &&
01722         scfx_find_msb( m_mant[m_msw] ) >= bits_in_word - shift_bits )
01723         resize_to( size() + 1, 1 );
01724 
01725     // do it
01726     m_wp -= shift_words;
01727     shift_left( shift_bits );
01728     find_sw();
01729     }
01730 }
01731 
01732 
01733 // ----------------------------------------------------------------------------
01734 //  destructive shift mantissa to the right
01735 // ----------------------------------------------------------------------------
01736 
01737 void
01738 scfx_rep::rshift( int n )
01739 {
01740     if( n == 0 )
01741         return;
01742 
01743     if( n < 0 )
01744     {
01745         lshift( -n );
01746     return;
01747     }
01748 
01749     if( is_normal() )
01750     {
01751         int shift_bits  = n % bits_in_word;
01752     int shift_words = n / bits_in_word;
01753 
01754     // resize if needed
01755     if( m_lsw == 0 && scfx_find_lsb( m_mant[m_lsw] ) < shift_bits )
01756         resize_to( size() + 1, -1 );
01757 
01758     // do it
01759     m_wp += shift_words;
01760     shift_right( shift_bits );
01761     find_sw();
01762     }
01763 }
01764 
01765 
01766 // ----------------------------------------------------------------------------
01767 //  FRIEND FUNCTION : compare_abs
01768 //
01769 //  Compares the absolute values of two scfx_reps, excluding the special cases.
01770 // ----------------------------------------------------------------------------
01771 
01772 int
01773 compare_abs( const scfx_rep& a, const scfx_rep& b )
01774 {
01775     // check for zero
01776 
01777     word a_word = a.m_mant[a.m_msw];
01778     word b_word = b.m_mant[b.m_msw];
01779   
01780     if( a_word == 0 || b_word == 0 )
01781     {
01782     if( a_word != 0 )
01783         return 1;
01784     if( b_word != 0 )
01785         return -1;
01786     return 0;
01787     }
01788 
01789     // compare msw index
01790 
01791     int a_msw = a.m_msw - a.m_wp;
01792     int b_msw = b.m_msw - b.m_wp;
01793 
01794     if( a_msw > b_msw )
01795     return 1;
01796 
01797     if( a_msw < b_msw )
01798     return -1;
01799 
01800     // compare content
01801 
01802     int a_i = a.m_msw;
01803     int b_i = b.m_msw;
01804 
01805     while( a_i >= a.m_lsw && b_i >= b.m_lsw )
01806     {
01807     a_word = a.m_mant[a_i];
01808     b_word = b.m_mant[b_i];
01809     if( a_word > b_word )
01810         return 1;
01811     if( a_word < b_word )
01812         return -1;
01813     -- a_i;
01814     -- b_i;
01815     }
01816 
01817     bool a_zero = true;
01818     while( a_i >= a.m_lsw )
01819     {
01820     a_zero = a_zero && ( a.m_mant[a_i] == 0 );
01821     -- a_i;
01822     }
01823   
01824     bool b_zero = true;
01825     while( b_i >= b.m_lsw )
01826     {
01827     b_zero = b_zero && ( b.m_mant[b_i] == 0 );
01828     -- b_i;
01829     }
01830 
01831     // assertion: a_zero || b_zero == true
01832 
01833     if( ! a_zero && b_zero )
01834     return 1;
01835 
01836     if( a_zero && ! b_zero )
01837     return -1;
01838 
01839     return 0;
01840 }
01841 
01842 
01843 // ----------------------------------------------------------------------------
01844 //  FRIEND FUNCTION : cmp_scfx_rep
01845 //
01846 //  Compares the values of two scfx_reps, including the special cases.
01847 // ----------------------------------------------------------------------------
01848 
01849 int
01850 cmp_scfx_rep( const scfx_rep& a, const scfx_rep& b )
01851 {
01852     // handle special cases
01853 
01854     if( a.is_nan() || b.is_nan() )
01855     {
01856 #if 0
01857     if( a.is_nan() && b.is_nan() )
01858     {
01859         return 0;
01860     }
01861 #endif
01862     return 2;
01863     }
01864 
01865     if( a.is_inf() || b.is_inf() )
01866     {
01867     if( a.is_inf() )
01868     {
01869         if( ! a.is_neg() )
01870         {
01871         if( b.is_inf() && ! b.is_neg() )
01872         {
01873             return 0;
01874         }
01875         else
01876         {
01877             return 1;
01878         }
01879         }
01880         else
01881         {
01882         if( b.is_inf() && b.is_neg() )
01883         {
01884             return 0;
01885         }
01886         else
01887         {
01888             return -1;
01889         }
01890         }
01891     }
01892     if( b.is_inf() )
01893     {
01894         if( ! b.is_neg() )
01895         {
01896         return -1;
01897         }
01898         else
01899         {
01900         return 1;
01901         }
01902     }
01903     }
01904   
01905     if( a.is_zero() && b.is_zero() )
01906     {
01907     return 0;
01908     }
01909 
01910     // compare sign
01911 
01912     if( a.m_sign != b.m_sign )
01913     {
01914     return a.m_sign;
01915     }
01916 
01917     return ( a.m_sign * compare_abs( a, b ) );
01918 }
01919 
01920 
01921 // ----------------------------------------------------------------------------
01922 //  PRIVATE METHOD : quantization
01923 //
01924 //  Performs destructive quantization.
01925 // ----------------------------------------------------------------------------
01926 
01927 void
01928 scfx_rep::quantization( const scfx_params& params, bool& q_flag )
01929 {
01930     scfx_index x = calc_indices( params.iwl() - params.wl() );
01931 
01932     if( x.wi() < 0 )
01933         return;
01934 
01935     if( x.wi() >= size() )
01936         resize_to( x.wi() + 1, 1 );
01937 
01938     bool qb = q_bit( x );
01939     bool qz = q_zero( x );
01940 
01941     q_flag = ( qb || ! qz );
01942 
01943     if( q_flag )
01944     {
01945         switch( params.q_mode() )
01946     {
01947             case SC_TRN:            // truncation
01948         {
01949             if( is_neg() )
01950             q_incr( x );
01951         break;
01952         }
01953             case SC_RND:            // rounding to plus infinity
01954         {
01955             if( ! is_neg() )
01956         {
01957             if( qb )
01958             q_incr( x );
01959         }
01960         else
01961         {
01962             if( qb && ! qz )
01963             q_incr( x );
01964         }
01965         break;
01966         }
01967             case SC_TRN_ZERO:           // truncation to zero
01968         {
01969             break;
01970         }
01971             case SC_RND_INF:            // rounding to infinity
01972         {
01973             if( qb )
01974             q_incr( x );
01975         break;
01976         }
01977             case SC_RND_CONV:           // convergent rounding
01978         {
01979         if( qb && ! qz || qb && qz && q_odd( x ) )
01980             q_incr( x );
01981         break;
01982         }
01983             case SC_RND_ZERO:           // rounding to zero
01984         {
01985         if( qb && ! qz )
01986             q_incr( x );
01987         break;
01988         }
01989             case SC_RND_MIN_INF:        // rounding to minus infinity
01990         {
01991         if( ! is_neg() )
01992         {
01993             if( qb && ! qz )
01994             q_incr( x );
01995         }
01996         else
01997         {
01998             if( qb )
01999             q_incr( x );
02000         }
02001         break;
02002         }
02003             default:
02004             ;
02005     }
02006     q_clear( x );
02007     
02008     find_sw();
02009     }
02010 }
02011 
02012 
02013 // ----------------------------------------------------------------------------
02014 //  PRIVATE METHOD : overflow
02015 //
02016 //  Performs destructive overflow handling.
02017 // ----------------------------------------------------------------------------
02018 
02019 void
02020 scfx_rep::overflow( const scfx_params& params, bool& o_flag )
02021 {
02022     scfx_index x = calc_indices( params.iwl() - 1 );
02023 
02024     if( x.wi() >= size() )
02025         resize_to( x.wi() + 1, 1 );
02026 
02027     if( x.wi() < 0 )
02028     {
02029         resize_to( size() - x.wi(), -1 );
02030         x.wi( 0 );
02031     }
02032 
02033     bool zero_left = o_zero_left( x );
02034     bool bit_at = o_bit_at( x );
02035     bool zero_right = o_zero_right( x );
02036 
02037     bool under = false;
02038     bool over = false;
02039 
02040     sc_enc enc = params.enc();
02041 
02042     if( enc == SC_TC_ )
02043     {
02044     if( is_neg() )
02045     {
02046         if( params.o_mode() == SC_SAT_SYM )
02047         under = ( ! zero_left || bit_at );
02048         else
02049         under = ( ! zero_left || zero_left && bit_at && ! zero_right );
02050     }
02051     else
02052         over = ( ! zero_left || bit_at );
02053     }
02054     else
02055     {
02056     if( is_neg() )
02057         under = ( ! is_zero() );
02058         else
02059         over = ( ! zero_left );
02060     }
02061 
02062     o_flag = ( under || over );
02063 
02064     if( o_flag )
02065     {
02066     scfx_index x2 = calc_indices( params.iwl() - params.wl() );
02067 
02068     if( x2.wi() < 0 )
02069     {
02070         resize_to( size() - x2.wi(), -1 );
02071         x.wi( x.wi() - x2.wi() );
02072         x2.wi( 0 );
02073     }
02074 
02075     switch( params.o_mode() )
02076     {
02077             case SC_WRAP:           // wrap-around
02078         {
02079         int n_bits = params.n_bits();
02080 
02081         if( n_bits == 0 )
02082         {
02083             // wrap-around all 'wl' bits
02084             toggle_tc();
02085             o_extend( x, enc );
02086             toggle_tc();
02087         }
02088         else if( n_bits < params.wl() )
02089         {
02090             scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits );
02091 
02092             // wrap-around least significant 'wl - n_bits' bits;
02093             // saturate most significant 'n_bits' bits
02094             toggle_tc();
02095             o_set( x, x3, enc, under );
02096             o_extend( x, enc );
02097             toggle_tc();
02098         }
02099         else
02100         {
02101             // saturate all 'wl' bits
02102             if( under )
02103             o_set_low( x, enc );
02104             else
02105             o_set_high( x, x2, enc );
02106         }
02107         break;
02108         }
02109             case SC_SAT:            // saturation
02110         {
02111         if( under )
02112             o_set_low( x, enc );
02113         else
02114             o_set_high( x, x2, enc );
02115         break;
02116         }
02117             case SC_SAT_SYM:            // symmetrical saturation
02118         {
02119         if( under )
02120         {
02121             if( enc == SC_TC_ )
02122             o_set_high( x, x2, SC_TC_, -1 );
02123             else
02124             o_set_low( x, SC_US_ );
02125         }
02126         else
02127             o_set_high( x, x2, enc );
02128         break;
02129         }
02130             case SC_SAT_ZERO:           // saturation to zero
02131         {
02132         set_zero();
02133         break;
02134         }
02135             case SC_WRAP_SM:            // sign magnitude wrap-around
02136         {
02137         SC_ERROR_IF_( enc == SC_US_,
02138                   sc_core::SC_ID_WRAP_SM_NOT_DEFINED_ );
02139 
02140         int n_bits = params.n_bits();
02141 
02142         if( n_bits == 0 )
02143         {
02144             scfx_index x4 = calc_indices( params.iwl() );
02145 
02146             if( x4.wi() >= size() )
02147             resize_to( x4.wi() + 1, 1 );
02148 
02149             toggle_tc();
02150             if( o_bit_at( x4 ) != o_bit_at( x ) )
02151             o_invert( x2 );
02152             o_extend( x, SC_TC_ );
02153             toggle_tc();
02154         }
02155         else if( n_bits == 1 )
02156         {
02157             toggle_tc();
02158             if( is_neg() != o_bit_at( x ) )
02159             o_invert( x2 );
02160             o_extend( x, SC_TC_ );
02161             toggle_tc();
02162         }
02163         else if( n_bits < params.wl() )
02164         {
02165             scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits );
02166             scfx_index x4 = calc_indices( params.iwl() - n_bits );
02167 
02168             // wrap-around least significant 'wl - n_bits' bits;
02169             // saturate most significant 'n_bits' bits
02170             toggle_tc();
02171             if( is_neg() == o_bit_at( x4 ) )
02172             o_invert( x2 );
02173             o_set( x, x3, SC_TC_, under );
02174             o_extend( x, SC_TC_ );
02175             toggle_tc();
02176         }
02177         else
02178         {
02179             if( under )
02180             o_set_low( x, SC_TC_ );
02181             else
02182             o_set_high( x, x2, SC_TC_ );
02183         }
02184         break;
02185         }
02186             default:
02187             ;
02188     }
02189 
02190     find_sw();
02191     }
02192 }
02193 
02194 
02195 // ----------------------------------------------------------------------------
02196 //  PUBLIC METHOD : cast
02197 //
02198 //  Performs a destructive cast operation on a scfx_rep.
02199 // ----------------------------------------------------------------------------
02200 
02201 void
02202 scfx_rep::cast( const scfx_params& params, bool& q_flag, bool& o_flag )
02203 {
02204     q_flag = false;
02205     o_flag = false;
02206 
02207     // check for special cases
02208     
02209     if( is_zero() )
02210     {
02211     if( is_neg() )
02212         m_sign = 1;
02213     return;
02214     }
02215 
02216     // perform casting
02217 
02218     quantization( params, q_flag );
02219     overflow( params, o_flag );
02220 
02221     // check for special case: -0
02222 
02223     if( is_zero() && is_neg() )
02224     m_sign = 1;
02225 }
02226 
02227 
02228 // ----------------------------------------------------------------------------
02229 //  make sure, the two mantissas are aligned
02230 // ----------------------------------------------------------------------------
02231 
02232 void
02233 align( const scfx_rep& lhs, const scfx_rep& rhs, int& new_wp,
02234        int& len_mant, scfx_mant_ref& lhs_mant, scfx_mant_ref& rhs_mant )
02235 {
02236     bool need_lhs = true;
02237     bool need_rhs = true;
02238 
02239     if( lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size() )
02240     {
02241     int lower_bound_lhs = lhs.m_lsw - lhs.m_wp;
02242     int upper_bound_lhs = lhs.m_msw - lhs.m_wp;
02243     int lower_bound_rhs = rhs.m_lsw - rhs.m_wp;
02244     int upper_bound_rhs = rhs.m_msw - rhs.m_wp;
02245 
02246     int lower_bound = sc_min( lower_bound_lhs, lower_bound_rhs );
02247     int upper_bound = sc_max( upper_bound_lhs, upper_bound_rhs );
02248 
02249     new_wp   = -lower_bound;
02250     len_mant = sc_max( min_mant, upper_bound - lower_bound + 1 );
02251 
02252     if( new_wp != lhs.m_wp || len_mant != lhs.size() )
02253     {
02254         lhs_mant = lhs.resize( len_mant, new_wp );
02255         need_lhs = false;
02256     }
02257 
02258     if( new_wp != rhs.m_wp || len_mant != rhs.size() )
02259         {
02260         rhs_mant = rhs.resize( len_mant, new_wp );
02261         need_rhs = false;
02262     }
02263     }
02264 
02265     if( need_lhs )
02266     {
02267     lhs_mant = lhs.m_mant;
02268     }
02269 
02270     if( need_rhs )
02271     {
02272     rhs_mant = rhs.m_mant;
02273     }
02274 }
02275 
02276 
02277 // ----------------------------------------------------------------------------
02278 //  compare two mantissas
02279 // ----------------------------------------------------------------------------
02280 
02281 int
02282 compare_msw_ff( const scfx_rep& lhs, const scfx_rep& rhs )
02283 {
02284     // special case: rhs.m_mant[rhs.m_msw + 1] == 1
02285     if( rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0 )
02286     {
02287     return -1;
02288     }
02289 
02290     int lhs_size = lhs.m_msw - lhs.m_lsw + 1;
02291     int rhs_size = rhs.m_msw - rhs.m_lsw + 1;
02292 
02293     int size = sc_min( lhs_size, rhs_size );
02294 
02295     int lhs_index = lhs.m_msw;
02296     int rhs_index = rhs.m_msw;
02297 
02298     int i;
02299 
02300     for( i = 0;
02301      i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index];
02302      i ++ )
02303     {
02304     lhs_index --;
02305     rhs_index --;
02306     }
02307 
02308     if( i == size )
02309     {
02310     if( lhs_size == rhs_size )
02311     {
02312         return 0;
02313     }
02314 
02315     if( lhs_size < rhs_size )
02316     {
02317         return -1;
02318     }
02319     else
02320     {
02321         return 1;
02322     }
02323   }
02324 
02325   if( lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index] )
02326   {
02327       return -1;
02328   } else {
02329       return 1;
02330   }
02331 }
02332 
02333 
02334 // ----------------------------------------------------------------------------
02335 //  divide the mantissa by ten
02336 // ----------------------------------------------------------------------------
02337 
02338 unsigned int
02339 scfx_rep::divide_by_ten()
02340 {
02341 #if defined( SC_BIG_ENDIAN )
02342     half_word* hw = (half_word*) &m_mant[m_msw];
02343 #elif defined( SC_LITTLE_ENDIAN )
02344     half_word* hw = ( (half_word*) &m_mant[m_msw] ) + 1;
02345 #endif
02346 
02347     unsigned int remainder = 0;
02348 
02349     word_short ls;
02350     ls.l = 0;
02351 
02352 #if defined( SC_BIG_ENDIAN )
02353     for( int i = 0, end = ( m_msw - m_wp + 1 ) * 2; i < end; i ++ )
02354 #elif defined( SC_LITTLE_ENDIAN )
02355     for( int i = 0, end = -( m_msw - m_wp + 1 ) * 2; i > end; i -- )
02356 #endif
02357     {
02358     ls.s.u = static_cast<half_word>( remainder );
02359     ls.s.l = hw[i];
02360     remainder = ls.l % 10;
02361     ls.l /= 10;
02362     hw[i] = ls.s.l;
02363     }
02364 
02365     return remainder;
02366 }
02367 
02368 
02369 // ----------------------------------------------------------------------------
02370 //  multiply the mantissa by ten
02371 // ----------------------------------------------------------------------------
02372 
02373 void
02374 scfx_rep::multiply_by_ten()
02375 {
02376     int size = m_mant.size() + 1;
02377 
02378     scfx_mant mant8( size );
02379     scfx_mant mant2( size );
02380 
02381     size --;
02382 
02383     mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3));
02384     mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1));
02385 
02386     while( -- size )
02387     {
02388     mant8[size] = ( m_mant[size] << 3 ) |
02389                   ( m_mant[size - 1] >> ( bits_in_word - 3 ) );
02390     mant2[size] = ( m_mant[size] << 1 ) |
02391                   ( m_mant[size - 1] >> ( bits_in_word - 1 ) );
02392     }
02393 
02394     mant8[0] = ( m_mant[0] << 3 );
02395     mant2[0] = ( m_mant[0] << 1 );
02396 
02397     add_mants( m_mant.size(), m_mant, mant8, mant2 );
02398 
02399 #if 0
02400     for( int i = size() - 1; i > 0; i -- )
02401     {
02402     m_mant[i] = ( m_mant[i] << 3 ) |
02403                     ( m_mant[i-1] >> ( bits_in_word - 3 ) )
02404               + ( m_mant[i] << 1 ) |
02405                     ( m_mant[i-1] >> ( bits_in_word - 1 ) );
02406     }
02407     m_mant[0] = ( m_mant[0] << 3 ) + ( m_mant[0] << 1 );
02408 #endif
02409 }
02410 
02411 
02412 // ----------------------------------------------------------------------------
02413 //  normalize
02414 // ----------------------------------------------------------------------------
02415 
02416 void
02417 scfx_rep::normalize( int exponent )
02418 {
02419     int shift = exponent % bits_in_word;
02420     if( shift < 0 )
02421     {
02422     shift += bits_in_word;
02423     }
02424 
02425     if( shift )
02426     {
02427     shift_left( shift );
02428     }
02429 
02430     find_sw();
02431 
02432     m_wp = (shift - exponent) / bits_in_word;
02433 }
02434 
02435 
02436 // ----------------------------------------------------------------------------
02437 //  return a new mantissa that is aligned and resized
02438 // ----------------------------------------------------------------------------
02439 
02440 scfx_mant*
02441 scfx_rep::resize( int new_size, int new_wp ) const
02442 {
02443     scfx_mant *result = new scfx_mant( new_size );
02444 
02445     result->clear();
02446 
02447     int shift = new_wp - m_wp;
02448 
02449     for( int j = m_lsw; j <= m_msw; j ++ )
02450     {
02451     (*result)[j+shift] = m_mant[j];
02452     }
02453 
02454     return result;
02455 }
02456 
02457 
02458 // ----------------------------------------------------------------------------
02459 //  set a single bit
02460 // ----------------------------------------------------------------------------
02461 
02462 void
02463 scfx_rep::set_bin( int i )
02464 {
02465     m_mant[i >> 5] |= 1 << ( i & 31 );
02466 }
02467 
02468 
02469 // ----------------------------------------------------------------------------
02470 //  set three bits
02471 // ----------------------------------------------------------------------------
02472 
02473 void
02474 scfx_rep::set_oct( int i, int n )
02475 {
02476     if( n & 1 )
02477     {
02478     m_mant[i >> 5] |= 1 << ( i & 31 );
02479     }
02480     i ++;
02481     if( n & 2 )
02482     {
02483     m_mant[i >> 5] |= 1 << ( i & 31 );
02484     }
02485     i ++;
02486     if( n & 4 )
02487     {
02488     m_mant[i >> 5] |= 1 << ( i & 31 );
02489     }
02490 }
02491 
02492 
02493 // ----------------------------------------------------------------------------
02494 //  set four bits
02495 // ----------------------------------------------------------------------------
02496 
02497 void
02498 scfx_rep::set_hex( int i, int n )
02499 {
02500     if( n & 1 )
02501     {
02502     m_mant[i >> 5] |= 1 << ( i & 31 );
02503     }
02504     i ++;
02505     if( n & 2 )
02506     {
02507     m_mant[i >> 5] |= 1 << ( i & 31 );
02508     }
02509     i ++;
02510     if( n & 4 )
02511     {
02512     m_mant[i >> 5] |= 1 << ( i & 31 );
02513     }
02514     i ++;
02515     if( n & 8 )
02516     {
02517     m_mant[i >> 5] |= 1 << ( i & 31 );
02518     }
02519 }
02520 
02521 
02522 // ----------------------------------------------------------------------------
02523 //  PRIVATE METHOD : shift_left
02524 //
02525 //  Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits.
02526 // ----------------------------------------------------------------------------
02527 
02528 void
02529 scfx_rep::shift_left( int n )
02530 {
02531     if( n != 0 )
02532     {
02533     int shift_left  = n;
02534     int shift_right = bits_in_word - n;
02535 
02536     SC_ASSERT_( !(m_mant[size()-1] >> shift_right),
02537             "shift_left overflow" );
02538 
02539     for( int i = size() - 1; i > 0; i -- )
02540     {
02541         m_mant[i] = ( m_mant[i] << shift_left ) |
02542                ( m_mant[i-1] >> shift_right );
02543     }
02544     m_mant[0] <<= shift_left;
02545     }
02546 }
02547 
02548 
02549 // ----------------------------------------------------------------------------
02550 //  PRIVATE METHOD : shift_right
02551 //
02552 //  Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits.
02553 // ----------------------------------------------------------------------------
02554 
02555 void
02556 scfx_rep::shift_right( int n )
02557 {
02558     if( n != 0 )
02559     {
02560     int shift_left  = bits_in_word - n;
02561     int shift_right = n;
02562 
02563     SC_ASSERT_( !(m_mant[0] << shift_left), "shift_right overflow" );
02564 
02565     for( int i = 0; i < size() - 1; i ++ )
02566     {
02567         m_mant[i] = ( m_mant[i] >> shift_right ) |
02568                ( m_mant[i+1] << shift_left );
02569     }
02570     m_mant[size()-1] >>= shift_right;
02571     }
02572 }
02573 
02574 
02575 // ----------------------------------------------------------------------------
02576 //  METHOD : get_bit
02577 //
02578 //  Tests a bit, in two's complement.
02579 // ----------------------------------------------------------------------------
02580 
02581 bool
02582 scfx_rep::get_bit( int i ) const
02583 {
02584     if( ! is_normal() )
02585     return false;
02586 
02587     scfx_index x = calc_indices( i );
02588 
02589     if( x.wi() >= size() )
02590     return is_neg();
02591 
02592     if( x.wi() < 0 )
02593     return false;
02594 
02595     const_cast<scfx_rep*>( this )->toggle_tc();
02596 
02597     bool result = ( m_mant[x.wi()] & ( 1 << x.bi() ) ) != 0;
02598 
02599     const_cast<scfx_rep*>( this )->toggle_tc();
02600 
02601     return result;
02602 }
02603 
02604 
02605 // ----------------------------------------------------------------------------
02606 //  METHOD : set
02607 //
02608 //  Sets a bit, in two's complement, between iwl-1 and -fwl.
02609 // ----------------------------------------------------------------------------
02610 
02611 bool
02612 scfx_rep::set( int i, const scfx_params& params )
02613 {
02614     if( ! is_normal() )
02615     return false;
02616 
02617     scfx_index x = calc_indices( i );
02618 
02619     if( x.wi() >= size() )
02620     {
02621     if( is_neg() )
02622         return true;
02623     else
02624         resize_to( x.wi() + 1, 1 );
02625     }
02626     else if( x.wi() < 0 )
02627     {
02628     resize_to( size() - x.wi(), -1 );
02629     x.wi( 0 );
02630     }
02631 
02632     toggle_tc();
02633 
02634     m_mant[x.wi()] |= 1 << x.bi();
02635 
02636     if( i == params.iwl() - 1 )
02637         o_extend( x, params.enc() );  // sign extension
02638 
02639     toggle_tc();
02640 
02641     find_sw();
02642 
02643     return true;
02644 }
02645 
02646 
02647 // ----------------------------------------------------------------------------
02648 //  METHOD : clear
02649 //
02650 //  Clears a bit, in two's complement, between iwl-1 and -fwl.
02651 // ----------------------------------------------------------------------------
02652 
02653 bool
02654 scfx_rep::clear( int i, const scfx_params& params )
02655 {
02656     if( ! is_normal() )
02657     return false;
02658 
02659     scfx_index x = calc_indices( i );
02660 
02661     if( x.wi() >= size() )
02662     {
02663     if( ! is_neg() )
02664         return true;
02665     else
02666         resize_to( x.wi() + 1, 1 );
02667     }
02668     else if( x.wi() < 0 )
02669     return true;
02670 
02671     toggle_tc();
02672 
02673     m_mant[x.wi()] &= ~( 1 << x.bi() );
02674 
02675     if( i == params.iwl() - 1 )
02676         o_extend( x, params.enc() );  // sign extension
02677 
02678     toggle_tc();
02679 
02680     find_sw();
02681 
02682     return true;
02683 }
02684 
02685 
02686 // ----------------------------------------------------------------------------
02687 //  METHOD : get_slice
02688 // ----------------------------------------------------------------------------
02689 
02690 bool
02691 scfx_rep::get_slice( int i, int j, const scfx_params&,
02692              sc_bv_base& bv ) const
02693 {
02694     if( is_nan() || is_inf() )
02695     return false;
02696 
02697     // get the bits
02698 
02699     int l = j;
02700     for( int k = 0; k < bv.length(); ++ k )
02701     {
02702     bv[k] = get_bit( l );
02703 
02704     if( i >= j )
02705         ++ l;
02706     else
02707         -- l;
02708     }
02709 
02710     return true;
02711 }
02712 
02713 bool
02714 scfx_rep::set_slice( int i, int j, const scfx_params& params,
02715              const sc_bv_base& bv )
02716 {
02717     if( is_nan() || is_inf() )
02718         return false;
02719 
02720     // set the bits
02721 
02722     int l = j;
02723     for( int k = 0; k < bv.length(); ++ k )
02724     {
02725     if( bv[k].to_bool() )
02726         set( l, params );
02727     else
02728         clear( l, params );
02729 
02730     if( i >= j )
02731         ++ l;
02732     else
02733         -- l;
02734     }
02735 
02736     return true;
02737 }
02738 
02739 
02740 // ----------------------------------------------------------------------------
02741 //  METHOD : print
02742 // ----------------------------------------------------------------------------
02743 
02744 void
02745 scfx_rep::print( ::std::ostream& os ) const
02746 {
02747     os << to_string( SC_DEC, -1, SC_E );
02748 }
02749 
02750 
02751 // ----------------------------------------------------------------------------
02752 //  METHOD : dump
02753 // ----------------------------------------------------------------------------
02754 
02755 void
02756 scfx_rep::dump( ::std::ostream& os ) const
02757 {
02758     os << "scfx_rep" << ::std::endl;
02759     os << "(" << ::std::endl;
02760 
02761     os << "mant  =" << ::std::endl;
02762     for( int i = size() - 1; i >= 0; i -- )
02763     {
02764     char buf[BUFSIZ];
02765     std::sprintf( buf, " %d: %10u (%8x)", i, (int) m_mant[i], (int) m_mant[i] );
02766     os << buf << ::std::endl;
02767     }
02768 
02769     os << "wp    = " << m_wp << ::std::endl;
02770     os << "sign  = " << m_sign << ::std::endl;
02771 
02772     os << "state = ";
02773     switch( m_state )
02774     {
02775         case normal:
02776         os << "normal";
02777         break;
02778         case infinity:
02779         os << "infinity";
02780         break;
02781         case not_a_number:
02782         os << "not_a_number";
02783         break;
02784         default:
02785         os << "unknown";
02786     }
02787     os << ::std::endl;
02788 
02789     os << "msw   = " << m_msw << ::std::endl;
02790     os << "lsw   = " << m_lsw << ::std::endl;
02791 
02792     os << ")" << ::std::endl;
02793 }
02794 
02795 
02796 // ----------------------------------------------------------------------------
02797 //  METHOD : get_type
02798 // ----------------------------------------------------------------------------
02799 
02800 void
02801 scfx_rep::get_type( int& wl, int& iwl, sc_enc& enc ) const
02802 {
02803     if( is_nan() || is_inf() )
02804     {
02805         wl  = 0;
02806         iwl = 0;
02807         enc = SC_TC_;
02808         return;
02809     }
02810 
02811     if( is_zero() )
02812     {
02813         wl  = 1;
02814         iwl = 1;
02815         enc = SC_US_;
02816         return;
02817     }
02818 
02819     int msb = ( m_msw - m_wp ) * bits_in_word
02820             + scfx_find_msb( m_mant[ m_msw ] ) + 1;
02821     while( get_bit( msb ) == get_bit( msb - 1 ) )
02822     {
02823         -- msb;
02824     }
02825 
02826     int lsb = ( m_lsw - m_wp ) * bits_in_word
02827             + scfx_find_lsb( m_mant[ m_lsw ] );
02828 
02829     if( is_neg() )
02830     {
02831         wl  = msb - lsb + 1;
02832         iwl = msb + 1;
02833         enc = SC_TC_;
02834     }
02835     else
02836     {
02837         wl  = msb - lsb;
02838         iwl = msb;
02839         enc = SC_US_;
02840     }
02841 }
02842 
02843 
02844 // ----------------------------------------------------------------------------
02845 //  PRIVATE METHOD : round
02846 //
02847 //  Performs convergent rounding (rounding to even) as in floating-point.
02848 // ----------------------------------------------------------------------------
02849 
02850 void
02851 scfx_rep::round( int wl )
02852 {
02853     // check for special cases
02854     
02855     if( is_nan() || is_inf() || is_zero() )
02856     return;
02857 
02858     // estimate effective wordlength and compare
02859 
02860     int wl_effective;
02861 
02862     wl_effective = ( m_msw - m_lsw + 1 ) * bits_in_word;
02863     if( wl_effective <= wl )
02864     return;
02865 
02866     // calculate effective wordlength and compare
02867 
02868     int msb = scfx_find_msb( m_mant[m_msw] );
02869     int lsb = scfx_find_lsb( m_mant[m_lsw] );
02870 
02871     wl_effective = ( m_msw * bits_in_word + msb ) -
02872                ( m_lsw * bits_in_word + lsb ) + 1;
02873     if( wl_effective <= wl )
02874     return;
02875 
02876     // perform rounding
02877 
02878     int wi = m_msw - ( wl - 1 ) / bits_in_word;
02879     int bi =  msb - ( wl - 1 ) % bits_in_word;
02880     if( bi < 0 )
02881     {
02882     -- wi;
02883     bi += bits_in_word;
02884     }
02885 
02886     scfx_index x( wi, bi );
02887 
02888     if( q_bit( x ) && ! q_zero( x ) ||
02889     q_bit( x ) && q_zero( x ) && q_odd( x ) )
02890     q_incr( x );
02891     q_clear( x );
02892 
02893     find_sw();
02894 
02895     m_r_flag = true;
02896 }
02897 
02898 } // namespace sc_dt
02899 
02900 
02901 // Taf!

Generated on Wed Jan 21 15:32:08 2009 for SystemC by  doxygen 1.5.5