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  sc_fxnum.cpp -
23
24  Original Author: Martin Janssen, Synopsys, Inc.
25
26 *****************************************************************************/
27
28/*****************************************************************************
29
30  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
31  changes you are making here.
32
33      Name, Affiliation, Date:
34  Description of Modification:
35
36 *****************************************************************************/
37
38
39// $Log: sc_fxnum.cpp,v $
40// Revision 1.3  2011/01/19 18:57:40  acg
41//  Andy Goodrich: changes for IEEE_1666_2011.
42//
43// Revision 1.2  2010/12/07 20:09:08  acg
44// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix
45//
46// Revision 1.1.1.1  2006/12/15 20:20:04  acg
47// SystemC 2.3
48//
49// Revision 1.3  2006/01/13 18:53:57  acg
50// Andy Goodrich: added $Log command so that CVS comments are reproduced in
51// the source.
52//
53
54#include <math.h>
55
56#include "sysc/datatypes/fx/sc_fxnum.h"
57
58
59namespace sc_dt
60{
61
62// ----------------------------------------------------------------------------
63//  CLASS : sc_fxnum_bitref
64//
65//  Proxy class for bit-selection in class sc_fxnum, behaves like sc_bit.
66// ----------------------------------------------------------------------------
67
68bool
69sc_fxnum_bitref::get() const
70{
71    return m_num.get_bit( m_idx );
72}
73
74void
75sc_fxnum_bitref::set( bool high )
76{
77    m_num.set_bit( m_idx, high );
78}
79
80
81// print or dump content
82
83void
84sc_fxnum_bitref::print( ::std::ostream& os ) const
85{
86    os << get();
87}
88
89void
90sc_fxnum_bitref::scan( ::std::istream& is )
91{
92    bool b;
93    is >> b;
94    *this = b;
95}
96
97void
98sc_fxnum_bitref::dump( ::std::ostream& os ) const
99{
100    os << "sc_fxnum_bitref" << ::std::endl;
101    os << "(" << ::std::endl;
102    os << "num = ";
103    m_num.dump( os );
104    os << "idx = " << m_idx << ::std::endl;
105    os << ")" << ::std::endl;
106}
107
108
109// ----------------------------------------------------------------------------
110//  CLASS : sc_fxnum_fast_bitref
111//
112//  Proxy class for bit-selection in class sc_fxnum_fast, behaves like sc_bit.
113// ----------------------------------------------------------------------------
114
115bool
116sc_fxnum_fast_bitref::get() const
117{
118    return m_num.get_bit( m_idx );
119}
120
121void
122sc_fxnum_fast_bitref::set( bool high )
123{
124    m_num.set_bit( m_idx, high );
125}
126
127
128// print or dump content
129
130void
131sc_fxnum_fast_bitref::print( ::std::ostream& os ) const
132{
133    os << get();
134}
135
136void
137sc_fxnum_fast_bitref::scan( ::std::istream& is )
138{
139    bool b;
140    is >> b;
141    *this = b;
142}
143
144void
145sc_fxnum_fast_bitref::dump( ::std::ostream& os ) const
146{
147    os << "sc_fxnum_fast_bitref" << ::std::endl;
148    os << "(" << ::std::endl;
149    os << "num = ";
150    m_num.dump( os );
151    os << "idx = " << m_idx << ::std::endl;
152    os << ")" << ::std::endl;
153}
154
155
156// ----------------------------------------------------------------------------
157//  CLASS : sc_fxnum_subref
158//
159//  Proxy class for part-selection in class sc_fxnum,
160//  behaves like sc_bv_base.
161// ----------------------------------------------------------------------------
162
163bool
164sc_fxnum_subref::get() const
165{
166    return m_num.get_slice( m_from, m_to, m_bv );
167}
168
169bool
170sc_fxnum_subref::set()
171{
172    return m_num.set_slice( m_from, m_to, m_bv );
173}
174
175
176// print or dump content
177
178void
179sc_fxnum_subref::print( ::std::ostream& os ) const
180{
181    get();
182    m_bv.print( os );
183}
184
185void
186sc_fxnum_subref::scan( ::std::istream& is )
187{
188    m_bv.scan( is );
189    set();
190}
191
192void
193sc_fxnum_subref::dump( ::std::ostream& os ) const
194{
195    os << "sc_fxnum_subref" << ::std::endl;
196    os << "(" << ::std::endl;
197    os << "num  = ";
198    m_num.dump( os );
199    os << "from = " << m_from << ::std::endl;
200    os << "to   = " << m_to << ::std::endl;
201    os << ")" << ::std::endl;
202}
203
204
205// ----------------------------------------------------------------------------
206//  CLASS : sc_fxnum_fast_subref
207//
208//  Proxy class for part-selection in class sc_fxnum_fast,
209//  behaves like sc_bv_base.
210// ----------------------------------------------------------------------------
211
212bool
213sc_fxnum_fast_subref::get() const
214{
215    return m_num.get_slice( m_from, m_to, m_bv );
216}
217
218bool
219sc_fxnum_fast_subref::set()
220{
221    return m_num.set_slice( m_from, m_to, m_bv );
222}
223
224
225// print or dump content
226
227void
228sc_fxnum_fast_subref::print( ::std::ostream& os ) const
229{
230    get();
231    m_bv.print( os );
232}
233
234void
235sc_fxnum_fast_subref::scan( ::std::istream& is )
236{
237    m_bv.scan( is );
238    set();
239}
240
241void
242sc_fxnum_fast_subref::dump( ::std::ostream& os ) const
243{
244    os << "sc_fxnum_fast_subref" << ::std::endl;
245    os << "(" << ::std::endl;
246    os << "num  = ";
247    m_num.dump( os );
248    os << "from = " << m_from << ::std::endl;
249    os << "to   = " << m_to << ::std::endl;
250    os << ")" << ::std::endl;
251}
252
253
254// ----------------------------------------------------------------------------
255//  CLASS : sc_fxnum
256//
257//  Base class for the fixed-point types; arbitrary precision.
258// ----------------------------------------------------------------------------
259
260// explicit conversion to character string
261
262const std::string
263sc_fxnum::to_string() const
264{
265    return std::string( m_rep->to_string( SC_DEC, -1, SC_F, &m_params ) );
266}
267
268const std::string
269sc_fxnum::to_string( sc_numrep numrep ) const
270{
271    return std::string( m_rep->to_string( numrep, -1, SC_F, &m_params ) );
272}
273
274const std::string
275sc_fxnum::to_string( sc_numrep numrep, bool w_prefix ) const
276{
277    return std::string( m_rep->to_string( numrep, (w_prefix ? 1 : 0),
278					SC_F, &m_params ) );
279}
280
281const std::string
282sc_fxnum::to_string( sc_fmt fmt ) const
283{
284    return std::string( m_rep->to_string( SC_DEC, -1, fmt, &m_params ) );
285}
286
287const std::string
288sc_fxnum::to_string( sc_numrep numrep, sc_fmt fmt ) const
289{
290    return std::string( m_rep->to_string( numrep, -1, fmt, &m_params ) );
291}
292
293const std::string
294sc_fxnum::to_string( sc_numrep numrep, bool w_prefix, sc_fmt fmt ) const
295{
296    return std::string( m_rep->to_string( numrep, (w_prefix ? 1 : 0),
297					fmt, &m_params ) );
298}
299
300
301const std::string
302sc_fxnum::to_dec() const
303{
304    return std::string( m_rep->to_string( SC_DEC, -1, SC_F, &m_params ) );
305}
306
307const std::string
308sc_fxnum::to_bin() const
309{
310    return std::string( m_rep->to_string( SC_BIN, -1, SC_F, &m_params ) );
311}
312
313const std::string
314sc_fxnum::to_oct() const
315{
316    return std::string( m_rep->to_string( SC_OCT, -1, SC_F, &m_params ) );
317}
318
319const std::string
320sc_fxnum::to_hex() const
321{
322    return std::string( m_rep->to_string( SC_HEX, -1, SC_F, &m_params ) );
323}
324
325
326// print or dump content
327
328void
329sc_fxnum::print( ::std::ostream& os ) const
330{
331    os << m_rep->to_string( SC_DEC, -1, SC_F, &m_params );
332}
333
334void
335sc_fxnum::scan( ::std::istream& is )
336{
337    std::string s;
338    is >> s;
339    *this = s.c_str();
340}
341
342void
343sc_fxnum::dump( ::std::ostream& os ) const
344{
345    os << "sc_fxnum" << ::std::endl;
346    os << "(" << ::std::endl;
347    os << "rep      = ";
348    m_rep->dump( os );
349    os << "params   = ";
350    m_params.dump( os );
351    os << "q_flag   = " << m_q_flag << ::std::endl;
352    os << "o_flag   = " << m_o_flag << ::std::endl;
353    // TO BE COMPLETED
354    // os << "observer = ";
355    // if( m_observer != 0 )
356    //     m_observer->dump( os );
357    // else
358    //     os << "0" << ::std::endl;
359    os << ")" << ::std::endl;
360}
361
362
363sc_fxnum_observer*
364sc_fxnum::lock_observer() const
365{
366    SC_ASSERT_( m_observer != 0, "lock observer failed" );
367    sc_fxnum_observer* tmp = m_observer;
368    m_observer = 0;
369    return tmp;
370}
371
372void
373sc_fxnum::unlock_observer( sc_fxnum_observer* observer_ ) const
374{
375    SC_ASSERT_( observer_ != 0, "unlock observer failed" );
376    m_observer = observer_;
377}
378
379
380// ----------------------------------------------------------------------------
381//  CLASS : sc_fxnum_fast
382//
383//  Base class for the fixed-point types; limited precision.
384// ----------------------------------------------------------------------------
385
386static
387void
388quantization( double& c, const scfx_params& params, bool& q_flag )
389{
390    int fwl = params.wl() - params.iwl();
391    double scale = scfx_pow2( fwl );
392    double val = scale * c;
393    double int_part;
394    double frac_part = modf( val, &int_part );
395
396    q_flag = ( frac_part != 0.0 );
397
398    if( q_flag )
399    {
400        val = int_part;
401
402	switch( params.q_mode() )
403	{
404            case SC_TRN:			// truncation
405	    {
406	        if( c < 0.0 )
407		    val -= 1.0;
408		break;
409	    }
410            case SC_RND:			// rounding to plus infinity
411	    {
412		if( frac_part >= 0.5 )
413		    val += 1.0;
414		else if( frac_part < -0.5 )
415		    val -= 1.0;
416		break;
417	    }
418            case SC_TRN_ZERO:			// truncation to zero
419	    {
420	        break;
421	    }
422            case SC_RND_INF:			// rounding to infinity
423	    {
424		if( frac_part >= 0.5 )
425		    val += 1.0;
426		else if( frac_part <= -0.5 )
427		    val -= 1.0;
428		break;
429	    }
430            case SC_RND_CONV:			// convergent rounding
431	    {
432		if( frac_part > 0.5 ||
433		    ( frac_part == 0.5 && fmod( int_part, 2.0 ) != 0.0 ) )
434		    val += 1.0;
435		else if( frac_part < -0.5 ||
436			 ( frac_part == -0.5 && fmod( int_part, 2.0 ) != 0.0 ) )
437		    val -= 1.0;
438		break;
439	    }
440            case SC_RND_ZERO:			// rounding to zero
441	    {
442		if( frac_part > 0.5 )
443		    val += 1.0;
444		else if( frac_part < -0.5 )
445		    val -= 1.0;
446		break;
447	    }
448            case SC_RND_MIN_INF:		// rounding to minus infinity
449	    {
450		if( frac_part > 0.5 )
451		    val += 1.0;
452		else if( frac_part <= -0.5 )
453		    val -= 1.0;
454		break;
455	    }
456            default:
457	        ;
458	}
459    }
460
461    val /= scale;
462    c = val;
463}
464
465static
466void
467overflow( double& c, const scfx_params& params, bool& o_flag )
468{
469    int iwl = params.iwl();
470    int fwl = params.wl() - iwl;
471    double full_circle = scfx_pow2( iwl );
472    double resolution = scfx_pow2( -fwl );
473    double low, high;
474    if( params.enc() == SC_TC_ )
475    {
476	high = full_circle / 2.0 - resolution;
477	if( params.o_mode() == SC_SAT_SYM )
478	    low = - high;
479	else
480	    low = - full_circle / 2.0;
481    }
482    else
483    {
484	low = 0.0;
485	high = full_circle - resolution;
486    }
487    double val = c;
488    sc_fxval_fast c2(c);
489
490    bool under = ( val < low );
491    bool over = ( val > high );
492
493    o_flag = ( under || over );
494
495    if( o_flag )
496    {
497        switch( params.o_mode() )
498	{
499            case SC_WRAP:			// wrap-around
500	    {
501		int n_bits = params.n_bits();
502
503	        if( n_bits == 0 )
504		{
505		    // wrap-around all 'wl' bits
506		    val -= floor( val / full_circle ) * full_circle;
507		    if( val > high )
508			val -= full_circle;
509		}
510		else if( n_bits < params.wl() )
511		{
512		    double X = scfx_pow2( iwl - n_bits );
513
514		    // wrap-around least significant 'wl - n_bits' bits
515		    val -= floor( val / X ) * X;
516		    if( val > ( X - resolution ) )
517			val -= X;
518
519		    // saturate most significant 'n_bits' bits
520		    if( under )
521		        val += low;
522		    else
523		    {
524		        if( params.enc() == SC_TC_ )
525			    val += full_circle / 2.0 - X;
526			else
527			    val += full_circle - X;
528		    }
529		}
530		else
531		{
532		    // saturate all 'wl' bits
533		    if( under )
534			val = low;
535		    else
536			val = high;
537		}
538		break;
539	    }
540            case SC_SAT:			// saturation
541            case SC_SAT_SYM:			// symmetrical saturation
542	    {
543	        if( under )
544		    val = low;
545		else
546		    val = high;
547		break;
548	    }
549            case SC_SAT_ZERO:			// saturation to zero
550	    {
551	        val = 0.0;
552		break;
553	    }
554            case SC_WRAP_SM:			// sign magnitude wrap-around
555	    {
556		SC_ERROR_IF_( params.enc() == SC_US_,
557			      sc_core::SC_ID_WRAP_SM_NOT_DEFINED_ );
558
559		int n_bits = params.n_bits();
560
561		if( n_bits == 0 )
562		{
563		    // invert conditionally
564		    if( c2.get_bit( iwl ) != c2.get_bit( iwl - 1 ) )
565			val = -val - resolution;
566
567		    // wrap-around all 'wl' bits
568		    val -= floor( val / full_circle ) * full_circle;
569		    if( val > high )
570			val -= full_circle;
571		}
572		else if( n_bits == 1 )
573		{
574		    // invert conditionally
575		    if( c2.is_neg() != c2.get_bit( iwl - 1 ) )
576			val = -val - resolution;
577
578		    // wrap-around all 'wl' bits
579		    val -= floor( val / full_circle ) * full_circle;
580		    if( val > high )
581			val -= full_circle;
582		}
583		else if( n_bits < params.wl() )
584		{
585		    // invert conditionally
586		    if( c2.is_neg() == c2.get_bit( iwl - n_bits ) )
587			val = -val - resolution;
588
589		    double X = scfx_pow2( iwl - n_bits );
590
591		    // wrap-around least significant 'wl - n_bits' bits
592		    val -= floor( val / X ) * X;
593		    if( val > ( X - resolution ) )
594			val -= X;
595
596		    // saturate most significant 'n_bits' bits
597		    if( under )
598		        val += low;
599		    else
600			val += full_circle / 2.0 - X;
601		} else {
602		    // saturate all 'wl' bits
603		    if( under )
604			val = low;
605		    else
606			val = high;
607		}
608	        break;
609	    }
610            default:
611	        ;
612	}
613
614	c = val;
615    }
616}
617
618
619void
620sc_fxnum_fast::cast()
621{
622    scfx_ieee_double id( m_val );
623    SC_ERROR_IF_( id.is_nan() || id.is_inf(), sc_core::SC_ID_INVALID_FX_VALUE_);
624
625    if( m_params.cast_switch() == SC_ON )
626    {
627        m_q_flag = false;
628	m_o_flag = false;
629
630	// check for special cases
631
632	if( id.is_zero() )
633	{
634	    if( id.negative() != 0 )
635	        m_val = -m_val;
636	    return;
637	}
638
639	// perform casting
640
641	sc_dt::quantization( m_val, m_params, m_q_flag );
642	sc_dt::overflow( m_val, m_params, m_o_flag );
643
644	// check for special case: -0
645
646	id = m_val;
647	if( id.is_zero() && id.negative() != 0 ) {
648	    m_val = -m_val;
649	}
650
651	// check for special case: NaN of Inf
652
653	if( id.is_nan() || id.is_inf() ) {
654	    m_val = 0.0;
655	}
656    }
657}
658
659
660// defined in sc_fxval.cpp;
661extern
662const char*
663to_string( const scfx_ieee_double&,
664	   sc_numrep,
665	   int,
666	   sc_fmt,
667	   const scfx_params* = 0 );
668
669
670// explicit conversion to character string
671
672const std::string
673sc_fxnum_fast::to_string() const
674{
675    return std::string( sc_dt::to_string( m_val, SC_DEC, -1, SC_F, &m_params ) );
676}
677
678const std::string
679sc_fxnum_fast::to_string( sc_numrep numrep ) const
680{
681    return std::string( sc_dt::to_string( m_val, numrep, -1, SC_F, &m_params ) );
682}
683
684const std::string
685sc_fxnum_fast::to_string( sc_numrep numrep, bool w_prefix ) const
686{
687    return std::string( sc_dt::to_string( m_val, numrep, (w_prefix ? 1 : 0),
688					SC_F, &m_params ) );
689}
690
691const std::string
692sc_fxnum_fast::to_string( sc_fmt fmt ) const
693{
694    return std::string( sc_dt::to_string( m_val, SC_DEC, -1, fmt, &m_params ) );
695}
696
697const std::string
698sc_fxnum_fast::to_string( sc_numrep numrep, sc_fmt fmt ) const
699{
700    return std::string( sc_dt::to_string( m_val, numrep, -1, fmt, &m_params ) );
701}
702
703const std::string
704sc_fxnum_fast::to_string( sc_numrep numrep, bool w_prefix, sc_fmt fmt ) const
705{
706    return std::string( sc_dt::to_string( m_val, numrep, (w_prefix ? 1 : 0),
707					fmt, &m_params ) );
708}
709
710
711const std::string
712sc_fxnum_fast::to_dec() const
713{
714    return std::string( sc_dt::to_string( m_val, SC_DEC, -1, SC_F, &m_params ) );
715}
716
717const std::string
718sc_fxnum_fast::to_bin() const
719{
720    return std::string( sc_dt::to_string( m_val, SC_BIN, -1, SC_F, &m_params ) );
721}
722
723const std::string
724sc_fxnum_fast::to_oct() const
725{
726    return std::string( sc_dt::to_string( m_val, SC_OCT, -1, SC_F, &m_params ) );
727}
728
729const std::string
730sc_fxnum_fast::to_hex() const
731{
732    return std::string( sc_dt::to_string( m_val, SC_HEX, -1, SC_F, &m_params ) );
733}
734
735
736// print or dump content
737
738void
739sc_fxnum_fast::print( ::std::ostream& os ) const
740{
741    os << sc_dt::to_string( m_val, SC_DEC, -1, SC_F, &m_params );
742}
743
744void
745sc_fxnum_fast::scan( ::std::istream& is )
746{
747    std::string s;
748    is >> s;
749    *this = s.c_str();
750}
751
752void
753sc_fxnum_fast::dump( ::std::ostream& os ) const
754{
755    os << "sc_fxnum_fast" << ::std::endl;
756    os << "(" << ::std::endl;
757    os << "val      = " << m_val << ::std::endl;
758    os << "params   = ";
759    m_params.dump( os );
760    os << "q_flag   = " << m_q_flag << ::std::endl;
761    os << "o_flag   = " << m_o_flag << ::std::endl;
762    // TO BE COMPLETED
763    // os << "observer = ";
764    // if( m_observer != 0 )
765    //     m_observer->dump( os );
766    // else
767    //     os << "0" << ::std::endl;
768    os << ")" << ::std::endl;
769}
770
771
772// internal use only;
773bool
774sc_fxnum_fast::get_bit( int i ) const
775{
776    scfx_ieee_double id( m_val );
777    if( id.is_zero() || id.is_nan() || id.is_inf() )
778        return false;
779
780    // convert to two's complement
781
782    unsigned int m0 = id.mantissa0();
783    unsigned int m1 = id.mantissa1();
784
785    if( id.is_normal() )
786        m0 += 1U << 20;
787
788    if( id.negative() != 0 )
789    {
790	m0 = ~ m0;
791	m1 = ~ m1;
792	unsigned int tmp = m1;
793	m1 += 1U;
794	if( m1 <= tmp )
795	    m0 += 1U;
796    }
797
798    // get the right bit
799
800    int j = i - id.exponent();
801    if( ( j += 20 ) >= 32 )
802        return ( ( m0 & 1U << 31 ) != 0 );
803    else if( j >= 0 )
804        return ( ( m0 & 1U << j ) != 0 );
805    else if( ( j += 32 ) >= 0 )
806        return ( ( m1 & 1U << j ) != 0 );
807    else
808        return false;
809}
810
811
812bool
813sc_fxnum_fast::set_bit( int i, bool high )
814{
815    scfx_ieee_double id( m_val );
816    if( id.is_nan() || id.is_inf() )
817        return false;
818
819    if( high )
820    {
821	if( get_bit( i ) )
822	    return true;
823
824	if( m_params.enc() == SC_TC_ && i == m_params.iwl() - 1 )
825	    m_val -= scfx_pow2( i );
826	else
827	    m_val += scfx_pow2( i );
828    }
829    else
830    {
831	if( ! get_bit( i ) )
832	    return true;
833
834	if( m_params.enc() == SC_TC_ && i == m_params.iwl() - 1 )
835	    m_val += scfx_pow2( i );
836	else
837	    m_val -= scfx_pow2( i );
838    }
839
840    return true;
841}
842
843
844bool
845sc_fxnum_fast::get_slice( int i, int j, sc_bv_base& bv ) const
846{
847    scfx_ieee_double id( m_val );
848    if( id.is_nan() || id.is_inf() )
849	return false;
850
851    // convert to two's complement
852
853    unsigned int m0 = id.mantissa0();
854    unsigned int m1 = id.mantissa1();
855
856    if( id.is_normal() )
857        m0 += 1U << 20;
858
859    if( id.negative() != 0 )
860    {
861	m0 = ~ m0;
862	m1 = ~ m1;
863	unsigned int tmp = m1;
864	m1 += 1U;
865	if( m1 <= tmp )
866	    m0 += 1U;
867    }
868
869    // get the bits
870
871    int l = j;
872    for( int k = 0; k < bv.length(); ++ k )
873    {
874	bool b = false;
875
876        int n = l - id.exponent();
877        if( ( n += 20 ) >= 32 )
878	    b = ( ( m0 & 1U << 31 ) != 0 );
879	else if( n >= 0 )
880	    b = ( ( m0 & 1U << n ) != 0 );
881	else if( ( n += 32 ) >= 0 )
882	    b = ( ( m1 & 1U << n ) != 0 );
883
884	bv[k] = b;
885
886	if( i >= j )
887	    ++ l;
888	else
889	    -- l;
890    }
891
892    return true;
893}
894
895bool
896sc_fxnum_fast::set_slice( int i, int j, const sc_bv_base& bv )
897{
898    scfx_ieee_double id( m_val );
899    if( id.is_nan() || id.is_inf() )
900        return false;
901
902    // set the bits
903
904    int l = j;
905    for( int k = 0; k < bv.length(); ++ k )
906    {
907	if( bv[k].to_bool() )
908	{
909	    if( ! get_bit( l ) )
910	    {
911		if( m_params.enc() == SC_TC_ && l == m_params.iwl() - 1 )
912		    m_val -= scfx_pow2( l );
913		else
914		    m_val += scfx_pow2( l );
915	    }
916	}
917	else
918	{
919	    if( get_bit( l ) )
920	    {
921		if( m_params.enc() == SC_TC_ && l == m_params.iwl() - 1 )
922		    m_val += scfx_pow2( l );
923		else
924		    m_val -= scfx_pow2( l );
925	    }
926	}
927
928
929	if( i >= j )
930	    ++ l;
931	else
932	    -- l;
933    }
934
935    return true;
936}
937
938
939sc_fxnum_fast_observer*
940sc_fxnum_fast::lock_observer() const
941{
942    SC_ASSERT_( m_observer != 0, "lock observer failed" );
943    sc_fxnum_fast_observer* tmp = m_observer;
944    m_observer = 0;
945    return tmp;
946}
947
948void
949sc_fxnum_fast::unlock_observer( sc_fxnum_fast_observer* observer_ ) const
950{
951    SC_ASSERT_( observer_ != 0, "unlock observer failed" );
952    m_observer = observer_;
953}
954
955} // namespace sc_dt
956
957
958// Taf!
959