1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22  scfx_rep.cpp -
23
24  Original Author: Robert Graulich, Synopsys, Inc.
25                   Martin Janssen,  Synopsys, Inc.
26
27 *****************************************************************************/
28
29/*****************************************************************************
30
31  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
32  changes you are making here.
33
34      Name, Affiliation, Date:
35  Description of Modification:
36
37 *****************************************************************************/
38
39
40// $Log: scfx_rep.cpp,v $
41// Revision 1.4  2011/08/24 22:05:43  acg
42//  Torsten Maehne: initialization changes to remove warnings.
43//
44// Revision 1.3  2011/08/15 16:43:24  acg
45//  Torsten Maehne: changes to remove unused argument warnings.
46//
47// Revision 1.2  2009/02/28 00:26:20  acg
48//  Andy Goodrich: bug fixes.
49//
50// Revision 1.2  2008/11/06 17:22:47  acg
51//  Andy Goodrich: bug fixes for 2.2.1.
52//
53// Revision 1.1.1.1  2006/12/15 20:31:36  acg
54// SystemC 2.2
55//
56// Revision 1.3  2006/01/13 18:53:58  acg
57// Andy Goodrich: added $Log command so that CVS comments are reproduced in
58// the source.
59//
60
61#include "sysc/utils/sc_machine.h"
62#include "sysc/datatypes/fx/scfx_rep.h"
63
64#include "sysc/datatypes/fx/scfx_ieee.h"
65#include "sysc/datatypes/fx/scfx_pow10.h"
66#include "sysc/datatypes/fx/scfx_utils.h"
67
68#include "sysc/datatypes/bit/sc_bv_base.h"
69
70#include <ctype.h>
71#include <cstdio>
72#include <stdlib.h>
73#include <math.h>
74
75
76namespace sc_dt
77{
78
79// ----------------------------------------------------------------------------
80//  some utilities
81// ----------------------------------------------------------------------------
82
83static scfx_pow10 pow10_fx;
84
85static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int;
86
87static inline
88int
89n_word( int x )
90{
91    return ( x + bits_in_word - 1 ) / bits_in_word;
92}
93
94
95// ----------------------------------------------------------------------------
96//  CONSTRUCTORS
97// ----------------------------------------------------------------------------
98
99scfx_rep::scfx_rep()
100: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
101  m_r_flag( false )
102{
103    set_zero();
104}
105
106scfx_rep::scfx_rep( int a )
107: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
108  m_r_flag( false )
109{
110    if( a != 0 )
111    {
112        m_mant.clear();
113	m_wp = m_msw = m_lsw = 2;
114	m_state = normal;
115	if( a > 0 )
116	{
117	    m_mant[2] = a;
118	    m_sign = 1;
119	}
120	else
121	{
122	    m_mant[2] = -a;
123	    m_sign = -1;
124	}
125    }
126    else
127        set_zero();
128}
129
130scfx_rep::scfx_rep( unsigned int a )
131: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
132  m_r_flag( false )
133{
134    if( a != 0 )
135    {
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