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_fxval.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_fxval.cpp,v $
40 // Revision 1.1.1.1  2006/12/15 20:20:04  acg
41 // SystemC 2.3
42 //
43 // Revision 1.3  2006/01/13 18:53:58  acg
44 // Andy Goodrich: added $Log command so that CVS comments are reproduced in
45 // the source.
46 //
47 
48 #include <cctype>
49 #include <cstdlib>
50 #include <cmath>
51 #include <cfloat>
52 
53 #include "sysc/datatypes/fx/sc_fxval.h"
54 
55 
56 namespace sc_dt
57 {
58 
59 // ----------------------------------------------------------------------------
60 //  CLASS : sc_fxval
61 //
62 //  Fixed-point value type; arbitrary precision.
63 // ----------------------------------------------------------------------------
64 
65 // explicit conversion to character string
66 
67 const std::string
to_string() const68 sc_fxval::to_string() const
69 {
70     return std::string( m_rep->to_string( SC_DEC, -1, SC_E ) );
71 }
72 
73 const std::string
to_string(sc_numrep numrep) const74 sc_fxval::to_string( sc_numrep numrep ) const
75 {
76     return std::string( m_rep->to_string( numrep, -1, SC_E ) );
77 }
78 
79 const std::string
to_string(sc_numrep numrep,bool w_prefix) const80 sc_fxval::to_string( sc_numrep numrep, bool w_prefix ) const
81 {
82     return std::string( m_rep->to_string( numrep, (w_prefix ? 1 : 0), SC_E ) );
83 }
84 
85 const std::string
to_string(sc_fmt fmt) const86 sc_fxval::to_string( sc_fmt fmt ) const
87 {
88     return std::string( m_rep->to_string( SC_DEC, -1, fmt ) );
89 }
90 
91 const std::string
to_string(sc_numrep numrep,sc_fmt fmt) const92 sc_fxval::to_string( sc_numrep numrep, sc_fmt fmt ) const
93 {
94     return std::string( m_rep->to_string( numrep, -1, fmt ) );
95 }
96 
97 const std::string
to_string(sc_numrep numrep,bool w_prefix,sc_fmt fmt) const98 sc_fxval::to_string( sc_numrep numrep, bool w_prefix, sc_fmt fmt ) const
99 {
100     return std::string( m_rep->to_string( numrep, (w_prefix ? 1 : 0), fmt ) );
101 }
102 
103 
104 const std::string
to_dec() const105 sc_fxval::to_dec() const
106 {
107     return std::string( m_rep->to_string( SC_DEC, -1, SC_E ) );
108 }
109 
110 const std::string
to_bin() const111 sc_fxval::to_bin() const
112 {
113     return std::string( m_rep->to_string( SC_BIN, -1, SC_E ) );
114 }
115 
116 const std::string
to_oct() const117 sc_fxval::to_oct() const
118 {
119     return std::string( m_rep->to_string( SC_OCT, -1, SC_E ) );
120 }
121 
122 const std::string
to_hex() const123 sc_fxval::to_hex() const
124 {
125     return std::string( m_rep->to_string( SC_HEX, -1, SC_E ) );
126 }
127 
128 
129 // print or dump content
130 
131 void
print(::std::ostream & os) const132 sc_fxval::print( ::std::ostream& os ) const
133 {
134     m_rep->print( os );
135 }
136 
137 void
scan(::std::istream & is)138 sc_fxval::scan( ::std::istream& is )
139 {
140     std::string s;
141     is >> s;
142     *this = s.c_str();
143 }
144 
145 void
dump(::std::ostream & os) const146 sc_fxval::dump( ::std::ostream& os ) const
147 {
148     os << "sc_fxval" << ::std::endl;
149     os << "(" << ::std::endl;
150     os << "rep = ";
151     m_rep->dump( os );
152     // TO BE COMPLETED
153     // os << "r_flag   = " << m_r_flag << ::std::endl;
154     // os << "observer = ";
155     // if( m_observer != 0 )
156     //     m_observer->dump( os );
157     // else
158     //     os << "0" << ::std::endl;
159     os << ")" << ::std::endl;
160 }
161 
162 
163 // protected methods and friend functions
164 
165 sc_fxval_observer*
lock_observer() const166 sc_fxval::lock_observer() const
167 {
168     SC_ASSERT_( m_observer != 0, "lock observer failed" );
169     sc_fxval_observer* tmp = m_observer;
170     m_observer = 0;
171     return tmp;
172 }
173 
174 void
unlock_observer(sc_fxval_observer * observer_) const175 sc_fxval::unlock_observer( sc_fxval_observer* observer_ ) const
176 {
177     SC_ASSERT_( observer_ != 0, "unlock observer failed" );
178     m_observer = observer_;
179 }
180 
181 
182 // ----------------------------------------------------------------------------
183 //  CLASS : sc_fxval_fast
184 //
185 //  Fixed-point value types; limited precision.
186 // ----------------------------------------------------------------------------
187 
188 static
189 void
print_dec(scfx_string & s,scfx_ieee_double id,int w_prefix,sc_fmt fmt)190 print_dec( scfx_string& s, scfx_ieee_double id, int w_prefix, sc_fmt fmt )
191 {
192     if( id.negative() != 0 )
193     {
194 	id.negative( 0 );
195 	s += '-';
196     }
197 
198     if( w_prefix == 1 ) {
199 	scfx_print_prefix( s, SC_DEC );
200     }
201 
202     if( id.is_zero() )
203     {
204 	s += '0';
205 	return;
206     }
207 
208     // split 'id' into its integer and fractional part
209 
210     double int_part;
211     double frac_part = std::modf( static_cast<double>( id ), &int_part );
212 
213     int i;
214 
215     // print integer part
216 
217     int int_digits = 0;
218     int int_zeros  = 0;
219 
220     if( int_part != 0.0 )
221     {
222 	int_digits = (int) std::ceil( std::log10( int_part + 1.0 ) );
223 
224 	int len = s.length();
225 	s.append( int_digits );
226 
227 	bool zero_digits = ( frac_part == 0.0 && fmt != SC_F );
228 
229 	for( i = int_digits + len - 1; i >= len; i-- )
230 	{
231 	    unsigned int remainder = (unsigned int) std::fmod( int_part, 10.0 );
232 	    s[i] = static_cast<char>( '0' + remainder );
233 
234 	    if( zero_digits )
235 	    {
236 		if( remainder == 0 )
237 		    int_zeros ++;
238 		else
239 		    zero_digits = false;
240 	    }
241 
242 	    int_part /= 10.0;
243 	}
244 
245 	// discard trailing zeros from int_part
246 	s.discard( int_zeros );
247 
248 	if( s[len] == '0' )
249 	{
250 	    // int_digits was overestimated by one
251 	    s.remove( len );
252 	    -- int_digits;
253 	}
254     }
255 
256     // print fractional part
257 
258     int frac_digits = 0;
259     int frac_zeros  = 0;
260 
261     if( frac_part != 0.0 )
262     {
263 	s += '.';
264 
265 	bool zero_digits = ( int_digits == 0 && fmt != SC_F );
266 
267 	frac_zeros = (int) std::floor( - std::log10( frac_part + DBL_EPSILON ) );
268 
269 	frac_part *= std::pow( 10.0, frac_zeros );
270 
271 	frac_digits = frac_zeros;
272 	if( ! zero_digits )
273 	{
274 	    for( i = 0; i < frac_zeros; i ++ )
275 		s += '0';
276 	    frac_zeros = 0;
277 	}
278 
279 	while( frac_part != 0.0 )
280 	{
281 	    frac_part *= 10.0;
282 	    int n = static_cast<int>( frac_part );
283 
284 	    if( zero_digits )
285 	    {
286 		if( n == 0 )
287 		    frac_zeros ++;
288 		else
289 		    zero_digits = false;
290 	    }
291 
292 	    if( ! zero_digits )
293 		s += static_cast<char>( '0' + n );
294 
295 	    frac_part -= n;
296 	    frac_digits ++;
297 	}
298     }
299 
300     // print exponent
301 
302     if( fmt != SC_F )
303     {
304         if( frac_digits == 0 )
305 	    scfx_print_exp( s, int_zeros );
306 	else if( int_digits == 0 )
307 	    scfx_print_exp( s, - frac_zeros );
308     }
309 }
310 
311 
312 static
313 void
print_other(scfx_string & s,const scfx_ieee_double & id,sc_numrep numrep,int w_prefix,sc_fmt fmt,const scfx_params * params)314 print_other( scfx_string& s, const scfx_ieee_double& id, sc_numrep numrep,
315 	     int w_prefix, sc_fmt fmt, const scfx_params* params )
316 {
317     scfx_ieee_double id2 = id;
318 
319     sc_numrep numrep2 = numrep;
320 
321     bool numrep_is_sm = ( numrep == SC_BIN_SM ||
322 			  numrep == SC_OCT_SM ||
323 			  numrep == SC_HEX_SM );
324 
325     if( numrep_is_sm )
326     {
327 	if( id2.negative() != 0 )
328 	{
329 	    s += '-';
330 	    id2.negative( 0 );
331 	}
332 	switch( numrep )
333 	{
334 	    case SC_BIN_SM:
335 		numrep2 = SC_BIN_US;
336 		break;
337 	    case SC_OCT_SM:
338 		numrep2 = SC_OCT_US;
339 		break;
340 	    case SC_HEX_SM:
341 		numrep2 = SC_HEX_US;
342 		break;
343 	    default:
344 		;
345 	}
346     }
347 
348     if( w_prefix != 0 ) {
349 	scfx_print_prefix( s, numrep );
350     }
351 
352     numrep = numrep2;
353 
354     sc_fxval_fast a( id2 );
355 
356     int msb, lsb;
357 
358     if( params != 0 )
359     {
360 	msb = params->iwl() - 1;
361 	lsb = params->iwl() - params->wl();
362 
363 	if( params->enc() == SC_TC_ &&
364 	    ( numrep == SC_BIN_US ||
365 	      numrep == SC_OCT_US ||
366 	      numrep == SC_HEX_US ) &&
367 	    ! numrep_is_sm &&
368 	    params->wl() > 1 )
369 	    -- msb;
370 	else if( params->enc() == SC_US_ &&
371 	    ( numrep == SC_BIN ||
372 	      numrep == SC_OCT ||
373 	      numrep == SC_HEX ||
374 	      numrep == SC_CSD ) )
375 	    ++ msb;
376     }
377     else
378     {
379 	if( a.is_zero() )
380 	{
381 	    msb = 0;
382 	    lsb = 0;
383 	}
384 	else
385 	{
386 	    msb = id2.exponent() + 1;
387 	    while( a.get_bit( msb ) == a.get_bit( msb - 1 ) )
388 		-- msb;
389 
390 	    if( numrep == SC_BIN_US ||
391 		numrep == SC_OCT_US ||
392 		numrep == SC_HEX_US )
393 		-- msb;
394 
395 	    lsb = id2.exponent() - 52;
396 	    while( ! a.get_bit( lsb ) )
397 		++ lsb;
398 	}
399     }
400 
401     int step;
402 
403     switch( numrep )
404     {
405 	case SC_BIN:
406 	case SC_BIN_US:
407 	case SC_CSD:
408 	    step = 1;
409 	   break;
410 	case SC_OCT:
411 	case SC_OCT_US:
412 	    step = 3;
413 	    break;
414 	case SC_HEX:
415 	case SC_HEX_US:
416 	    step = 4;
417 	    break;
418 	default:
419             SC_REPORT_FATAL( sc_core::SC_ID_ASSERTION_FAILED_
420                            , "unexpected sc_numrep" );
421             sc_core::sc_abort();
422     }
423 
424     msb = (int) std::ceil( double( msb + 1 ) / step ) * step - 1;
425 
426     lsb = (int) std::floor( double( lsb ) / step ) * step;
427 
428     if( msb < 0 )
429     {
430 	s += '.';
431 	if( fmt == SC_F )
432 	{
433 	    int sign = ( id2.negative() != 0 ) ? ( 1 << step ) - 1 : 0;
434 	    for( int i = ( msb + 1 ) / step; i < 0; i ++ )
435 	    {
436 		if( sign < 10 )
437 		    s += static_cast<char>( sign + '0' );
438 		else
439 		    s += static_cast<char>( sign + 'a' - 10 );
440 	    }
441 	}
442     }
443 
444     int i = msb;
445     while( i >= lsb )
446     {
447         int value = 0;
448         for( int j = step - 1; j >= 0; -- j )
449 	{
450             value += static_cast<int>( a.get_bit( i ) ) << j;
451             -- i;
452         }
453         if( value < 10 )
454             s += static_cast<char>( value + '0' );
455 	else
456             s += static_cast<char>( value + 'a' - 10 );
457 	if( i == -1 )
458 	    s += '.';
459     }
460 
461     if( lsb > 0 && fmt == SC_F )
462     {
463 	for( int i = lsb / step; i > 0; i -- )
464 	    s += '0';
465     }
466 
467     if( s[s.length() - 1] == '.' )
468 	s.discard( 1 );
469 
470     if( fmt != SC_F )
471     {
472 	if( msb < 0 )
473 	    scfx_print_exp( s, ( msb + 1 ) / step );
474 	else if( lsb > 0 )
475 	    scfx_print_exp( s, lsb / step );
476     }
477 
478     if( numrep == SC_CSD )
479 	scfx_tc2csd( s, w_prefix );
480 }
481 
482 
483 const char*
to_string(const scfx_ieee_double & id,sc_numrep numrep,int w_prefix,sc_fmt fmt,const scfx_params * params=0)484 to_string( const scfx_ieee_double& id, sc_numrep numrep, int w_prefix,
485 	   sc_fmt fmt, const scfx_params* params = 0 )
486 {
487     static scfx_string s;
488 
489     s.clear();
490 
491     if( id.is_nan() )
492         scfx_print_nan( s );
493     else if( id.is_inf() )
494         scfx_print_inf( s, static_cast<bool>( id.negative() ) );
495     else if( id.negative() && ! id.is_zero() &&
496 	     ( numrep == SC_BIN_US ||
497 	       numrep == SC_OCT_US ||
498 	       numrep == SC_HEX_US ) )
499         s += "negative";
500     else if( numrep == SC_DEC )
501         sc_dt::print_dec( s, id, w_prefix, fmt );
502     else
503         sc_dt::print_other( s, id, numrep, w_prefix, fmt, params );
504 
505     return s;
506 }
507 
508 
509 // explicit conversion to character string
510 
511 const std::string
to_string() const512 sc_fxval_fast::to_string() const
513 {
514     return std::string( sc_dt::to_string( m_val, SC_DEC, -1, SC_E ) );
515 }
516 
517 const std::string
to_string(sc_numrep numrep) const518 sc_fxval_fast::to_string( sc_numrep numrep ) const
519 {
520     return std::string( sc_dt::to_string( m_val, numrep, -1, SC_E ) );
521 }
522 
523 const std::string
to_string(sc_numrep numrep,bool w_prefix) const524 sc_fxval_fast::to_string( sc_numrep numrep, bool w_prefix ) const
525 {
526     return std::string( sc_dt::to_string( m_val, numrep, (w_prefix ? 1 : 0),
527 					SC_E ) );
528 }
529 
530 const std::string
to_string(sc_fmt fmt) const531 sc_fxval_fast::to_string( sc_fmt fmt ) const
532 {
533     return std::string( sc_dt::to_string( m_val, SC_DEC, -1, fmt ) );
534 }
535 
536 const std::string
to_string(sc_numrep numrep,sc_fmt fmt) const537 sc_fxval_fast::to_string( sc_numrep numrep, sc_fmt fmt ) const
538 {
539     return std::string( sc_dt::to_string( m_val, numrep, -1, fmt ) );
540 }
541 
542 const std::string
to_string(sc_numrep numrep,bool w_prefix,sc_fmt fmt) const543 sc_fxval_fast::to_string( sc_numrep numrep, bool w_prefix, sc_fmt fmt ) const
544 {
545     return std::string( sc_dt::to_string( m_val, numrep, (w_prefix ? 1 : 0),
546 					fmt ) );
547 }
548 
549 
550 const std::string
to_dec() const551 sc_fxval_fast::to_dec() const
552 {
553     return std::string( sc_dt::to_string( m_val, SC_DEC, -1, SC_E ) );
554 }
555 
556 const std::string
to_bin() const557 sc_fxval_fast::to_bin() const
558 {
559     return std::string( sc_dt::to_string( m_val, SC_BIN, -1, SC_E ) );
560 }
561 
562 const std::string
to_oct() const563 sc_fxval_fast::to_oct() const
564 {
565     return std::string( sc_dt::to_string( m_val, SC_OCT, -1, SC_E ) );
566 }
567 
568 const std::string
to_hex() const569 sc_fxval_fast::to_hex() const
570 {
571     return std::string( sc_dt::to_string( m_val, SC_HEX, -1, SC_E ) );
572 }
573 
574 
575 // print or dump content
576 
577 void
print(::std::ostream & os) const578 sc_fxval_fast::print( ::std::ostream& os ) const
579 {
580     os << sc_dt::to_string( m_val, SC_DEC, -1, SC_E );
581 }
582 
583 void
scan(::std::istream & is)584 sc_fxval_fast::scan( ::std::istream& is )
585 {
586     std::string s;
587     is >> s;
588     *this = s.c_str();
589 }
590 
591 void
dump(::std::ostream & os) const592 sc_fxval_fast::dump( ::std::ostream& os ) const
593 {
594     os << "sc_fxval_fast" << ::std::endl;
595     os << "(" << ::std::endl;
596     os << "val = " << m_val << ::std::endl;
597     // TO BE COMPLETED
598     // os << "r_flag   = " << m_r_flag << ::std::endl;
599     // os << "observer = ";
600     // if( m_observer != 0 )
601     //     m_observer->dump( os );
602     // else
603     //     os << "0" << ::std::endl;
604     os << ")" << ::std::endl;
605 }
606 
607 
608 // internal use only;
609 bool
get_bit(int i) const610 sc_fxval_fast::get_bit( int i ) const
611 {
612     scfx_ieee_double id( m_val );
613     if( id.is_zero() || id.is_nan() || id.is_inf() )
614         return false;
615 
616     // convert to two's complement
617 
618     unsigned int m0 = id.mantissa0();
619     unsigned int m1 = id.mantissa1();
620 
621     if( id.is_normal() )
622         m0 += 1U << 20;
623 
624     if( id.negative() != 0 )
625     {
626 	m0 = ~ m0;
627 	m1 = ~ m1;
628 	unsigned int tmp = m1;
629 	m1 += 1U;
630 	if( m1 <= tmp )
631 	    m0 += 1U;
632     }
633 
634     // get the right bit
635 
636     int j = i - id.exponent();
637     if( ( j += 20 ) >= 32 )
638         return ( ( m0 & 1U << 31 ) != 0 );
639     else if( j >= 0 )
640         return ( ( m0 & 1U << j ) != 0 );
641     else if( ( j += 32 ) >= 0 )
642         return ( ( m1 & 1U << j ) != 0 );
643     else
644         return false;
645 }
646 
647 
648 // protected methods and friend functions
649 
650 sc_fxval_fast_observer*
lock_observer() const651 sc_fxval_fast::lock_observer() const
652 {
653     SC_ASSERT_( m_observer != 0, "lock observer failed" );
654     sc_fxval_fast_observer* tmp = m_observer;
655     m_observer = 0;
656     return tmp;
657 }
658 
659 void
unlock_observer(sc_fxval_fast_observer * observer_) const660 sc_fxval_fast::unlock_observer( sc_fxval_fast_observer* observer_ ) const
661 {
662     SC_ASSERT_( observer_ != 0, "unlock observer failed" );
663     m_observer = observer_;
664 }
665 
666 
667 #define SCFX_FAIL_IF_(cnd)                                                    \
668 {                                                                             \
669     if( ( cnd ) )                                                             \
670         return static_cast<double>( scfx_ieee_double::nan() );                \
671 }
672 
673 double
from_string(const char * s)674 sc_fxval_fast::from_string( const char* s )
675 {
676     SCFX_FAIL_IF_( s == 0 || *s == 0 );
677 
678     scfx_string s2;
679     s2 += s;
680     s2 += '\0';
681 
682     bool sign_char;
683     int sign = scfx_parse_sign( s, sign_char );
684 
685     sc_numrep numrep = scfx_parse_prefix( s );
686 
687     int base = 0;
688 
689     switch( numrep )
690     {
691 	case SC_DEC:
692 	{
693 	    base = 10;
694 	    if( scfx_is_nan( s ) )  // special case: NaN
695 		return static_cast<double>( scfx_ieee_double::nan() );
696 	    if( scfx_is_inf( s ) )  // special case: Infinity
697 		return static_cast<double>( scfx_ieee_double::inf( sign ) );
698 	    break;
699 	}
700 	case SC_BIN:
701 	case SC_BIN_US:
702 	{
703 	    SCFX_FAIL_IF_( sign_char );
704 	    base = 2;
705 	    break;
706 	}
707 
708 	case SC_BIN_SM:
709 	{
710 	    base = 2;
711 	    break;
712 	}
713 	case SC_OCT:
714 	case SC_OCT_US:
715 	{
716 	    SCFX_FAIL_IF_( sign_char );
717 	    base = 8;
718 	    break;
719 	}
720 	case SC_OCT_SM:
721 	{
722 	    base = 8;
723 	    break;
724 	}
725 	case SC_HEX:
726 	case SC_HEX_US:
727 	{
728 	    SCFX_FAIL_IF_( sign_char );
729 	    base = 16;
730 	    break;
731 	}
732 	case SC_HEX_SM:
733 	{
734 	    base = 16;
735 	    break;
736 	}
737 	case SC_CSD:
738 	{
739 	    SCFX_FAIL_IF_( sign_char );
740 	    base = 2;
741 	    scfx_csd2tc( s2 );
742 	    s = (const char*) s2 + 4;
743 	    numrep = SC_BIN;
744 	    break;
745 	}
746        default:;// Martin, what is default???
747     }
748 
749     //
750     // find end of mantissa and count the digits and points
751     //
752 
753     const char *end = s;
754     bool based_point = false;
755     int int_digits = 0;
756     int frac_digits = 0;
757 
758     while( *end )
759     {
760 	if( scfx_exp_start( end ) )
761 	    break;
762 
763 	if( *end == '.' )
764 	{
765 	    SCFX_FAIL_IF_( based_point );
766 	    based_point = true;
767 	}
768 	else
769 	{
770 	    SCFX_FAIL_IF_( ! scfx_is_digit( *end, numrep ) );
771 	    if( based_point )
772 		frac_digits ++;
773 	    else
774 		int_digits ++;
775 	}
776 
777 	end ++;
778     }
779 
780     SCFX_FAIL_IF_( int_digits == 0 && frac_digits == 0 );
781 
782     // [ exponent ]
783 
784     int exponent = 0;
785 
786     if( *end )
787     {
788 	for( const char *e = end + 2; *e; e ++ )
789 	    SCFX_FAIL_IF_( ! scfx_is_digit( *e, SC_DEC ) );
790 	exponent = std::atoi( end + 1 );
791     }
792 
793     //
794     // convert the mantissa
795     //
796 
797     double integer = 0.0;
798 
799     if( int_digits != 0 )
800     {
801 
802 	bool first_digit = true;
803 
804 	for( ; s < end; s ++ )
805 	{
806 	    if( *s == '.' )
807 		break;
808 
809 	    if( first_digit )
810 	    {
811 		integer = scfx_to_digit( *s, numrep );
812 		switch( numrep )
813 		{
814 		    case SC_BIN:
815 		    case SC_OCT:
816 		    case SC_HEX:
817 		    {
818 			if( integer >= ( base >> 1 ) )
819 			    integer -= base;  // two's complement
820 			break;
821 		    }
822 		    default:
823 			;
824 		}
825 		first_digit = false;
826 	    }
827             else
828 	    {
829 		integer *= base;
830 		integer += scfx_to_digit( *s, numrep );
831 	    }
832 	}
833     }
834 
835     // [ . fraction ]
836 
837     double fraction = 0.0;
838 
839     if( frac_digits != 0 )
840     {
841 	s ++;  // skip '.'
842 
843 	bool first_digit = ( int_digits == 0 );
844 
845 	double scale = 1.0;
846 
847 	for( ; s < end; s ++ )
848 	{
849 	    scale /= base;
850 
851 	    if( first_digit )
852 	    {
853 		fraction = scfx_to_digit( *s, numrep );
854 		switch( numrep )
855 		{
856 		    case SC_BIN:
857 		    case SC_OCT:
858 		    case SC_HEX:
859 		    {
860 			if( fraction >= ( base >> 1 ) )
861 			    fraction -= base;  // two's complement
862 			break;
863 		    }
864 		    default:
865 			;
866 		}
867 		fraction *= scale;
868 		first_digit = false;
869 	    }
870 	    else
871 		fraction += scfx_to_digit( *s, numrep ) * scale;
872 	}
873     }
874 
875     double exp = ( exponent != 0 ) ? std::pow( (double) base, (double) exponent )
876 	                           : 1;
877 
878     return ( sign * ( integer + fraction ) * exp );
879 }
880 
881 #undef SCFX_FAIL_IF_
882 
883 } // namespace sc_dt
884 
885 
886 // Taf!
887