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