scfx_rep.cpp revision 12027
14486Sbinkertn@umich.edu/*****************************************************************************
24486Sbinkertn@umich.edu
34486Sbinkertn@umich.edu  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
44486Sbinkertn@umich.edu  more contributor license agreements.  See the NOTICE file distributed
54486Sbinkertn@umich.edu  with this work for additional information regarding copyright ownership.
64486Sbinkertn@umich.edu  Accellera licenses this file to you under the Apache License, Version 2.0
74486Sbinkertn@umich.edu  (the "License"); you may not use this file except in compliance with the
84486Sbinkertn@umich.edu  License.  You may obtain a copy of the License at
94486Sbinkertn@umich.edu
104486Sbinkertn@umich.edu    http://www.apache.org/licenses/LICENSE-2.0
114486Sbinkertn@umich.edu
124486Sbinkertn@umich.edu  Unless required by applicable law or agreed to in writing, software
134486Sbinkertn@umich.edu  distributed under the License is distributed on an "AS IS" BASIS,
144486Sbinkertn@umich.edu  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
154486Sbinkertn@umich.edu  implied.  See the License for the specific language governing
164486Sbinkertn@umich.edu  permissions and limitations under the License.
174486Sbinkertn@umich.edu
184486Sbinkertn@umich.edu *****************************************************************************/
194486Sbinkertn@umich.edu
204486Sbinkertn@umich.edu/*****************************************************************************
214486Sbinkertn@umich.edu
224486Sbinkertn@umich.edu  scfx_rep.cpp -
234486Sbinkertn@umich.edu
244486Sbinkertn@umich.edu  Original Author: Robert Graulich, Synopsys, Inc.
254486Sbinkertn@umich.edu                   Martin Janssen,  Synopsys, Inc.
264486Sbinkertn@umich.edu
274486Sbinkertn@umich.edu *****************************************************************************/
284486Sbinkertn@umich.edu
293630SN/A/*****************************************************************************
303630SN/A
314104SN/A  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
325478Snate@binkert.org  changes you are making here.
335478Snate@binkert.org
343743SN/A      Name, Affiliation, Date:
353630SN/A  Description of Modification:
363898SN/A
373898SN/A *****************************************************************************/
383898SN/A
393898SN/A
403898SN/A// $Log: scfx_rep.cpp,v $
413898SN/A// Revision 1.4  2011/08/24 22:05:43  acg
423914SN/A//  Torsten Maehne: initialization changes to remove warnings.
433914SN/A//
443914SN/A// Revision 1.3  2011/08/15 16:43:24  acg
453914SN/A//  Torsten Maehne: changes to remove unused argument warnings.
463914SN/A//
474104SN/A// Revision 1.2  2009/02/28 00:26:20  acg
484104SN/A//  Andy Goodrich: bug fixes.
498742Sgblack@eecs.umich.edu//
504104SN/A// Revision 1.2  2008/11/06 17:22:47  acg
514104SN/A//  Andy Goodrich: bug fixes for 2.2.1.
523914SN/A//
533630SN/A// Revision 1.1.1.1  2006/12/15 20:31:36  acg
543630SN/A// SystemC 2.2
553630SN/A//
563630SN/A// Revision 1.3  2006/01/13 18:53:58  acg
574007SN/A// Andy Goodrich: added $Log command so that CVS comments are reproduced in
584007SN/A// the source.
593630SN/A//
603814SN/A
614007SN/A#include "sysc/utils/sc_machine.h"
624007SN/A#include "sysc/datatypes/fx/scfx_rep.h"
633814SN/A
644007SN/A#include "sysc/datatypes/fx/scfx_ieee.h"
654007SN/A#include "sysc/datatypes/fx/scfx_pow10.h"
663814SN/A#include "sysc/datatypes/fx/scfx_utils.h"
673814SN/A
684007SN/A#include "sysc/datatypes/bit/sc_bv_base.h"
694007SN/A
703814SN/A#include <ctype.h>
713814SN/A#include <cstdio>
724007SN/A#include <stdlib.h>
734007SN/A#include <math.h>
743814SN/A
753814SN/A
764007SN/Anamespace sc_dt
774007SN/A{
783814SN/A
793814SN/A// ----------------------------------------------------------------------------
804007SN/A//  some utilities
814007SN/A// ----------------------------------------------------------------------------
823814SN/A
833825SN/Astatic scfx_pow10 pow10_fx;
844007SN/A
854007SN/Astatic const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int;
863825SN/A
873825SN/Astatic inline
884007SN/Aint
894007SN/An_word( int x )
903825SN/A{
913825SN/A    return ( x + bits_in_word - 1 ) / bits_in_word;
924007SN/A}
934007SN/A
943825SN/A
953825SN/A// ----------------------------------------------------------------------------
964007SN/A//  CONSTRUCTORS
974007SN/A// ----------------------------------------------------------------------------
983825SN/A
994007SN/Ascfx_rep::scfx_rep()
1004007SN/A: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
1013814SN/A  m_r_flag( false )
1025478Snate@binkert.org{
1033814SN/A    set_zero();
1043914SN/A}
1053914SN/A
1065478Snate@binkert.orgscfx_rep::scfx_rep( int a )
1073814SN/A: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
1083630SN/A  m_r_flag( false )
1094104SN/A{
1104104SN/A    if( a != 0 )
1114104SN/A    {
1128847Sandreas.hansson@arm.com        m_mant.clear();
1138847Sandreas.hansson@arm.com	m_wp = m_msw = m_lsw = 2;
1144104SN/A	m_state = normal;
1154104SN/A	if( a > 0 )
1163630SN/A	{
1173630SN/A	    m_mant[2] = a;
1183630SN/A	    m_sign = 1;
1193630SN/A	}
1205478Snate@binkert.org	else
1215478Snate@binkert.org	{
1228847Sandreas.hansson@arm.com	    m_mant[2] = -a;
1238847Sandreas.hansson@arm.com	    m_sign = -1;
1248847Sandreas.hansson@arm.com	}
1258847Sandreas.hansson@arm.com    }
1268847Sandreas.hansson@arm.com    else
1278847Sandreas.hansson@arm.com        set_zero();
1288847Sandreas.hansson@arm.com}
1298847Sandreas.hansson@arm.com
1308847Sandreas.hansson@arm.comscfx_rep::scfx_rep( unsigned int a )
1318847Sandreas.hansson@arm.com: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
1328847Sandreas.hansson@arm.com  m_r_flag( false )
1338847Sandreas.hansson@arm.com{
1348847Sandreas.hansson@arm.com    if( a != 0 )
1358847Sandreas.hansson@arm.com    {
136        m_mant.clear();
137	m_wp = m_msw = m_lsw = 2;
138	m_state = normal;
139	m_mant[2] = a;
140	m_sign = 1;
141    }
142    else
143        set_zero();
144}
145
146scfx_rep::scfx_rep( long a )
147: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
148  m_r_flag( false )
149{
150    if( a != 0 )
151    {
152        m_mant.clear();
153	m_state = normal;
154        if ( a > 0 )
155        {
156	    m_sign = 1;
157        }
158        else
159        {
160            a = -a;
161            m_sign = -1;
162        }
163#       if defined(SC_LONG_64)
164            m_wp = 1;
165            m_mant[1] = static_cast<word>( a );
166            m_mant[2] = static_cast<word>( a >> bits_in_word );
167	    find_sw();
168#       else
169            m_wp = 2;
170            m_msw = 2;
171            m_lsw = 2;
172            m_mant[2] = a;
173#       endif
174
175    }
176    else
177        set_zero();
178}
179
180scfx_rep::scfx_rep( unsigned long a )
181: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
182  m_r_flag( false )
183{
184    if( a != 0 )
185    {
186        m_mant.clear();
187	m_wp = m_msw = m_lsw = 2;
188	m_state = normal;
189#       if defined(SC_LONG_64)
190	    m_wp = 1;
191	    m_mant[1] = static_cast<word>( a );
192	    m_mant[2] = static_cast<word>( a >> bits_in_word );
193	    find_sw();
194#       else
195	    m_wp = 2;
196	    m_msw = 2;
197	    m_lsw = 2;
198	    m_mant[2] = a;
199#	endif
200	m_sign = 1;
201    }
202    else
203        set_zero();
204}
205
206scfx_rep::scfx_rep( double a )
207: m_mant( min_mant ), m_wp( 0 ), m_sign(), m_state( normal ), m_msw( 0 ),
208  m_lsw( 0 ), m_r_flag( false )
209{
210    m_mant.clear();
211
212    scfx_ieee_double id( a );
213
214    m_sign = id.negative() ? -1 : 1;
215
216    if( id.is_nan() )
217        m_state = not_a_number;
218    else if( id.is_inf() )
219        m_state = infinity;
220    else if( id.is_subnormal() )
221    {
222	m_mant[0] = id.mantissa1();
223	m_mant[1] = id.mantissa0();
224	normalize( id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE );
225    }
226    else if( id.is_normal() )
227    {
228	m_mant[0] = id.mantissa1();
229	m_mant[1] = id.mantissa0() | ( 1 << mantissa0_size );
230	normalize( id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE );
231    }
232}
233
234scfx_rep::scfx_rep( int64 a )
235: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
236  m_r_flag( false )
237{
238    if( a != 0 )
239    {
240        m_mant.clear();
241	m_wp = 1;
242	m_state = normal;
243	if( a > 0 )
244	{
245	    m_mant[1] = static_cast<word>( a );
246	    m_mant[2] = static_cast<word>( a >> bits_in_word );
247	    m_sign = 1;
248	}
249	else
250	{
251	    m_mant[1] = static_cast<word>( -a );
252	    m_mant[2] = static_cast<word>( (-a) >> bits_in_word );
253	    m_sign = -1;
254	}
255	find_sw();
256    }
257    else
258        set_zero();
259}
260
261scfx_rep::scfx_rep( uint64 a )
262: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
263  m_r_flag( false )
264{
265    if( a != 0 )
266    {
267        m_mant.clear();
268	m_wp = 1;
269	m_state = normal;
270	m_mant[1] = static_cast<word>( a );
271	m_mant[2] = static_cast<word>( a >> bits_in_word );
272	m_sign = 1;
273	find_sw();
274    }
275    else
276        set_zero();
277}
278
279scfx_rep::scfx_rep( const sc_signed& a )
280: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
281  m_r_flag( false )
282{
283    if( a.iszero() )
284	set_zero();
285    else
286    {
287	int words = n_word( a.length() );
288	if( words > size() )
289	    resize_to( words );
290	m_mant.clear();
291	m_wp = 0;
292	m_state = normal;
293	if( a.sign() )
294	{
295	    sc_signed a2 = -a;
296	    for( int i = 0; i < a2.length(); ++ i )
297	    {
298		if( a2[i] )
299		{
300		    scfx_index x = calc_indices( i );
301		    m_mant[x.wi()] |= 1 << x.bi();
302		}
303	    }
304	    m_sign = -1;
305	}
306	else
307	{
308	    for( int i = 0; i < a.length(); ++ i )
309	    {
310		if( a[i] )
311		{
312		    scfx_index x = calc_indices( i );
313		    m_mant[x.wi()] |= 1 << x.bi();
314		}
315	    }
316	    m_sign = 1;
317	}
318	find_sw();
319    }
320}
321
322scfx_rep::scfx_rep( const sc_unsigned& a )
323: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
324  m_r_flag( false )
325{
326    if( a.iszero() )
327	set_zero();
328    else
329    {
330	int words = n_word( a.length() );
331	if( words > size() )
332	    resize_to( words );
333	m_mant.clear();
334	m_wp = 0;
335	m_state = normal;
336	for( int i = 0; i < a.length(); ++ i )
337	{
338	    if( a[i] )
339	    {
340		scfx_index x = calc_indices( i );
341		m_mant[x.wi()] |= 1 << x.bi();
342	    }
343	}
344	m_sign = 1;
345	find_sw();
346    }
347}
348
349
350// copy constructor
351
352scfx_rep::scfx_rep( const scfx_rep& a )
353: m_mant( a.m_mant ), m_wp( a.m_wp ), m_sign( a.m_sign ), m_state( a.m_state ),
354  m_msw( a.m_msw ), m_lsw( a.m_lsw ), m_r_flag( false )
355{}
356
357
358// ----------------------------------------------------------------------------
359//  OPERATORS : new, delete
360//
361//  Memory management for class scfx_rep.
362// ----------------------------------------------------------------------------
363
364union scfx_rep_node
365{
366    char           data[sizeof( scfx_rep )];
367    scfx_rep_node* next;
368};
369
370
371static scfx_rep_node* list = 0;
372
373
374void*
375scfx_rep::operator new( std::size_t size )
376{
377    const int ALLOC_SIZE = 1024;
378
379    if( size != sizeof( scfx_rep ) )
380	return ::operator new( size );
381
382    if( ! list )
383    {
384	list = new scfx_rep_node[ALLOC_SIZE];
385	for( int i = 0; i < ALLOC_SIZE - 1; i ++ )
386	    list[i].next = list + i + 1;
387	list[ALLOC_SIZE - 1].next = 0;
388    }
389
390    scfx_rep* ptr = reinterpret_cast<scfx_rep*>( list->data );
391    list = list->next;
392
393    return ptr;
394}
395
396
397void scfx_rep::operator delete( void* ptr, std::size_t size )
398{
399    if( size != sizeof( scfx_rep ) )
400    {
401	::operator delete( ptr );
402	return;
403    }
404
405    scfx_rep_node* node = static_cast<scfx_rep_node*>( ptr );
406    node->next = list;
407    list = node;
408}
409
410
411// ----------------------------------------------------------------------------
412//  METHOD : from_string
413//
414//  Convert from character string to sc_fxrep.
415// ----------------------------------------------------------------------------
416
417#define SCFX_FAIL_IF_(cnd)                                                    \
418{                                                                             \
419    if( ( cnd ) )                                                             \
420    {                                                                         \
421        m_state = not_a_number;                                               \
422	m_mant.clear(); /* to avoid Purify UMRs during assignment */          \
423        return;                                                               \
424    }                                                                         \
425}
426
427
428void
429scfx_rep::from_string( const char* s, int cte_wl )
430{
431    SCFX_FAIL_IF_( s == 0 || *s == 0 );
432
433    scfx_string s2;
434    s2 += s;
435    s2 += '\0';
436
437    bool sign_char;
438    m_sign = scfx_parse_sign( s, sign_char );
439
440    sc_numrep numrep = scfx_parse_prefix( s );
441
442    int base = 0;
443
444    switch( numrep )
445    {
446	case SC_DEC:
447	{
448	    base = 10;
449	    if( scfx_is_nan( s ) )
450	    {   // special case: NaN
451		m_state = not_a_number;
452		m_mant.clear(); /* to avoid Purify UMRs during assignment */
453		return;
454	    }
455	    if( scfx_is_inf( s ) )
456	    {   // special case: Infinity
457		m_state = infinity;
458		m_mant.clear(); /* to avoid Purify UMRs during assignment */
459		return;
460	    }
461	    break;
462	}
463	case SC_BIN:
464	case SC_BIN_US:
465	{
466	    SCFX_FAIL_IF_( sign_char );
467	    base = 2;
468	    break;
469	}
470
471	case SC_BIN_SM:
472	{
473	    base = 2;
474	    break;
475	}
476	case SC_OCT:
477	case SC_OCT_US:
478	{
479	    SCFX_FAIL_IF_( sign_char );
480	    base = 8;
481	    break;
482	}
483	case SC_OCT_SM:
484	{
485	    base = 8;
486	    break;
487	}
488	case SC_HEX:
489	case SC_HEX_US:
490	{
491	    SCFX_FAIL_IF_( sign_char );
492	    base = 16;
493	    break;
494	}
495	case SC_HEX_SM:
496	{
497	    base = 16;
498	    break;
499	}
500	case SC_CSD:
501	{
502	    SCFX_FAIL_IF_( sign_char );
503	    base = 2;
504	    scfx_csd2tc( s2 );
505	    s = (const char*) s2 + 4;
506	    numrep = SC_BIN;
507	    break;
508	}
509        default:;
510    }
511
512    //
513    // find end of mantissa and count the digits and points
514    //
515
516    const char *end = s;
517    bool based_point = false;
518    int int_digits = 0;
519    int frac_digits = 0;
520
521    while( *end )
522    {
523	if( scfx_exp_start( end ) )
524	    break;
525
526	if( *end == '.' )
527	{
528	    SCFX_FAIL_IF_( based_point );
529	    based_point = true;
530	}
531	else
532	{
533	    SCFX_FAIL_IF_( ! scfx_is_digit( *end, numrep ) );
534	    if( based_point )
535		frac_digits ++;
536	    else
537		int_digits ++;
538	}
539
540	++ end;
541    }
542
543    SCFX_FAIL_IF_( int_digits == 0 && frac_digits == 0 );
544
545    // [ exponent ]
546
547    int exponent = 0;
548
549    if( *end )
550    {
551	for( const char *e = end + 2; *e; ++ e )
552	    SCFX_FAIL_IF_( ! scfx_is_digit( *e, SC_DEC ) );
553	exponent = atoi( end + 1 );
554    }
555
556    //
557    // check if the mantissa is negative
558    //
559
560    bool mant_is_neg = false;
561
562    switch( numrep )
563    {
564	case SC_BIN:
565	case SC_OCT:
566	case SC_HEX:
567	{
568	    const char* p = s;
569	    if( *p == '.' )
570		++ p;
571
572	    mant_is_neg = ( scfx_to_digit( *p, numrep ) >= ( base >> 1 ) );
573
574	    break;
575	}
576	default:
577	    ;
578    }
579
580    //
581    // convert the mantissa
582    //
583
584    switch( base )
585    {
586        case 2:
587	{
588	    int bit_offset = exponent % bits_in_word;
589	    int word_offset = exponent / bits_in_word;
590
591	    int_digits += bit_offset;
592	    frac_digits -= bit_offset;
593
594	    int words = n_word( int_digits ) + n_word( frac_digits );
595	    if( words > size() )
596		resize_to( words );
597	    m_mant.clear();
598
599	    int j = n_word( frac_digits ) * bits_in_word + int_digits - 1;
600
601	    for( ; s < end; s ++ )
602	    {
603		switch( *s )
604		{
605		    case '1':
606		        set_bin( j );
607		    case '0':
608			j --;
609		    case '.':
610			break;
611		    default:
612			SCFX_FAIL_IF_( true );  // should not happen
613		}
614	    }
615
616	    m_wp = n_word( frac_digits ) - word_offset;
617	    break;
618	}
619        case 8:
620	{
621	    exponent *= 3;
622	    int_digits *= 3;
623	    frac_digits *= 3;
624
625	    int bit_offset = exponent % bits_in_word;
626	    int word_offset = exponent / bits_in_word;
627
628	    int_digits += bit_offset;
629	    frac_digits -= bit_offset;
630
631	    int words = n_word( int_digits ) + n_word( frac_digits );
632	    if( words > size() )
633		resize_to( words );
634	    m_mant.clear();
635
636	    int j = n_word( frac_digits ) * bits_in_word + int_digits - 3;
637
638	    for( ; s < end; s ++ )
639	    {
640		switch( *s )
641		{
642		    case '7': case '6': case '5': case '4':
643		    case '3': case '2': case '1':
644		        set_oct( j, *s - '0' );
645		    case '0':
646			j -= 3;
647		    case '.':
648			break;
649		    default:
650			SCFX_FAIL_IF_( true );  // should not happen
651		}
652	    }
653
654	    m_wp = n_word( frac_digits ) - word_offset;
655	    break;
656	}
657        case 10:
658	{
659	    word carry, temp;
660	    int length = int_digits + frac_digits;
661	    resize_to( sc_max( min_mant, n_word( 4 * length ) ) );
662
663	    m_mant.clear();
664	    m_msw = m_lsw = 0;
665
666	    for( ; s < end; s ++ )
667	    {
668		switch( *s )
669		{
670		    case '9': case '8': case '7': case '6': case '5':
671		    case '4': case '3': case '2': case '1': case '0':
672		        multiply_by_ten();
673			carry = *s - '0';
674			for ( int i = 0; carry && i < m_mant.size(); i++ )
675			{
676			    temp = m_mant[i];
677                            temp += carry;
678			    carry = temp < m_mant[i];
679			    m_mant[i] = temp;
680			}
681		    case '.':
682			break;
683		    default:
684			SCFX_FAIL_IF_( true );  // should not happen
685		}
686	    }
687
688	    m_wp = 0;
689	    find_sw();
690
691	    int denominator = frac_digits - exponent;
692
693	    if( denominator )
694	    {
695		scfx_rep frac_num = pow10_fx( denominator );
696		scfx_rep* temp_num =
697		    div_scfx_rep( const_cast<const scfx_rep&>( *this ),
698				   frac_num, cte_wl );
699		*this = *temp_num;
700		delete temp_num;
701	    }
702
703	    break;
704	}
705        case 16:
706	{
707	    exponent *= 4;
708	    int_digits *= 4;
709	    frac_digits *= 4;
710
711	    int bit_offset = exponent % bits_in_word;
712	    int word_offset = exponent / bits_in_word;
713
714	    int_digits += bit_offset;
715	    frac_digits -= bit_offset;
716
717	    int words = n_word( int_digits ) + n_word( frac_digits );
718	    if( words > size() )
719		resize_to( words );
720	    m_mant.clear();
721
722	    int j = n_word( frac_digits ) * bits_in_word + int_digits - 4;
723
724	    for( ; s < end; s ++ )
725	    {
726		switch( *s )
727		{
728		    case 'f': case 'e': case 'd': case 'c': case 'b': case 'a':
729		       set_hex( j, *s - 'a' + 10 );
730		       j -= 4;
731		       break;
732		    case 'F': case 'E': case 'D': case 'C': case 'B': case 'A':
733		       set_hex( j, *s - 'A' + 10 );
734		       j -= 4;
735		       break;
736		    case '9': case '8': case '7': case '6': case '5':
737		    case '4': case '3': case '2': case '1':
738		       set_hex( j, *s - '0' );
739		    case '0':
740		       j -= 4;
741		    case '.':
742		       break;
743		   default:
744		       SCFX_FAIL_IF_( true );  // should not happen
745		}
746	    }
747
748	    m_wp = n_word( frac_digits ) - word_offset;
749	    break;
750	}
751    }
752
753    m_state = normal;
754    find_sw();
755
756    //
757    // two's complement of mantissa if it is negative
758    //
759
760    if( mant_is_neg )
761    {
762	m_mant[m_msw] |=  -1 << scfx_find_msb( m_mant[m_msw] );
763	for( int i = m_msw + 1; i < m_mant.size(); ++ i )
764	    m_mant[i] = static_cast<word>( -1 );
765	complement( m_mant, m_mant, m_mant.size() );
766	inc( m_mant );
767	m_sign *= -1;
768	find_sw();
769    }
770}
771
772
773#undef SCFX_FAIL_IF_
774
775
776// ----------------------------------------------------------------------------
777//  METHOD : to_double
778//
779//  Convert from scfx_rep to double.
780// ----------------------------------------------------------------------------
781
782double
783scfx_rep::to_double() const
784{
785    scfx_ieee_double id;
786
787    // handle special cases
788
789    if( is_nan() )
790    {
791        id.set_nan();
792	return id;
793    }
794
795    if( is_inf() )
796    {
797        id.set_inf();
798	id.negative( m_sign < 0 );
799	return id;
800    }
801
802    if( is_zero() )
803    {
804	id = 0.;
805	id.negative( m_sign < 0 );
806	return id;
807    }
808
809    int msb = scfx_find_msb( m_mant[m_msw] );
810
811    int exp = (m_msw - m_wp) * bits_in_word + msb;
812
813    if( exp > SCFX_IEEE_DOUBLE_E_MAX )
814    {
815	id.set_inf();
816	id.negative( m_sign < 0 );
817	return id;
818    }
819
820    if( exp < SCFX_IEEE_DOUBLE_E_MIN
821	- static_cast<int>( SCFX_IEEE_DOUBLE_M_SIZE ) )
822    {
823	id = 0.;
824	return id;
825    }
826
827    int shift = mantissa0_size - msb;
828
829    unsigned int m0;
830    unsigned int m1 = 0;
831    unsigned int guard = 0;
832
833    if( shift == 0 )
834    {
835        m0 = m_mant[m_msw] & ~( 1 << mantissa0_size );
836	if( m_msw > m_lsw )
837	{
838	    m1 = m_mant[m_msw - 1];
839	    if( m_msw - 1 > m_lsw )
840	        guard = m_mant[m_msw - 2] >> ( bits_in_word - 1 );
841	}
842    }
843    else if( shift < 0 )
844    {
845	m0 = ( m_mant[m_msw] >> -shift ) & ~( 1 << mantissa0_size );
846	m1 = m_mant[m_msw] << ( bits_in_word + shift );
847	if( m_msw > m_lsw )
848	{
849	    m1 |= m_mant[m_msw - 1] >> -shift;
850	    guard = ( m_mant[m_msw - 1] >> ( -shift - 1 ) ) & 1;
851	}
852    }
853    else
854    {
855	m0 = ( m_mant[m_msw] << shift ) & ~( 1 << mantissa0_size );
856	if( m_msw > m_lsw )
857	{
858	    m0 |= m_mant[m_msw - 1] >> ( bits_in_word - shift );
859	    m1 = m_mant[m_msw - 1] << shift;
860	    if( m_msw - 1 > m_lsw )
861	    {
862	        m1 |= m_mant[m_msw - 2] >> ( bits_in_word - shift );
863		guard = ( m_mant[m_msw - 2] >> (bits_in_word - shift - 1) )
864                      & 1;
865	    }
866	}
867    }
868
869    if( exp < SCFX_IEEE_DOUBLE_E_MIN )
870    {
871	m0 |= ( 1 << mantissa0_size );
872
873	int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp;
874
875	if( subnormal_shift < bits_in_word )
876	{
877	    m1 = m1 >> subnormal_shift
878	       | m0 << ( bits_in_word - subnormal_shift );
879	    m0 = m0 >> subnormal_shift;
880	}
881	else
882	{
883	    m1 = m0 >> ( subnormal_shift - bits_in_word );
884	    m0 = 0;
885	}
886
887	guard = 0;
888
889	exp = SCFX_IEEE_DOUBLE_E_MIN - 1;
890    }
891
892    id.mantissa0( m0 );
893    id.mantissa1( m1 );
894    id.exponent( exp );
895    id.negative( m_sign < 0 );
896
897    double result = id;
898
899    if( guard != 0 )
900        result += m_sign * scfx_pow2( exp - SCFX_IEEE_DOUBLE_M_SIZE );
901
902    return result;
903}
904
905
906// ----------------------------------------------------------------------------
907//  METHOD : to_string
908//
909//  Convert from scfx_rep to character string.
910// ----------------------------------------------------------------------------
911
912void
913print_dec( scfx_string& s, const scfx_rep& num, int w_prefix, sc_fmt fmt )
914{
915    if( num.is_neg() )
916	s += '-';
917
918    if( w_prefix == 1 ) {
919	scfx_print_prefix( s, SC_DEC );
920    }
921
922    if( num.is_zero() )
923    {
924	s += '0';
925	return;
926    }
927
928    // split 'num' into its integer and fractional part
929
930    scfx_rep int_part  = num;
931    scfx_rep frac_part = num;
932
933    int i;
934
935    for( i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i ++ )
936	int_part.m_mant[i] = 0;
937    int_part.find_sw();
938    if( int_part.m_wp < int_part.m_lsw )
939	int_part.resize_to( int_part.size() - int_part.m_wp, -1 );
940
941    for( i = frac_part.m_msw;
942	 i >= frac_part.m_lsw && i >= frac_part.m_wp;
943	 i -- )
944	frac_part.m_mant[i] = 0;
945    frac_part.find_sw();
946    if( frac_part.m_msw == frac_part.size() - 1 )
947	frac_part.resize_to( frac_part.size() + 1, 1 );
948
949    // print integer part
950
951    int int_digits = 0;
952    int int_zeros  = 0;
953
954    if( ! int_part.is_zero() )
955    {
956	double int_wl = ( int_part.m_msw - int_part.m_wp ) * bits_in_word
957	              + scfx_find_msb( int_part.m_mant[int_part.m_msw] ) + 1;
958	int_digits = (int) ceil( int_wl * log10( 2. ) );
959
960	int len = s.length();
961	s.append( int_digits );
962
963	bool zero_digits = ( frac_part.is_zero() && fmt != SC_F );
964
965	for( i = int_digits + len - 1; i >= len; i-- )
966	{
967	    unsigned int remainder = int_part.divide_by_ten();
968	    s[i] = static_cast<char>( '0' + remainder );
969
970	    if( zero_digits )
971	    {
972		if( remainder == 0 )
973		    int_zeros ++;
974		else
975		    zero_digits = false;
976	    }
977	}
978
979	// discard trailing zeros from int_part
980	s.discard( int_zeros );
981
982	if( s[len] == '0' )
983	{
984	    // int_digits was overestimated by one
985	    s.remove( len );
986	    -- int_digits;
987	}
988    }
989
990    // print fractional part
991
992    int frac_digits = 0;
993    int frac_zeros  = 0;
994
995    if( ! frac_part.is_zero() )
996    {
997	s += '.';
998
999	bool zero_digits = ( int_digits == 0 && fmt != SC_F );
1000
1001	double frac_wl = ( frac_part.m_wp - frac_part.m_msw ) * bits_in_word
1002	               - scfx_find_msb( frac_part.m_mant[frac_part.m_msw] )
1003                       - 1;
1004	frac_zeros = (int) floor( frac_wl * log10( 2. ) );
1005
1006	scfx_rep temp;
1007	sc_dt::multiply( temp, frac_part, pow10_fx( frac_zeros ) );
1008	frac_part = temp;
1009	if( frac_part.m_msw == frac_part.size() - 1 )
1010	    frac_part.resize_to( frac_part.size() + 1, 1 );
1011
1012	frac_digits = frac_zeros;
1013	if( ! zero_digits )
1014	{
1015	    for( i = 0; i < frac_zeros; i ++ )
1016		s += '0';
1017	    frac_zeros = 0;
1018	}
1019
1020	while( ! frac_part.is_zero() )
1021	{
1022	    frac_part.multiply_by_ten();
1023	    int n = frac_part.m_mant[frac_part.m_msw + 1];
1024
1025	    if( zero_digits )
1026	    {
1027		if( n == 0 )
1028		    frac_zeros ++;
1029		else
1030		    zero_digits = false;
1031	    }
1032
1033	    if( ! zero_digits )
1034		s += static_cast<char>( '0' + n );
1035
1036	    frac_part.m_mant[frac_part.m_msw + 1] = 0;
1037	    frac_digits ++;
1038	}
1039    }
1040
1041    // print exponent
1042
1043    if( fmt != SC_F )
1044    {
1045        if( frac_digits == 0 )
1046	    scfx_print_exp( s, int_zeros );
1047	else if( int_digits == 0 )
1048	    scfx_print_exp( s, - frac_zeros );
1049    }
1050}
1051
1052void
1053print_other( scfx_string& s, const scfx_rep& a, sc_numrep numrep, int w_prefix,
1054	     sc_fmt fmt, const scfx_params* params )
1055{
1056    scfx_rep b = a;
1057
1058    sc_numrep numrep2 = numrep;
1059
1060    bool numrep_is_sm = ( numrep == SC_BIN_SM ||
1061			  numrep == SC_OCT_SM ||
1062			  numrep == SC_HEX_SM );
1063
1064    if( numrep_is_sm )
1065    {
1066	if( b.is_neg() )
1067	{
1068	    s += '-';
1069	    b = *neg_scfx_rep( a );
1070	}
1071	switch( numrep )
1072	{
1073	    case SC_BIN_SM:
1074		numrep2 = SC_BIN_US;
1075		break;
1076	    case SC_OCT_SM:
1077		numrep2 = SC_OCT_US;
1078		break;
1079	    case SC_HEX_SM:
1080		numrep2 = SC_HEX_US;
1081		break;
1082	    default:
1083		;
1084	}
1085    }
1086
1087    if( w_prefix != 0 ) {
1088	scfx_print_prefix( s, numrep );
1089    }
1090
1091    numrep = numrep2;
1092
1093    int msb, lsb;
1094
1095    if( params != 0 )
1096    {
1097	msb = params->iwl() - 1;
1098	lsb = params->iwl() - params->wl();
1099
1100	if( params->enc() == SC_TC_ &&
1101	    ( numrep == SC_BIN_US ||
1102	      numrep == SC_OCT_US ||
1103	      numrep == SC_HEX_US ) &&
1104	    ! numrep_is_sm &&
1105	    params->wl() > 1 )
1106	    -- msb;
1107	else if( params->enc() == SC_US_ &&
1108	    ( numrep == SC_BIN ||
1109	      numrep == SC_OCT ||
1110	      numrep == SC_HEX ||
1111	      numrep == SC_CSD ) )
1112	    ++ msb;
1113    }
1114    else
1115    {
1116	if( b.is_zero() )
1117	{
1118	    msb = 0;
1119	    lsb = 0;
1120	}
1121	else
1122	{
1123	    msb = ( b.m_msw - b.m_wp ) * bits_in_word
1124		+ scfx_find_msb( b.m_mant[ b.m_msw ] ) + 1;
1125	    while( b.get_bit( msb ) == b.get_bit( msb - 1 ) )
1126		-- msb;
1127
1128	    if( numrep == SC_BIN_US ||
1129		numrep == SC_OCT_US ||
1130		numrep == SC_HEX_US )
1131		-- msb;
1132
1133	    lsb = ( b.m_lsw - b.m_wp ) * bits_in_word
1134		+ scfx_find_lsb( b.m_mant[ b.m_lsw ] );
1135	}
1136    }
1137
1138    int step;
1139
1140    switch( numrep )
1141    {
1142	case SC_BIN:
1143	case SC_BIN_US:
1144	case SC_CSD:
1145	    step = 1;
1146	   break;
1147	case SC_OCT:
1148	case SC_OCT_US:
1149	    step = 3;
1150	    break;
1151	case SC_HEX:
1152	case SC_HEX_US:
1153	    step = 4;
1154	    break;
1155	default:
1156	    step = 0;
1157    }
1158
1159    msb = (int) ceil( double( msb + 1 ) / step ) * step - 1;
1160
1161    lsb = (int) floor( double( lsb ) / step ) * step;
1162
1163    if( msb < 0 )
1164    {
1165	s += '.';
1166	if( fmt == SC_F )
1167	{
1168	    int sign = ( b.is_neg() ) ? ( 1 << step ) - 1 : 0;
1169	    for( int i = ( msb + 1 ) / step; i < 0; i ++ )
1170	    {
1171		if( sign < 10 )
1172		    s += static_cast<char>( sign + '0' );
1173		else
1174		    s += static_cast<char>( sign + 'a' - 10 );
1175	    }
1176	}
1177    }
1178
1179    int i = msb;
1180    while( i >= lsb )
1181    {
1182        int value = 0;
1183        for( int j = step - 1; j >= 0; -- j )
1184	{
1185            value += static_cast<int>( b.get_bit( i ) ) << j;
1186            -- i;
1187        }
1188        if( value < 10 )
1189            s += static_cast<char>( value + '0' );
1190	else
1191            s += static_cast<char>( value + 'a' - 10 );
1192	if( i == -1 )
1193	    s += '.';
1194    }
1195
1196    if( lsb > 0 && fmt == SC_F )
1197    {
1198	for( int i = lsb / step; i > 0; i -- )
1199	    s += '0';
1200    }
1201
1202    if( s[s.length() - 1] == '.' )
1203	s.discard( 1 );
1204
1205    if( fmt != SC_F )
1206    {
1207	if( msb < 0 )
1208	    scfx_print_exp( s, ( msb + 1 ) / step );
1209	else if( lsb > 0 )
1210	    scfx_print_exp( s, lsb / step );
1211    }
1212
1213    if( numrep == SC_CSD )
1214	scfx_tc2csd( s, w_prefix );
1215}
1216
1217const char*
1218scfx_rep::to_string( sc_numrep numrep, int w_prefix,
1219		     sc_fmt fmt, const scfx_params* params ) const
1220{
1221    static scfx_string s;
1222
1223    s.clear();
1224
1225    if( is_nan() )
1226        scfx_print_nan( s );
1227    else if( is_inf() )
1228        scfx_print_inf( s, is_neg() );
1229    else if( is_neg() && ! is_zero() &&
1230	     ( numrep == SC_BIN_US ||
1231	       numrep == SC_OCT_US ||
1232	       numrep == SC_HEX_US ) )
1233        s += "negative";
1234    else if( numrep == SC_DEC || numrep == SC_NOBASE )
1235        sc_dt::print_dec( s, *this, w_prefix, fmt );
1236    else
1237        sc_dt::print_other( s, *this, numrep, w_prefix, fmt, params );
1238
1239    return s;
1240}
1241
1242
1243// ----------------------------------------------------------------------------
1244//  ADD
1245//
1246//  add two mantissas of the same size
1247//  result has the same size
1248//  returns carry of operation
1249// ----------------------------------------------------------------------------
1250
1251static inline
1252int
1253add_mants( int size, scfx_mant& result,
1254	   const scfx_mant& a, const scfx_mant& b )
1255{
1256    unsigned int carry = 0;
1257
1258    int index = 0;
1259
1260    do
1261    {
1262        word x = a[index];
1263	word y = b[index];
1264
1265	y += carry;
1266	carry = y < carry;
1267	y += x;
1268	carry += y < x;
1269	result[index] = y;
1270    }
1271    while( ++ index < size );
1272
1273    return ( carry ? 1 : 0 );
1274}
1275
1276
1277static inline
1278int
1279sub_mants( int size, scfx_mant& result,
1280	   const scfx_mant& a, const scfx_mant& b )
1281{
1282    unsigned carry = 0;
1283
1284    int index = 0;
1285
1286    do
1287    {
1288	word x = a[index];
1289	word y = b[index];
1290
1291	y += carry;
1292	carry = y < carry;
1293	y = x - y;
1294	carry += y > x;
1295	result[index] = y;
1296    }
1297    while( ++ index < size );
1298
1299    return ( carry ? 1 : 0 );
1300}
1301
1302
1303scfx_rep*
1304add_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int max_wl )
1305{
1306    scfx_rep& result = *new scfx_rep;
1307
1308    //
1309    // check for special cases
1310    //
1311
1312    if( lhs.is_nan() || rhs.is_nan()
1313    ||  ( lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign ) )
1314    {
1315	result.set_nan();
1316	return &result;
1317    }
1318
1319    if( lhs.is_inf() )
1320    {
1321	result.set_inf( lhs.m_sign );
1322	return &result;
1323    }
1324
1325    if( rhs.is_inf() )
1326    {
1327	result.set_inf( rhs.m_sign );
1328	return &result;
1329    }
1330
1331    //
1332    // align operands if needed
1333    //
1334
1335    scfx_mant_ref lhs_mant;
1336    scfx_mant_ref rhs_mant;
1337
1338    int len_mant = lhs.size();
1339    int new_wp = lhs.m_wp;
1340
1341    align( lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant );
1342
1343    //
1344    // size the result mantissa
1345    //
1346
1347    result.resize_to( len_mant );
1348    result.m_wp = new_wp;
1349
1350    //
1351    // do it
1352    //
1353
1354    if( lhs.m_sign == rhs.m_sign )
1355    {
1356	add_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
1357	result.m_sign = lhs.m_sign;
1358    }
1359    else
1360    {
1361	int cmp = compare_abs( lhs, rhs );
1362
1363	if( cmp == 1 )
1364	{
1365	    sub_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
1366	    result.m_sign = lhs.m_sign;
1367	}
1368	else if ( cmp == -1 )
1369	{
1370	    sub_mants( len_mant, result.m_mant, rhs_mant, lhs_mant );
1371	    result.m_sign = rhs.m_sign;
1372	}
1373	else
1374	{
1375	    result.m_mant.clear();
1376	    result.m_sign = 1;
1377	}
1378    }
1379
1380    result.find_sw();
1381    result.round( max_wl );
1382
1383    return &result;
1384}
1385
1386
1387// ----------------------------------------------------------------------------
1388//  SUB
1389//
1390//  sub two word's of the same size
1391//  result has the same size
1392//  returns carry of operation
1393// ----------------------------------------------------------------------------
1394
1395static inline
1396int
1397sub_with_index(       scfx_mant& a, int a_msw, int /*a_lsw*/,
1398		const scfx_mant& b, int b_msw, int b_lsw )
1399{
1400    unsigned carry = 0;
1401
1402    int size    = b_msw - b_lsw;
1403    int a_index = a_msw - size;
1404    int b_index = b_msw - size;
1405
1406    do
1407    {
1408	word x = a[a_index];
1409	word y = b[b_index];
1410
1411	y += carry;
1412	carry = y < carry;
1413	y = x - y;
1414	carry += y > x;
1415	a[a_index] = y;
1416
1417	a_index ++;
1418	b_index ++;
1419    }
1420    while( size -- );
1421
1422    if( carry )
1423    {
1424        // special case: a[a_msw + 1 ] == 1
1425        a[a_msw + 1] = 0;
1426    }
1427
1428    return ( carry ? 1 : 0 );
1429}
1430
1431
1432scfx_rep*
1433sub_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int max_wl )
1434{
1435    scfx_rep& result = *new scfx_rep;
1436
1437    //
1438    // check for special cases
1439    //
1440
1441    if( lhs.is_nan() || rhs.is_nan()
1442    ||  ( lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign ) )
1443    {
1444	result.set_nan();
1445	return &result;
1446    }
1447
1448    if( lhs.is_inf() )
1449    {
1450	result.set_inf( lhs.m_sign );
1451	return &result;
1452    }
1453
1454    if( rhs.is_inf() )
1455    {
1456	result.set_inf( -1 * rhs.m_sign );
1457	return &result;
1458    }
1459
1460    //
1461    // align operands if needed
1462    //
1463
1464    scfx_mant_ref lhs_mant;
1465    scfx_mant_ref rhs_mant;
1466
1467    int len_mant = lhs.size();
1468    int new_wp = lhs.m_wp;
1469
1470    align( lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant );
1471
1472    //
1473    // size the result mantissa
1474    //
1475
1476    result.resize_to( len_mant );
1477    result.m_wp = new_wp;
1478
1479    //
1480    // do it
1481    //
1482
1483    if( lhs.m_sign != rhs.m_sign )
1484    {
1485	add_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
1486	result.m_sign = lhs.m_sign;
1487    }
1488    else
1489    {
1490	int cmp = compare_abs( lhs, rhs );
1491
1492	if( cmp == 1 )
1493	{
1494	    sub_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );
1495	    result.m_sign = lhs.m_sign;
1496	}
1497	else if ( cmp == -1 )
1498	{
1499	    sub_mants( len_mant, result.m_mant, rhs_mant, lhs_mant );
1500	    result.m_sign = -rhs.m_sign;
1501	} else {
1502	    result.m_mant.clear();
1503	    result.m_sign = 1;
1504	}
1505    }
1506
1507    result.find_sw();
1508    result.round( max_wl );
1509
1510    return &result;
1511}
1512
1513
1514// ----------------------------------------------------------------------------
1515//  MUL
1516// ----------------------------------------------------------------------------
1517
1518union word_short
1519{
1520    word l;
1521    struct
1522    {
1523#if defined( SC_BIG_ENDIAN )
1524        half_word u;
1525        half_word l;
1526#elif defined( SC_LITTLE_ENDIAN )
1527        half_word l;
1528        half_word u;
1529#endif
1530    } s;
1531};
1532
1533
1534#if defined( SC_BIG_ENDIAN )
1535static const int half_word_incr = -1;
1536#elif defined( SC_LITTLE_ENDIAN )
1537static const int half_word_incr = 1;
1538#endif
1539
1540
1541void
1542multiply( scfx_rep& result, const scfx_rep& lhs, const scfx_rep& rhs,
1543	  int max_wl )
1544{
1545    //
1546    // check for special cases
1547    //
1548
1549    if( lhs.is_nan() || rhs.is_nan()
1550    ||  (lhs.is_inf() && rhs.is_zero())
1551    ||  (lhs.is_zero() && rhs.is_inf()) )
1552    {
1553	result.set_nan();
1554	return;
1555    }
1556
1557    if( lhs.is_inf() || rhs.is_inf() )
1558    {
1559	result.set_inf( lhs.m_sign * rhs.m_sign );
1560	return;
1561    }
1562
1563    if( lhs.is_zero() || rhs.is_zero() ) {
1564	result.set_zero( lhs.m_sign * rhs.m_sign );
1565	return;
1566    }
1567
1568    //
1569    // do it
1570    //
1571
1572    int len_lhs = lhs.m_msw - lhs.m_lsw + 1;
1573    int len_rhs = rhs.m_msw - rhs.m_lsw + 1;
1574
1575    int new_size = sc_max( min_mant, len_lhs + len_rhs );
1576    int new_wp   = ( lhs.m_wp - lhs.m_lsw ) + ( rhs.m_wp - rhs.m_lsw );
1577    int new_sign = lhs.m_sign * rhs.m_sign;
1578
1579    result.resize_to( new_size );
1580    result.m_mant.clear();
1581    result.m_wp    = new_wp;
1582    result.m_sign  = new_sign;
1583    result.m_state = scfx_rep::normal;
1584
1585    half_word *s1 = lhs.m_mant.half_addr( lhs.m_lsw );
1586    half_word *s2 = rhs.m_mant.half_addr( rhs.m_lsw );
1587
1588    half_word *t = result.m_mant.half_addr();
1589
1590    len_lhs <<= 1;
1591    len_rhs <<= 1;
1592
1593    int i1, i2;
1594
1595    for( i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr )
1596    {
1597	word_short ls;
1598	ls.l = 0;
1599
1600	half_word v1 = s1[i1];
1601
1602	for( i2  = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr )
1603	{
1604	    ls.l  += v1 * s2[i2];
1605	    ls.s.l = ls.s.u + ( ( t[i2] += ls.s.l ) < ls.s.l );
1606	    ls.s.u = 0;
1607	}
1608
1609	t[i2] = ls.s.l;
1610	t += half_word_incr;
1611    }
1612
1613    result.find_sw();
1614    result.round( max_wl );
1615}
1616
1617
1618// ----------------------------------------------------------------------------
1619//  DIV
1620// ----------------------------------------------------------------------------
1621
1622scfx_rep*
1623div_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int div_wl )
1624{
1625    scfx_rep& result = *new scfx_rep;
1626
1627    //
1628    // check for special cases
1629    //
1630
1631    if( lhs.is_nan() || rhs.is_nan() || (lhs.is_inf() && rhs.is_inf()) ||
1632	(lhs.is_zero() && rhs.is_zero()) )
1633    {
1634	result.set_nan();
1635	return &result;
1636    }
1637
1638    if( lhs.is_inf() || rhs.is_zero() )
1639    {
1640	result.set_inf( lhs.m_sign * rhs.m_sign );
1641	return &result;
1642    }
1643
1644    if( lhs.is_zero() || rhs.is_inf() )
1645    {
1646	result.set_zero( lhs.m_sign * rhs.m_sign );
1647	return &result;
1648    }
1649
1650    //
1651    // do it
1652    //
1653
1654    // compute one bit more for rounding
1655    div_wl ++;
1656
1657    result.resize_to( sc_max( n_word( div_wl ) + 1, min_mant ) );
1658    result.m_mant.clear();
1659    result.m_sign = lhs.m_sign * rhs.m_sign;
1660
1661    int msb_lhs = scfx_find_msb( lhs.m_mant[lhs.m_msw] )
1662	        + ( lhs.m_msw - lhs.m_wp ) * bits_in_word;
1663    int msb_rhs = scfx_find_msb( rhs.m_mant[rhs.m_msw] )
1664	        + ( rhs.m_msw - rhs.m_wp ) * bits_in_word;
1665
1666    int msb_res = msb_lhs - msb_rhs;
1667    int to_shift = -msb_res % bits_in_word;
1668    int result_index;
1669
1670    int c = ( msb_res % bits_in_word >= 0 ) ? 1 : 0;
1671
1672    result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word;
1673    result.m_wp   = (result.size() - c) - msb_res / bits_in_word;
1674
1675    scfx_rep remainder = lhs;
1676
1677    // align msb from remainder to msb from rhs
1678    remainder.lshift( to_shift );
1679
1680    // make sure msw( remainder ) < size - 1
1681    if( remainder.m_msw == remainder.size() - 1 )
1682	remainder.resize_to( remainder.size() + 1, 1 );
1683
1684    // make sure msw( remainder ) >= msw( rhs )!
1685    int msw_diff = rhs.m_msw - remainder.m_msw;
1686    if (msw_diff > 0)
1687	remainder.resize_to( remainder.size() + msw_diff, -1 );
1688
1689    int counter;
1690
1691    for( counter = div_wl; counter && ! remainder.is_zero(); counter -- )
1692    {
1693	if( compare_msw_ff( rhs, remainder ) <= 0 )
1694	{
1695	    result.set_bin( result_index );
1696	    sub_with_index( remainder.m_mant, remainder.m_msw, remainder.m_lsw,
1697			    rhs.m_mant, rhs.m_msw, rhs.m_lsw );
1698	}
1699	result_index --;
1700	remainder.shift_left( 1 );
1701        remainder.m_lsw = remainder.find_lsw();
1702    }
1703
1704    // perform convergent rounding, if needed
1705    if( counter == 0 )
1706    {
1707	int index = result_index + 1 - result.m_wp * bits_in_word;
1708
1709	scfx_index x = result.calc_indices( index );
1710	scfx_index x1 = result.calc_indices( index + 1 );
1711
1712	if( result.o_bit_at( x ) && result.o_bit_at( x1 ) )
1713	    result.q_incr( x );
1714
1715	result.m_r_flag = true;
1716    }
1717
1718    result.find_sw();
1719
1720    return &result;
1721}
1722
1723
1724// ----------------------------------------------------------------------------
1725//  destructive shift mantissa to the left
1726// ----------------------------------------------------------------------------
1727
1728void
1729scfx_rep::lshift( int n )
1730{
1731    if( n == 0 )
1732        return;
1733
1734    if( n < 0 )
1735    {
1736        rshift( -n );
1737	return;
1738    }
1739
1740    if( is_normal() )
1741    {
1742        int shift_bits  = n % bits_in_word;
1743	int shift_words = n / bits_in_word;
1744
1745	// resize if needed
1746	if( m_msw == size() - 1 &&
1747	    scfx_find_msb( m_mant[m_msw] ) >= bits_in_word - shift_bits )
1748	    resize_to( size() + 1, 1 );
1749
1750	// do it
1751	m_wp -= shift_words;
1752	shift_left( shift_bits );
1753	find_sw();
1754    }
1755}
1756
1757
1758// ----------------------------------------------------------------------------
1759//  destructive shift mantissa to the right
1760// ----------------------------------------------------------------------------
1761
1762void
1763scfx_rep::rshift( int n )
1764{
1765    if( n == 0 )
1766        return;
1767
1768    if( n < 0 )
1769    {
1770        lshift( -n );
1771	return;
1772    }
1773
1774    if( is_normal() )
1775    {
1776        int shift_bits  = n % bits_in_word;
1777	int shift_words = n / bits_in_word;
1778
1779	// resize if needed
1780	if( m_lsw == 0 && scfx_find_lsb( m_mant[m_lsw] ) < shift_bits )
1781	    resize_to( size() + 1, -1 );
1782
1783	// do it
1784	m_wp += shift_words;
1785	shift_right( shift_bits );
1786	find_sw();
1787    }
1788}
1789
1790
1791// ----------------------------------------------------------------------------
1792//  FRIEND FUNCTION : compare_abs
1793//
1794//  Compares the absolute values of two scfx_reps, excluding the special cases.
1795// ----------------------------------------------------------------------------
1796
1797int
1798compare_abs( const scfx_rep& a, const scfx_rep& b )
1799{
1800    // check for zero
1801
1802    word a_word = a.m_mant[a.m_msw];
1803    word b_word = b.m_mant[b.m_msw];
1804
1805    if( a_word == 0 || b_word == 0 )
1806    {
1807	if( a_word != 0 )
1808	    return 1;
1809	if( b_word != 0 )
1810	    return -1;
1811	return 0;
1812    }
1813
1814    // compare msw index
1815
1816    int a_msw = a.m_msw - a.m_wp;
1817    int b_msw = b.m_msw - b.m_wp;
1818
1819    if( a_msw > b_msw )
1820	return 1;
1821
1822    if( a_msw < b_msw )
1823	return -1;
1824
1825    // compare content
1826
1827    int a_i = a.m_msw;
1828    int b_i = b.m_msw;
1829
1830    while( a_i >= a.m_lsw && b_i >= b.m_lsw )
1831    {
1832	a_word = a.m_mant[a_i];
1833	b_word = b.m_mant[b_i];
1834	if( a_word > b_word )
1835	    return 1;
1836	if( a_word < b_word )
1837	    return -1;
1838	-- a_i;
1839	-- b_i;
1840    }
1841
1842    bool a_zero = true;
1843    while( a_i >= a.m_lsw )
1844    {
1845	a_zero = a_zero && ( a.m_mant[a_i] == 0 );
1846	-- a_i;
1847    }
1848
1849    bool b_zero = true;
1850    while( b_i >= b.m_lsw )
1851    {
1852	b_zero = b_zero && ( b.m_mant[b_i] == 0 );
1853	-- b_i;
1854    }
1855
1856    // assertion: a_zero || b_zero == true
1857
1858    if( ! a_zero && b_zero )
1859	return 1;
1860
1861    if( a_zero && ! b_zero )
1862	return -1;
1863
1864    return 0;
1865}
1866
1867
1868// ----------------------------------------------------------------------------
1869//  FRIEND FUNCTION : cmp_scfx_rep
1870//
1871//  Compares the values of two scfx_reps, including the special cases.
1872// ----------------------------------------------------------------------------
1873
1874int
1875cmp_scfx_rep( const scfx_rep& a, const scfx_rep& b )
1876{
1877    // handle special cases
1878
1879    if( a.is_nan() || b.is_nan() )
1880    {
1881#if 0
1882	if( a.is_nan() && b.is_nan() )
1883	{
1884	    return 0;
1885	}
1886#endif
1887	return 2;
1888    }
1889
1890    if( a.is_inf() || b.is_inf() )
1891    {
1892	if( a.is_inf() )
1893	{
1894	    if( ! a.is_neg() )
1895	    {
1896		if( b.is_inf() && ! b.is_neg() )
1897		{
1898		    return 0;
1899		}
1900		else
1901		{
1902		    return 1;
1903		}
1904	    }
1905	    else
1906	    {
1907		if( b.is_inf() && b.is_neg() )
1908		{
1909		    return 0;
1910		}
1911		else
1912		{
1913		    return -1;
1914		}
1915	    }
1916	}
1917	if( b.is_inf() )
1918	{
1919	    if( ! b.is_neg() )
1920	    {
1921		return -1;
1922	    }
1923	    else
1924	    {
1925		return 1;
1926	    }
1927	}
1928    }
1929
1930    if( a.is_zero() && b.is_zero() )
1931    {
1932	return 0;
1933    }
1934
1935    // compare sign
1936
1937    if( a.m_sign != b.m_sign )
1938    {
1939	return a.m_sign;
1940    }
1941
1942    return ( a.m_sign * compare_abs( a, b ) );
1943}
1944
1945
1946// ----------------------------------------------------------------------------
1947//  PRIVATE METHOD : quantization
1948//
1949//  Performs destructive quantization.
1950// ----------------------------------------------------------------------------
1951
1952void
1953scfx_rep::quantization( const scfx_params& params, bool& q_flag )
1954{
1955    scfx_index x = calc_indices( params.iwl() - params.wl() );
1956
1957    if( x.wi() < 0 )
1958        return;
1959
1960    if( x.wi() >= size() )
1961        resize_to( x.wi() + 1, 1 );
1962
1963    bool qb = q_bit( x );
1964    bool qz = q_zero( x );
1965
1966    q_flag = ( qb || ! qz );
1967
1968    if( q_flag )
1969    {
1970        switch( params.q_mode() )
1971	{
1972            case SC_TRN:			// truncation
1973	    {
1974	        if( is_neg() )
1975		    q_incr( x );
1976		break;
1977	    }
1978            case SC_RND:			// rounding to plus infinity
1979	    {
1980	        if( ! is_neg() )
1981		{
1982		    if( qb )
1983			q_incr( x );
1984		}
1985		else
1986		{
1987		    if( qb && ! qz )
1988			q_incr( x );
1989		}
1990		break;
1991	    }
1992            case SC_TRN_ZERO:			// truncation to zero
1993	    {
1994	        break;
1995	    }
1996            case SC_RND_INF:			// rounding to infinity
1997	    {
1998	        if( qb )
1999		    q_incr( x );
2000		break;
2001	    }
2002            case SC_RND_CONV:			// convergent rounding
2003	    {
2004		if( (qb && ! qz) || (qb && qz && q_odd( x )) )
2005		    q_incr( x );
2006		break;
2007	    }
2008            case SC_RND_ZERO:			// rounding to zero
2009	    {
2010		if( qb && ! qz )
2011		    q_incr( x );
2012		break;
2013	    }
2014            case SC_RND_MIN_INF:		// rounding to minus infinity
2015	    {
2016		if( ! is_neg() )
2017		{
2018		    if( qb && ! qz )
2019			q_incr( x );
2020		}
2021		else
2022		{
2023		    if( qb )
2024			q_incr( x );
2025		}
2026		break;
2027	    }
2028            default:
2029	        ;
2030	}
2031	q_clear( x );
2032
2033	find_sw();
2034    }
2035}
2036
2037
2038// ----------------------------------------------------------------------------
2039//  PRIVATE METHOD : overflow
2040//
2041//  Performs destructive overflow handling.
2042// ----------------------------------------------------------------------------
2043
2044void
2045scfx_rep::overflow( const scfx_params& params, bool& o_flag )
2046{
2047    scfx_index x = calc_indices( params.iwl() - 1 );
2048
2049    if( x.wi() >= size() )
2050        resize_to( x.wi() + 1, 1 );
2051
2052    if( x.wi() < 0 )
2053    {
2054        resize_to( size() - x.wi(), -1 );
2055        x.wi( 0 );
2056    }
2057
2058    bool zero_left = o_zero_left( x );
2059    bool bit_at = o_bit_at( x );
2060    bool zero_right = o_zero_right( x );
2061
2062    bool under = false;
2063    bool over = false;
2064
2065    sc_enc enc = params.enc();
2066
2067    if( enc == SC_TC_ )
2068    {
2069	if( is_neg() )
2070	{
2071	    if( params.o_mode() == SC_SAT_SYM )
2072		under = ( ! zero_left || bit_at );
2073	    else
2074		under = (! zero_left || (zero_left && bit_at && ! zero_right));
2075	}
2076	else
2077	    over = ( ! zero_left || bit_at );
2078    }
2079    else
2080    {
2081	if( is_neg() )
2082	    under = ( ! is_zero() );
2083        else
2084	    over = ( ! zero_left );
2085    }
2086
2087    o_flag = ( under || over );
2088
2089    if( o_flag )
2090    {
2091	scfx_index x2 = calc_indices( params.iwl() - params.wl() );
2092
2093	if( x2.wi() < 0 )
2094	{
2095	    resize_to( size() - x2.wi(), -1 );
2096	    x.wi( x.wi() - x2.wi() );
2097	    x2.wi( 0 );
2098	}
2099
2100	switch( params.o_mode() )
2101	{
2102            case SC_WRAP:			// wrap-around
2103	    {
2104		int n_bits = params.n_bits();
2105
2106		if( n_bits == 0 )
2107		{
2108		    // wrap-around all 'wl' bits
2109		    toggle_tc();
2110		    o_extend( x, enc );
2111		    toggle_tc();
2112		}
2113		else if( n_bits < params.wl() )
2114		{
2115		    scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits );
2116
2117		    // wrap-around least significant 'wl - n_bits' bits;
2118		    // saturate most significant 'n_bits' bits
2119		    toggle_tc();
2120		    o_set( x, x3, enc, under );
2121		    o_extend( x, enc );
2122		    toggle_tc();
2123		}
2124		else
2125		{
2126		    // saturate all 'wl' bits
2127		    if( under )
2128			o_set_low( x, enc );
2129		    else
2130			o_set_high( x, x2, enc );
2131		}
2132		break;
2133	    }
2134            case SC_SAT:			// saturation
2135	    {
2136		if( under )
2137		    o_set_low( x, enc );
2138		else
2139		    o_set_high( x, x2, enc );
2140		break;
2141	    }
2142            case SC_SAT_SYM:			// symmetrical saturation
2143	    {
2144		if( under )
2145		{
2146		    if( enc == SC_TC_ )
2147			o_set_high( x, x2, SC_TC_, -1 );
2148		    else
2149			o_set_low( x, SC_US_ );
2150		}
2151		else
2152		    o_set_high( x, x2, enc );
2153		break;
2154	    }
2155            case SC_SAT_ZERO:			// saturation to zero
2156	    {
2157		set_zero();
2158		break;
2159	    }
2160            case SC_WRAP_SM:			// sign magnitude wrap-around
2161	    {
2162		SC_ERROR_IF_( enc == SC_US_,
2163			      sc_core::SC_ID_WRAP_SM_NOT_DEFINED_ );
2164
2165		int n_bits = params.n_bits();
2166
2167		if( n_bits == 0 )
2168		{
2169		    scfx_index x4 = calc_indices( params.iwl() );
2170
2171		    if( x4.wi() >= size() )
2172			resize_to( x4.wi() + 1, 1 );
2173
2174		    toggle_tc();
2175		    if( o_bit_at( x4 ) != o_bit_at( x ) )
2176			o_invert( x2 );
2177		    o_extend( x, SC_TC_ );
2178		    toggle_tc();
2179		}
2180		else if( n_bits == 1 )
2181		{
2182		    toggle_tc();
2183		    if( is_neg() != o_bit_at( x ) )
2184			o_invert( x2 );
2185		    o_extend( x, SC_TC_ );
2186		    toggle_tc();
2187		}
2188		else if( n_bits < params.wl() )
2189		{
2190		    scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits );
2191		    scfx_index x4 = calc_indices( params.iwl() - n_bits );
2192
2193		    // wrap-around least significant 'wl - n_bits' bits;
2194		    // saturate most significant 'n_bits' bits
2195		    toggle_tc();
2196		    if( is_neg() == o_bit_at( x4 ) )
2197			o_invert( x2 );
2198		    o_set( x, x3, SC_TC_, under );
2199		    o_extend( x, SC_TC_ );
2200		    toggle_tc();
2201		}
2202		else
2203		{
2204		    if( under )
2205			o_set_low( x, SC_TC_ );
2206		    else
2207			o_set_high( x, x2, SC_TC_ );
2208		}
2209		break;
2210	    }
2211            default:
2212	        ;
2213	}
2214
2215	find_sw();
2216    }
2217}
2218
2219
2220// ----------------------------------------------------------------------------
2221//  PUBLIC METHOD : cast
2222//
2223//  Performs a destructive cast operation on a scfx_rep.
2224// ----------------------------------------------------------------------------
2225
2226void
2227scfx_rep::cast( const scfx_params& params, bool& q_flag, bool& o_flag )
2228{
2229    q_flag = false;
2230    o_flag = false;
2231
2232    // check for special cases
2233
2234    if( is_zero() )
2235    {
2236	if( is_neg() )
2237	    m_sign = 1;
2238	return;
2239    }
2240
2241    // perform casting
2242
2243    quantization( params, q_flag );
2244    overflow( params, o_flag );
2245
2246    // check for special case: -0
2247
2248    if( is_zero() && is_neg() )
2249	m_sign = 1;
2250}
2251
2252
2253// ----------------------------------------------------------------------------
2254//  make sure, the two mantissas are aligned
2255// ----------------------------------------------------------------------------
2256
2257void
2258align( const scfx_rep& lhs, const scfx_rep& rhs, int& new_wp,
2259       int& len_mant, scfx_mant_ref& lhs_mant, scfx_mant_ref& rhs_mant )
2260{
2261    bool need_lhs = true;
2262    bool need_rhs = true;
2263
2264    if( lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size() )
2265    {
2266	int lower_bound_lhs = lhs.m_lsw - lhs.m_wp;
2267	int upper_bound_lhs = lhs.m_msw - lhs.m_wp;
2268	int lower_bound_rhs = rhs.m_lsw - rhs.m_wp;
2269	int upper_bound_rhs = rhs.m_msw - rhs.m_wp;
2270
2271	int lower_bound = sc_min( lower_bound_lhs, lower_bound_rhs );
2272	int upper_bound = sc_max( upper_bound_lhs, upper_bound_rhs );
2273
2274	new_wp   = -lower_bound;
2275	len_mant = sc_max( min_mant, upper_bound - lower_bound + 1 );
2276
2277	if( new_wp != lhs.m_wp || len_mant != lhs.size() )
2278	{
2279	    lhs_mant = lhs.resize( len_mant, new_wp );
2280	    need_lhs = false;
2281	}
2282
2283	if( new_wp != rhs.m_wp || len_mant != rhs.size() )
2284        {
2285	    rhs_mant = rhs.resize( len_mant, new_wp );
2286	    need_rhs = false;
2287	}
2288    }
2289
2290    if( need_lhs )
2291    {
2292	lhs_mant = lhs.m_mant;
2293    }
2294
2295    if( need_rhs )
2296    {
2297	rhs_mant = rhs.m_mant;
2298    }
2299}
2300
2301
2302// ----------------------------------------------------------------------------
2303//  compare two mantissas
2304// ----------------------------------------------------------------------------
2305
2306int
2307compare_msw_ff( const scfx_rep& lhs, const scfx_rep& rhs )
2308{
2309    // special case: rhs.m_mant[rhs.m_msw + 1] == 1
2310    if( rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0 )
2311    {
2312	return -1;
2313    }
2314
2315    int lhs_size = lhs.m_msw - lhs.m_lsw + 1;
2316    int rhs_size = rhs.m_msw - rhs.m_lsw + 1;
2317
2318    int size = sc_min( lhs_size, rhs_size );
2319
2320    int lhs_index = lhs.m_msw;
2321    int rhs_index = rhs.m_msw;
2322
2323    int i;
2324
2325    for( i = 0;
2326	 i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index];
2327	 i ++ )
2328    {
2329	lhs_index --;
2330	rhs_index --;
2331    }
2332
2333    if( i == size )
2334    {
2335	if( lhs_size == rhs_size )
2336	{
2337	    return 0;
2338	}
2339
2340	if( lhs_size < rhs_size )
2341	{
2342	    return -1;
2343	}
2344	else
2345	{
2346	    return 1;
2347	}
2348  }
2349
2350  if( lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index] )
2351  {
2352      return -1;
2353  } else {
2354      return 1;
2355  }
2356}
2357
2358
2359// ----------------------------------------------------------------------------
2360//  divide the mantissa by ten
2361// ----------------------------------------------------------------------------
2362
2363unsigned int
2364scfx_rep::divide_by_ten()
2365{
2366#if defined( SC_BIG_ENDIAN )
2367    half_word* hw = (half_word*) &m_mant[m_msw];
2368#elif defined( SC_LITTLE_ENDIAN )
2369    half_word* hw = ( (half_word*) &m_mant[m_msw] ) + 1;
2370#endif
2371
2372    unsigned int remainder = 0;
2373
2374    word_short ls;
2375    ls.l = 0;
2376
2377#if defined( SC_BIG_ENDIAN )
2378    for( int i = 0, end = ( m_msw - m_wp + 1 ) * 2; i < end; i ++ )
2379#elif defined( SC_LITTLE_ENDIAN )
2380    for( int i = 0, end = -( m_msw - m_wp + 1 ) * 2; i > end; i -- )
2381#endif
2382    {
2383	ls.s.u = static_cast<half_word>( remainder );
2384	ls.s.l = hw[i];
2385	remainder = ls.l % 10;
2386	ls.l /= 10;
2387	hw[i] = ls.s.l;
2388    }
2389
2390    return remainder;
2391}
2392
2393
2394// ----------------------------------------------------------------------------
2395//  multiply the mantissa by ten
2396// ----------------------------------------------------------------------------
2397
2398void
2399scfx_rep::multiply_by_ten()
2400{
2401    int size = m_mant.size() + 1;
2402
2403    scfx_mant mant8( size );
2404    scfx_mant mant2( size );
2405
2406    size --;
2407
2408    mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3));
2409    mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1));
2410
2411    while( -- size )
2412    {
2413	mant8[size] = ( m_mant[size] << 3 ) |
2414	              ( m_mant[size - 1] >> ( bits_in_word - 3 ) );
2415	mant2[size] = ( m_mant[size] << 1 ) |
2416	              ( m_mant[size - 1] >> ( bits_in_word - 1 ) );
2417    }
2418
2419    mant8[0] = ( m_mant[0] << 3 );
2420    mant2[0] = ( m_mant[0] << 1 );
2421
2422    add_mants( m_mant.size(), m_mant, mant8, mant2 );
2423
2424#if 0
2425    for( int i = size() - 1; i > 0; i -- )
2426    {
2427	m_mant[i] = ( m_mant[i] << 3 ) |
2428                    ( m_mant[i-1] >> ( bits_in_word - 3 ) )
2429	          + ( m_mant[i] << 1 ) |
2430                    ( m_mant[i-1] >> ( bits_in_word - 1 ) );
2431    }
2432    m_mant[0] = ( m_mant[0] << 3 ) + ( m_mant[0] << 1 );
2433#endif
2434}
2435
2436
2437// ----------------------------------------------------------------------------
2438//  normalize
2439// ----------------------------------------------------------------------------
2440
2441void
2442scfx_rep::normalize( int exponent )
2443{
2444    int shift = exponent % bits_in_word;
2445    if( shift < 0 )
2446    {
2447	shift += bits_in_word;
2448    }
2449
2450    if( shift )
2451    {
2452	shift_left( shift );
2453    }
2454
2455    find_sw();
2456
2457    m_wp = (shift - exponent) / bits_in_word;
2458}
2459
2460
2461// ----------------------------------------------------------------------------
2462//  return a new mantissa that is aligned and resized
2463// ----------------------------------------------------------------------------
2464
2465scfx_mant*
2466scfx_rep::resize( int new_size, int new_wp ) const
2467{
2468    scfx_mant *result = new scfx_mant( new_size );
2469
2470    result->clear();
2471
2472    int shift = new_wp - m_wp;
2473
2474    for( int j = m_lsw; j <= m_msw; j ++ )
2475    {
2476	(*result)[j+shift] = m_mant[j];
2477    }
2478
2479    return result;
2480}
2481
2482
2483// ----------------------------------------------------------------------------
2484//  set a single bit
2485// ----------------------------------------------------------------------------
2486
2487void
2488scfx_rep::set_bin( int i )
2489{
2490    m_mant[i >> 5] |= 1 << ( i & 31 );
2491}
2492
2493
2494// ----------------------------------------------------------------------------
2495//  set three bits
2496// ----------------------------------------------------------------------------
2497
2498void
2499scfx_rep::set_oct( int i, int n )
2500{
2501    if( n & 1 )
2502    {
2503	m_mant[i >> 5] |= 1 << ( i & 31 );
2504    }
2505    i ++;
2506    if( n & 2 )
2507    {
2508	m_mant[i >> 5] |= 1 << ( i & 31 );
2509    }
2510    i ++;
2511    if( n & 4 )
2512    {
2513	m_mant[i >> 5] |= 1 << ( i & 31 );
2514    }
2515}
2516
2517
2518// ----------------------------------------------------------------------------
2519//  set four bits
2520// ----------------------------------------------------------------------------
2521
2522void
2523scfx_rep::set_hex( int i, int n )
2524{
2525    if( n & 1 )
2526    {
2527	m_mant[i >> 5] |= 1 << ( i & 31 );
2528    }
2529    i ++;
2530    if( n & 2 )
2531    {
2532	m_mant[i >> 5] |= 1 << ( i & 31 );
2533    }
2534    i ++;
2535    if( n & 4 )
2536    {
2537	m_mant[i >> 5] |= 1 << ( i & 31 );
2538    }
2539    i ++;
2540    if( n & 8 )
2541    {
2542	m_mant[i >> 5] |= 1 << ( i & 31 );
2543    }
2544}
2545
2546
2547// ----------------------------------------------------------------------------
2548//  PRIVATE METHOD : shift_left
2549//
2550//  Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits.
2551// ----------------------------------------------------------------------------
2552
2553void
2554scfx_rep::shift_left( int n )
2555{
2556    if( n != 0 )
2557    {
2558	int shift_left  = n;
2559	int shift_right = bits_in_word - n;
2560
2561	SC_ASSERT_( !(m_mant[size()-1] >> shift_right),
2562		    "shift_left overflow" );
2563
2564	for( int i = size() - 1; i > 0; i -- )
2565	{
2566	    m_mant[i] = ( m_mant[i] << shift_left ) |
2567		       ( m_mant[i-1] >> shift_right );
2568	}
2569	m_mant[0] <<= shift_left;
2570    }
2571}
2572
2573
2574// ----------------------------------------------------------------------------
2575//  PRIVATE METHOD : shift_right
2576//
2577//  Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits.
2578// ----------------------------------------------------------------------------
2579
2580void
2581scfx_rep::shift_right( int n )
2582{
2583    if( n != 0 )
2584    {
2585	int shift_left  = bits_in_word - n;
2586	int shift_right = n;
2587
2588	SC_ASSERT_( !(m_mant[0] << shift_left), "shift_right overflow" );
2589
2590	for( int i = 0; i < size() - 1; i ++ )
2591	{
2592	    m_mant[i] = ( m_mant[i] >> shift_right ) |
2593		       ( m_mant[i+1] << shift_left );
2594	}
2595	m_mant[size()-1] >>= shift_right;
2596    }
2597}
2598
2599
2600// ----------------------------------------------------------------------------
2601//  METHOD : get_bit
2602//
2603//  Tests a bit, in two's complement.
2604// ----------------------------------------------------------------------------
2605
2606bool
2607scfx_rep::get_bit( int i ) const
2608{
2609    if( ! is_normal() )
2610	return false;
2611
2612    scfx_index x = calc_indices( i );
2613
2614    if( x.wi() >= size() )
2615	return is_neg();
2616
2617    if( x.wi() < 0 )
2618	return false;
2619
2620    const_cast<scfx_rep*>( this )->toggle_tc();
2621
2622    bool result = ( m_mant[x.wi()] & ( 1 << x.bi() ) ) != 0;
2623
2624    const_cast<scfx_rep*>( this )->toggle_tc();
2625
2626    return result;
2627}
2628
2629
2630// ----------------------------------------------------------------------------
2631//  METHOD : set
2632//
2633//  Sets a bit, in two's complement, between iwl-1 and -fwl.
2634// ----------------------------------------------------------------------------
2635
2636bool
2637scfx_rep::set( int i, const scfx_params& params )
2638{
2639    if( ! is_normal() )
2640	return false;
2641
2642    scfx_index x = calc_indices( i );
2643
2644    if( x.wi() >= size() )
2645    {
2646	if( is_neg() )
2647	    return true;
2648	else
2649	    resize_to( x.wi() + 1, 1 );
2650    }
2651    else if( x.wi() < 0 )
2652    {
2653	resize_to( size() - x.wi(), -1 );
2654	x.wi( 0 );
2655    }
2656
2657    toggle_tc();
2658
2659    m_mant[x.wi()] |= 1 << x.bi();
2660
2661    if( i == params.iwl() - 1 )
2662        o_extend( x, params.enc() );  // sign extension
2663
2664    toggle_tc();
2665
2666    find_sw();
2667
2668    return true;
2669}
2670
2671
2672// ----------------------------------------------------------------------------
2673//  METHOD : clear
2674//
2675//  Clears a bit, in two's complement, between iwl-1 and -fwl.
2676// ----------------------------------------------------------------------------
2677
2678bool
2679scfx_rep::clear( int i, const scfx_params& params )
2680{
2681    if( ! is_normal() )
2682	return false;
2683
2684    scfx_index x = calc_indices( i );
2685
2686    if( x.wi() >= size() )
2687    {
2688	if( ! is_neg() )
2689	    return true;
2690	else
2691	    resize_to( x.wi() + 1, 1 );
2692    }
2693    else if( x.wi() < 0 )
2694	return true;
2695
2696    toggle_tc();
2697
2698    m_mant[x.wi()] &= ~( 1 << x.bi() );
2699
2700    if( i == params.iwl() - 1 )
2701        o_extend( x, params.enc() );  // sign extension
2702
2703    toggle_tc();
2704
2705    find_sw();
2706
2707    return true;
2708}
2709
2710
2711// ----------------------------------------------------------------------------
2712//  METHOD : get_slice
2713// ----------------------------------------------------------------------------
2714
2715bool
2716scfx_rep::get_slice( int i, int j, const scfx_params&,
2717		     sc_bv_base& bv ) const
2718{
2719    if( is_nan() || is_inf() )
2720	return false;
2721
2722    // get the bits
2723
2724    int l = j;
2725    for( int k = 0; k < bv.length(); ++ k )
2726    {
2727	bv[k] = get_bit( l );
2728
2729	if( i >= j )
2730	    ++ l;
2731	else
2732	    -- l;
2733    }
2734
2735    return true;
2736}
2737
2738bool
2739scfx_rep::set_slice( int i, int j, const scfx_params& params,
2740		     const sc_bv_base& bv )
2741{
2742    if( is_nan() || is_inf() )
2743        return false;
2744
2745    // set the bits
2746
2747    int l = j;
2748    for( int k = 0; k < bv.length(); ++ k )
2749    {
2750	if( bv[k].to_bool() )
2751	    set( l, params );
2752	else
2753	    clear( l, params );
2754
2755	if( i >= j )
2756	    ++ l;
2757	else
2758	    -- l;
2759    }
2760
2761    return true;
2762}
2763
2764
2765// ----------------------------------------------------------------------------
2766//  METHOD : print
2767// ----------------------------------------------------------------------------
2768
2769void
2770scfx_rep::print( ::std::ostream& os ) const
2771{
2772    os << to_string( SC_DEC, -1, SC_E );
2773}
2774
2775
2776// ----------------------------------------------------------------------------
2777//  METHOD : dump
2778// ----------------------------------------------------------------------------
2779
2780void
2781scfx_rep::dump( ::std::ostream& os ) const
2782{
2783    os << "scfx_rep" << ::std::endl;
2784    os << "(" << ::std::endl;
2785
2786    os << "mant  =" << ::std::endl;
2787    for( int i = size() - 1; i >= 0; i -- )
2788    {
2789	char buf[BUFSIZ];
2790	std::sprintf( buf, " %d: %10u (%8x)", i, (int) m_mant[i], (int) m_mant[i] );
2791	os << buf << ::std::endl;
2792    }
2793
2794    os << "wp    = " << m_wp << ::std::endl;
2795    os << "sign  = " << m_sign << ::std::endl;
2796
2797    os << "state = ";
2798    switch( m_state )
2799    {
2800        case normal:
2801	    os << "normal";
2802	    break;
2803        case infinity:
2804	    os << "infinity";
2805	    break;
2806        case not_a_number:
2807	    os << "not_a_number";
2808	    break;
2809        default:
2810	    os << "unknown";
2811    }
2812    os << ::std::endl;
2813
2814    os << "msw   = " << m_msw << ::std::endl;
2815    os << "lsw   = " << m_lsw << ::std::endl;
2816
2817    os << ")" << ::std::endl;
2818}
2819
2820
2821// ----------------------------------------------------------------------------
2822//  METHOD : get_type
2823// ----------------------------------------------------------------------------
2824
2825void
2826scfx_rep::get_type( int& wl, int& iwl, sc_enc& enc ) const
2827{
2828    if( is_nan() || is_inf() )
2829    {
2830        wl  = 0;
2831        iwl = 0;
2832        enc = SC_TC_;
2833        return;
2834    }
2835
2836    if( is_zero() )
2837    {
2838        wl  = 1;
2839        iwl = 1;
2840        enc = SC_US_;
2841        return;
2842    }
2843
2844    int msb = ( m_msw - m_wp ) * bits_in_word
2845            + scfx_find_msb( m_mant[ m_msw ] ) + 1;
2846    while( get_bit( msb ) == get_bit( msb - 1 ) )
2847    {
2848        -- msb;
2849    }
2850
2851    int lsb = ( m_lsw - m_wp ) * bits_in_word
2852            + scfx_find_lsb( m_mant[ m_lsw ] );
2853
2854    if( is_neg() )
2855    {
2856        wl  = msb - lsb + 1;
2857        iwl = msb + 1;
2858        enc = SC_TC_;
2859    }
2860    else
2861    {
2862        wl  = msb - lsb;
2863        iwl = msb;
2864        enc = SC_US_;
2865    }
2866}
2867
2868
2869// ----------------------------------------------------------------------------
2870//  PRIVATE METHOD : round
2871//
2872//  Performs convergent rounding (rounding to even) as in floating-point.
2873// ----------------------------------------------------------------------------
2874
2875void
2876scfx_rep::round( int wl )
2877{
2878    // check for special cases
2879
2880    if( is_nan() || is_inf() || is_zero() )
2881	return;
2882
2883    // estimate effective wordlength and compare
2884
2885    int wl_effective;
2886
2887    wl_effective = ( m_msw - m_lsw + 1 ) * bits_in_word;
2888    if( wl_effective <= wl )
2889	return;
2890
2891    // calculate effective wordlength and compare
2892
2893    int msb = scfx_find_msb( m_mant[m_msw] );
2894    int lsb = scfx_find_lsb( m_mant[m_lsw] );
2895
2896    wl_effective = ( m_msw * bits_in_word + msb ) -
2897	           ( m_lsw * bits_in_word + lsb ) + 1;
2898    if( wl_effective <= wl )
2899	return;
2900
2901    // perform rounding
2902
2903    int wi = m_msw - ( wl - 1 ) / bits_in_word;
2904    int bi =  msb - ( wl - 1 ) % bits_in_word;
2905    if( bi < 0 )
2906    {
2907	-- wi;
2908	bi += bits_in_word;
2909    }
2910
2911    scfx_index x( wi, bi );
2912
2913    if( (q_bit( x ) && ! q_zero( x )) ||
2914	(q_bit( x ) && q_zero( x ) && q_odd( x )) )
2915	q_incr( x );
2916    q_clear( x );
2917
2918    find_sw();
2919
2920    m_r_flag = true;
2921}
2922
2923} // namespace sc_dt
2924
2925
2926// Taf!
2927