scfx_rep.cc revision 13197:aeba6988033f
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 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 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
1064    int step;
1065
1066    switch (numrep) {
1067      case SC_BIN:
1068      case SC_BIN_US:
1069      case SC_CSD:
1070        step = 1;
1071       break;
1072      case SC_OCT:
1073      case SC_OCT_US:
1074        step = 3;
1075        break;
1076      case SC_HEX:
1077      case SC_HEX_US:
1078        step = 4;
1079        break;
1080      default:
1081        SC_REPORT_FATAL("assertion failed", "unexpected sc_numrep");
1082        sc_core::sc_abort();
1083    }
1084
1085    msb = (int)std::ceil(double(msb + 1) / step) * step - 1;
1086
1087    lsb = (int)std::floor(double(lsb) / step) * step;
1088
1089    if (msb < 0) {
1090        s += '.';
1091        if (fmt == SC_F) {
1092            int sign = (b.is_neg()) ? (1 << step) - 1 : 0;
1093            for (int i = (msb + 1) / step; i < 0; i++) {
1094                if (sign < 10)
1095                    s += static_cast<char>(sign + '0');
1096                else
1097                    s += static_cast<char>(sign + 'a' - 10);
1098            }
1099        }
1100    }
1101
1102    int i = msb;
1103    while (i >= lsb) {
1104        int value = 0;
1105        for (int j = step - 1; j >= 0; --j) {
1106            value += static_cast<int>(b.get_bit(i)) << j;
1107            --i;
1108        }
1109        if (value < 10)
1110            s += static_cast<char>(value + '0');
1111        else
1112            s += static_cast<char>(value + 'a' - 10);
1113        if (i == -1)
1114            s += '.';
1115    }
1116
1117    if (lsb > 0 && fmt == SC_F) {
1118        for (int i = lsb / step; i > 0; i--)
1119            s += '0';
1120    }
1121
1122    if (s[s.length() - 1] == '.')
1123        s.discard(1);
1124
1125    if (fmt != SC_F) {
1126        if (msb < 0)
1127            scfx_print_exp(s, (msb + 1) / step);
1128        else if (lsb > 0)
1129            scfx_print_exp(s, lsb / step);
1130    }
1131
1132    if (numrep == SC_CSD)
1133        scfx_tc2csd(s, w_prefix);
1134}
1135
1136const char *
1137scfx_rep::to_string(sc_numrep numrep, int w_prefix,
1138                    sc_fmt fmt, const scfx_params *params) const
1139{
1140    static scfx_string s;
1141
1142    s.clear();
1143
1144    if (is_nan()) {
1145        scfx_print_nan(s);
1146    } else if (is_inf()) {
1147        scfx_print_inf(s, is_neg());
1148    } else if (is_neg() && !is_zero() &&
1149               (numrep == SC_BIN_US ||
1150                numrep == SC_OCT_US ||
1151                numrep == SC_HEX_US)) {
1152        s += "negative";
1153    } else if (numrep == SC_DEC || numrep == SC_NOBASE) {
1154        sc_dt::print_dec(s, *this, w_prefix, fmt);
1155    } else {
1156        sc_dt::print_other(s, *this, numrep, w_prefix, fmt, params);
1157    }
1158
1159    return s;
1160}
1161
1162
1163// ----------------------------------------------------------------------------
1164//  ADD
1165//
1166//  add two mantissas of the same size
1167//  result has the same size
1168//  returns carry of operation
1169// ----------------------------------------------------------------------------
1170
1171static inline int
1172add_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b)
1173{
1174    unsigned int carry = 0;
1175
1176    int index = 0;
1177
1178    do {
1179        word x = a[index];
1180        word y = b[index];
1181
1182        y += carry;
1183        carry = y < carry;
1184        y += x;
1185        carry += y < x;
1186        result[index] = y;
1187    } while (++index < size);
1188
1189    return (carry ? 1 : 0);
1190}
1191
1192static inline int
1193sub_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b)
1194{
1195    unsigned carry = 0;
1196
1197    int index = 0;
1198
1199    do {
1200        word x = a[index];
1201        word y = b[index];
1202
1203        y += carry;
1204        carry = y < carry;
1205        y = x - y;
1206        carry += y > x;
1207        result[index] = y;
1208    } while (++index < size);
1209
1210    return (carry ? 1 : 0);
1211}
1212
1213scfx_rep *
1214add_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl)
1215{
1216    scfx_rep &result = *new scfx_rep;
1217
1218    //
1219    // check for special cases
1220    //
1221    if (lhs.is_nan() || rhs.is_nan() ||
1222        (lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign)) {
1223        result.set_nan();
1224        return &result;
1225    }
1226
1227    if (lhs.is_inf()) {
1228        result.set_inf(lhs.m_sign);
1229        return &result;
1230    }
1231
1232    if (rhs.is_inf()) {
1233        result.set_inf(rhs.m_sign);
1234        return &result;
1235    }
1236
1237    //
1238    // align operands if needed
1239    //
1240    scfx_mant_ref lhs_mant;
1241    scfx_mant_ref rhs_mant;
1242
1243    int len_mant = lhs.size();
1244    int new_wp = lhs.m_wp;
1245
1246    align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant);
1247
1248    //
1249    // size the result mantissa
1250    //
1251    result.resize_to(len_mant);
1252    result.m_wp = new_wp;
1253
1254    //
1255    // do it
1256    //
1257    if (lhs.m_sign == rhs.m_sign) {
1258        add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1259        result.m_sign = lhs.m_sign;
1260    } else {
1261        int cmp = compare_abs(lhs, rhs);
1262
1263        if (cmp == 1) {
1264            sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1265            result.m_sign = lhs.m_sign;
1266        } else if (cmp == -1) {
1267            sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant);
1268            result.m_sign = rhs.m_sign;
1269        } else {
1270            result.m_mant.clear();
1271            result.m_sign = 1;
1272        }
1273    }
1274
1275    result.find_sw();
1276    result.round(max_wl);
1277
1278    return &result;
1279}
1280
1281
1282// ----------------------------------------------------------------------------
1283//  SUB
1284//
1285//  sub two word's of the same size
1286//  result has the same size
1287//  returns carry of operation
1288// ----------------------------------------------------------------------------
1289
1290static inline int
1291sub_with_index(scfx_mant &a, int a_msw, int /*a_lsw*/,
1292               const scfx_mant &b, int b_msw, int b_lsw)
1293{
1294    unsigned carry = 0;
1295
1296    int size = b_msw - b_lsw;
1297    int a_index = a_msw - size;
1298    int b_index = b_msw - size;
1299
1300    do {
1301        word x = a[a_index];
1302        word y = b[b_index];
1303
1304        y += carry;
1305        carry = y < carry;
1306        y = x - y;
1307        carry += y > x;
1308        a[a_index] = y;
1309
1310        a_index++;
1311        b_index++;
1312    } while (size--);
1313
1314    if (carry) {
1315        // special case: a[a_msw + 1] == 1
1316        a[a_msw + 1] = 0;
1317    }
1318
1319    return (carry ? 1 : 0);
1320}
1321
1322scfx_rep *
1323sub_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl)
1324{
1325    scfx_rep &result = *new scfx_rep;
1326
1327    //
1328    // check for special cases
1329    //
1330    if (lhs.is_nan() || rhs.is_nan() ||
1331        (lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign)) {
1332        result.set_nan();
1333        return &result;
1334    }
1335
1336    if (lhs.is_inf()) {
1337        result.set_inf(lhs.m_sign);
1338        return &result;
1339    }
1340
1341    if (rhs.is_inf()) {
1342        result.set_inf(-1 * rhs.m_sign);
1343        return &result;
1344    }
1345
1346    //
1347    // align operands if needed
1348    //
1349    scfx_mant_ref lhs_mant;
1350    scfx_mant_ref rhs_mant;
1351
1352    int len_mant = lhs.size();
1353    int new_wp = lhs.m_wp;
1354
1355    align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant);
1356
1357    //
1358    // size the result mantissa
1359    //
1360    result.resize_to(len_mant);
1361    result.m_wp = new_wp;
1362
1363    //
1364    // do it
1365    //
1366    if (lhs.m_sign != rhs.m_sign) {
1367        add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1368        result.m_sign = lhs.m_sign;
1369    } else {
1370        int cmp = compare_abs(lhs, rhs);
1371
1372        if (cmp == 1) {
1373            sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1374            result.m_sign = lhs.m_sign;
1375        } else if (cmp == -1) {
1376            sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant);
1377            result.m_sign = -rhs.m_sign;
1378        } else {
1379            result.m_mant.clear();
1380            result.m_sign = 1;
1381        }
1382    }
1383
1384    result.find_sw();
1385    result.round(max_wl);
1386
1387    return &result;
1388}
1389
1390
1391// ----------------------------------------------------------------------------
1392//  MUL
1393// ----------------------------------------------------------------------------
1394
1395union word_short
1396{
1397    word l;
1398    struct
1399    {
1400#if defined(SC_BOOST_BIG_ENDIAN)
1401        half_word u;
1402        half_word l;
1403#elif defined(SC_BOOST_LITTLE_ENDIAN)
1404        half_word l;
1405        half_word u;
1406#endif
1407    } s;
1408};
1409
1410#if defined(SC_BOOST_BIG_ENDIAN)
1411static const int half_word_incr = -1;
1412#elif defined(SC_BOOST_LITTLE_ENDIAN)
1413static const int half_word_incr = 1;
1414#endif
1415
1416void
1417multiply(scfx_rep &result, const scfx_rep &lhs, const scfx_rep &rhs,
1418         int max_wl)
1419{
1420    //
1421    // check for special cases
1422    //
1423    if (lhs.is_nan() || rhs.is_nan() ||
1424        (lhs.is_inf() && rhs.is_zero()) ||
1425        (lhs.is_zero() && rhs.is_inf())) {
1426        result.set_nan();
1427        return;
1428    }
1429
1430    if (lhs.is_inf() || rhs.is_inf()) {
1431        result.set_inf(lhs.m_sign * rhs.m_sign);
1432        return;
1433    }
1434
1435    if (lhs.is_zero() || rhs.is_zero()) {
1436        result.set_zero(lhs.m_sign * rhs.m_sign);
1437        return;
1438    }
1439
1440    //
1441    // do it
1442    //
1443    int len_lhs = lhs.m_msw - lhs.m_lsw + 1;
1444    int len_rhs = rhs.m_msw - rhs.m_lsw + 1;
1445
1446    int new_size = sc_max(min_mant, len_lhs + len_rhs);
1447    int new_wp = (lhs.m_wp - lhs.m_lsw) + (rhs.m_wp - rhs.m_lsw);
1448    int new_sign = lhs.m_sign * rhs.m_sign;
1449
1450    result.resize_to(new_size);
1451    result.m_mant.clear();
1452    result.m_wp = new_wp;
1453    result.m_sign = new_sign;
1454    result.m_state = scfx_rep::normal;
1455
1456    half_word *s1 = lhs.m_mant.half_addr(lhs.m_lsw);
1457    half_word *s2 = rhs.m_mant.half_addr(rhs.m_lsw);
1458
1459    half_word *t = result.m_mant.half_addr();
1460
1461    len_lhs <<= 1;
1462    len_rhs <<= 1;
1463
1464    int i1, i2;
1465
1466    for (i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr) {
1467        word_short ls;
1468        ls.l = 0;
1469
1470        half_word v1 = s1[i1];
1471
1472        for (i2  = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr) {
1473            ls.l  += v1 * s2[i2];
1474            ls.s.l = ls.s.u + ((t[i2] += ls.s.l) < ls.s.l);
1475            ls.s.u = 0;
1476        }
1477
1478        t[i2] = ls.s.l;
1479        t += half_word_incr;
1480    }
1481
1482    result.find_sw();
1483    result.round(max_wl);
1484}
1485
1486
1487// ----------------------------------------------------------------------------
1488//  DIV
1489// ----------------------------------------------------------------------------
1490
1491scfx_rep *
1492div_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int div_wl)
1493{
1494    scfx_rep &result = *new scfx_rep;
1495
1496    //
1497    // check for special cases
1498    //
1499    if (lhs.is_nan() || rhs.is_nan() || (lhs.is_inf() && rhs.is_inf()) ||
1500        (lhs.is_zero() && rhs.is_zero())) {
1501        result.set_nan();
1502        return &result;
1503    }
1504
1505    if (lhs.is_inf() || rhs.is_zero()) {
1506        result.set_inf(lhs.m_sign * rhs.m_sign);
1507        return &result;
1508    }
1509
1510    if (lhs.is_zero() || rhs.is_inf()) {
1511        result.set_zero(lhs.m_sign * rhs.m_sign);
1512        return &result;
1513    }
1514
1515    //
1516    // do it
1517    //
1518
1519    // compute one bit more for rounding
1520    div_wl++;
1521
1522    result.resize_to(sc_max(n_word(div_wl) + 1, min_mant));
1523    result.m_mant.clear();
1524    result.m_sign = lhs.m_sign * rhs.m_sign;
1525
1526    int msb_lhs = scfx_find_msb(lhs.m_mant[lhs.m_msw]) +
1527                  (lhs.m_msw - lhs.m_wp) * bits_in_word;
1528    int msb_rhs = scfx_find_msb(rhs.m_mant[rhs.m_msw]) +
1529                  (rhs.m_msw - rhs.m_wp) * bits_in_word;
1530
1531    int msb_res = msb_lhs - msb_rhs;
1532    int to_shift = -msb_res % bits_in_word;
1533    int result_index;
1534
1535    int c = (msb_res % bits_in_word >= 0) ? 1 : 0;
1536
1537    result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word;
1538    result.m_wp = (result.size() - c) - msb_res / bits_in_word;
1539
1540    scfx_rep remainder = lhs;
1541
1542    // align msb from remainder to msb from rhs
1543    remainder.lshift(to_shift);
1544
1545    // make sure msw(remainder) < size - 1
1546    if (remainder.m_msw == remainder.size() - 1)
1547        remainder.resize_to(remainder.size() + 1, 1);
1548
1549    // make sure msw(remainder) >= msw(rhs)!
1550    int msw_diff = rhs.m_msw - remainder.m_msw;
1551    if (msw_diff > 0)
1552        remainder.resize_to(remainder.size() + msw_diff, -1);
1553
1554    int counter;
1555
1556    for (counter = div_wl; counter && !remainder.is_zero(); counter--) {
1557        if (compare_msw_ff(rhs, remainder) <= 0) {
1558            result.set_bin(result_index);
1559            sub_with_index(remainder.m_mant, remainder.m_msw, remainder.m_lsw,
1560                           rhs.m_mant, rhs.m_msw, rhs.m_lsw);
1561        }
1562        result_index--;
1563        remainder.shift_left(1);
1564        remainder.m_lsw = remainder.find_lsw();
1565    }
1566
1567    // perform convergent rounding, if needed
1568    if (counter == 0) {
1569        int index = result_index + 1 - result.m_wp * bits_in_word;
1570
1571        scfx_index x = result.calc_indices(index);
1572        scfx_index x1 = result.calc_indices(index + 1);
1573
1574        if (result.o_bit_at(x) && result.o_bit_at(x1))
1575            result.q_incr(x);
1576
1577        result.m_r_flag = true;
1578    }
1579
1580    result.find_sw();
1581
1582    return &result;
1583}
1584
1585// ----------------------------------------------------------------------------
1586//  destructive shift mantissa to the left
1587// ----------------------------------------------------------------------------
1588
1589void
1590scfx_rep::lshift(int n)
1591{
1592    if (n == 0)
1593        return;
1594
1595    if (n < 0) {
1596        rshift(-n);
1597        return;
1598    }
1599
1600    if (is_normal()) {
1601        int shift_bits = n % bits_in_word;
1602        int shift_words = n / bits_in_word;
1603
1604        // resize if needed
1605        if (m_msw == size() - 1 &&
1606            scfx_find_msb(m_mant[m_msw]) >= bits_in_word - shift_bits)
1607            resize_to(size() + 1, 1);
1608
1609        // do it
1610        m_wp -= shift_words;
1611        shift_left(shift_bits);
1612        find_sw();
1613    }
1614}
1615
1616// ----------------------------------------------------------------------------
1617//  destructive shift mantissa to the right
1618// ----------------------------------------------------------------------------
1619
1620void
1621scfx_rep::rshift(int n)
1622{
1623    if (n == 0)
1624        return;
1625
1626    if (n < 0) {
1627        lshift(-n);
1628        return;
1629    }
1630
1631    if (is_normal()) {
1632        int shift_bits = n % bits_in_word;
1633        int shift_words = n / bits_in_word;
1634
1635        // resize if needed
1636        if (m_lsw == 0 && scfx_find_lsb(m_mant[m_lsw]) < shift_bits)
1637            resize_to(size() + 1, -1);
1638
1639        // do it
1640        m_wp += shift_words;
1641        shift_right(shift_bits);
1642        find_sw();
1643    }
1644}
1645
1646
1647// ----------------------------------------------------------------------------
1648//  FRIEND FUNCTION : compare_abs
1649//
1650//  Compares the absolute values of two scfx_reps, excluding the special cases.
1651// ----------------------------------------------------------------------------
1652
1653int
1654compare_abs(const scfx_rep &a, const scfx_rep &b)
1655{
1656    // check for zero
1657    word a_word = a.m_mant[a.m_msw];
1658    word b_word = b.m_mant[b.m_msw];
1659
1660    if (a_word == 0 || b_word == 0) {
1661        if (a_word != 0)
1662            return 1;
1663        if (b_word != 0)
1664            return -1;
1665        return 0;
1666    }
1667
1668    // compare msw index
1669    int a_msw = a.m_msw - a.m_wp;
1670    int b_msw = b.m_msw - b.m_wp;
1671
1672    if (a_msw > b_msw)
1673        return 1;
1674
1675    if (a_msw < b_msw)
1676        return -1;
1677
1678    // compare content
1679    int a_i = a.m_msw;
1680    int b_i = b.m_msw;
1681
1682    while (a_i >= a.m_lsw && b_i >= b.m_lsw) {
1683        a_word = a.m_mant[a_i];
1684        b_word = b.m_mant[b_i];
1685        if (a_word > b_word)
1686            return 1;
1687        if (a_word < b_word)
1688            return -1;
1689        --a_i;
1690        --b_i;
1691    }
1692
1693    bool a_zero = true;
1694    while (a_i >= a.m_lsw) {
1695        a_zero = a_zero && (a.m_mant[a_i] == 0);
1696        --a_i;
1697    }
1698
1699    bool b_zero = true;
1700    while (b_i >= b.m_lsw) {
1701        b_zero = b_zero && (b.m_mant[b_i] == 0);
1702        --b_i;
1703    }
1704
1705    // assertion: a_zero || b_zero
1706
1707    if (!a_zero && b_zero)
1708        return 1;
1709
1710    if (a_zero && !b_zero)
1711        return -1;
1712
1713    return 0;
1714}
1715
1716// ----------------------------------------------------------------------------
1717//  FRIEND FUNCTION : cmp_scfx_rep
1718//
1719//  Compares the values of two scfx_reps, including the special cases.
1720// ----------------------------------------------------------------------------
1721
1722int
1723cmp_scfx_rep(const scfx_rep &a, const scfx_rep &b)
1724{
1725    // handle special cases
1726
1727    if (a.is_nan() || b.is_nan()) {
1728        return 2;
1729    }
1730
1731    if (a.is_inf() || b.is_inf()) {
1732        if (a.is_inf()) {
1733            if (!a.is_neg()) {
1734                if (b.is_inf() && !b.is_neg()) {
1735                    return 0;
1736                } else {
1737                    return 1;
1738                }
1739            } else {
1740                if (b.is_inf() && b.is_neg()) {
1741                    return 0;
1742                } else {
1743                    return -1;
1744                }
1745            }
1746        }
1747        if (b.is_inf()) {
1748            if (!b.is_neg()) {
1749                return -1;
1750            } else {
1751                return 1;
1752            }
1753        }
1754    }
1755
1756    if (a.is_zero() && b.is_zero()) {
1757        return 0;
1758    }
1759
1760    // compare sign
1761    if (a.m_sign != b.m_sign) {
1762        return a.m_sign;
1763    }
1764
1765    return (a.m_sign * compare_abs(a, b));
1766}
1767
1768
1769// ----------------------------------------------------------------------------
1770//  PRIVATE METHOD : quantization
1771//
1772//  Performs destructive quantization.
1773// ----------------------------------------------------------------------------
1774
1775void
1776scfx_rep::quantization(const scfx_params &params, bool &q_flag)
1777{
1778    scfx_index x = calc_indices(params.iwl() - params.wl());
1779
1780    if (x.wi() < 0)
1781        return;
1782
1783    if (x.wi() >= size())
1784        resize_to(x.wi() + 1, 1);
1785
1786    bool qb = q_bit(x);
1787    bool qz = q_zero(x);
1788
1789    q_flag = (qb || ! qz);
1790
1791    if (q_flag) {
1792        switch (params.q_mode()) {
1793          case SC_TRN: // truncation
1794            {
1795                if (is_neg())
1796                    q_incr(x);
1797                break;
1798            }
1799          case SC_RND: // rounding to plus infinity
1800            {
1801                if (!is_neg()) {
1802                    if (qb)
1803                        q_incr(x);
1804                } else {
1805                    if (qb && !qz)
1806                        q_incr(x);
1807                }
1808                break;
1809            }
1810          case SC_TRN_ZERO: // truncation to zero
1811            {
1812                break;
1813            }
1814          case SC_RND_INF: // rounding to infinity
1815            {
1816                if (qb)
1817                    q_incr(x);
1818                break;
1819            }
1820          case SC_RND_CONV: // convergent rounding
1821            {
1822                if ((qb && !qz) || (qb && qz && q_odd(x)))
1823                    q_incr(x);
1824                break;
1825            }
1826          case SC_RND_ZERO: // rounding to zero
1827            {
1828                if (qb && !qz)
1829                    q_incr(x);
1830                break;
1831            }
1832          case SC_RND_MIN_INF: // rounding to minus infinity
1833            {
1834                if (!is_neg()) {
1835                    if (qb && !qz)
1836                        q_incr(x);
1837                } else {
1838                    if (qb)
1839                        q_incr(x);
1840                }
1841                break;
1842            }
1843          default:
1844            ;
1845        }
1846        q_clear(x);
1847
1848        find_sw();
1849    }
1850}
1851
1852
1853// ----------------------------------------------------------------------------
1854//  PRIVATE METHOD : overflow
1855//
1856//  Performs destructive overflow handling.
1857// ----------------------------------------------------------------------------
1858
1859void
1860scfx_rep::overflow(const scfx_params &params, bool &o_flag)
1861{
1862    scfx_index x = calc_indices(params.iwl() - 1);
1863
1864    if (x.wi() >= size())
1865        resize_to(x.wi() + 1, 1);
1866
1867    if (x.wi() < 0) {
1868        resize_to(size() - x.wi(), -1);
1869        x.wi(0);
1870    }
1871
1872    bool zero_left = o_zero_left(x);
1873    bool bit_at = o_bit_at(x);
1874    bool zero_right = o_zero_right(x);
1875
1876    bool under = false;
1877    bool over = false;
1878
1879    sc_enc enc = params.enc();
1880
1881    if (enc == SC_TC_) {
1882        if (is_neg()) {
1883            if (params.o_mode() == SC_SAT_SYM)
1884                under = (!zero_left || bit_at);
1885            else
1886                under = (!zero_left || (zero_left && bit_at && ! zero_right));
1887        } else {
1888            over = (! zero_left || bit_at);
1889        }
1890    } else {
1891        if (is_neg())
1892            under = (!is_zero());
1893        else
1894            over = (!zero_left);
1895    }
1896
1897    o_flag = (under || over);
1898
1899    if (o_flag) {
1900        scfx_index x2 = calc_indices(params.iwl() - params.wl());
1901
1902        if (x2.wi() < 0) {
1903            resize_to(size() - x2.wi(), -1);
1904            x.wi(x.wi() - x2.wi());
1905            x2.wi(0);
1906        }
1907
1908        switch (params.o_mode()) {
1909          case SC_WRAP: // wrap-around
1910            {
1911                int n_bits = params.n_bits();
1912
1913                if (n_bits == 0) {
1914                    // wrap-around all 'wl' bits
1915                    toggle_tc();
1916                    o_extend(x, enc);
1917                    toggle_tc();
1918                } else if (n_bits < params.wl()) {
1919                    scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits);
1920
1921                    // wrap-around least significant 'wl - n_bits' bits;
1922                    // saturate most significant 'n_bits' bits
1923                    toggle_tc();
1924                    o_set(x, x3, enc, under);
1925                    o_extend(x, enc);
1926                    toggle_tc();
1927                } else {
1928                    // saturate all 'wl' bits
1929                    if (under)
1930                        o_set_low(x, enc);
1931                    else
1932                        o_set_high(x, x2, enc);
1933                }
1934                break;
1935            }
1936          case SC_SAT: // saturation
1937            {
1938                if (under)
1939                    o_set_low(x, enc);
1940                else
1941                    o_set_high(x, x2, enc);
1942                break;
1943            }
1944          case SC_SAT_SYM: // symmetrical saturation
1945            {
1946                if (under) {
1947                    if (enc == SC_TC_)
1948                        o_set_high(x, x2, SC_TC_, -1);
1949                    else
1950                        o_set_low(x, SC_US_);
1951                } else {
1952                    o_set_high(x, x2, enc);
1953                }
1954                break;
1955            }
1956          case SC_SAT_ZERO: // saturation to zero
1957            {
1958                set_zero();
1959                break;
1960            }
1961          case SC_WRAP_SM: // sign magnitude wrap-around
1962            {
1963                SC_ERROR_IF_(enc == SC_US_,
1964                             "SC_WRAP_SM not defined for unsigned numbers");
1965
1966                int n_bits = params.n_bits();
1967
1968                if (n_bits == 0) {
1969                    scfx_index x4 = calc_indices(params.iwl());
1970
1971                    if (x4.wi() >= size())
1972                        resize_to(x4.wi() + 1, 1);
1973
1974                    toggle_tc();
1975                    if (o_bit_at(x4) != o_bit_at(x))
1976                        o_invert(x2);
1977                    o_extend(x, SC_TC_);
1978                    toggle_tc();
1979                } else if (n_bits == 1) {
1980                    toggle_tc();
1981                    if (is_neg() != o_bit_at(x))
1982                        o_invert(x2);
1983                    o_extend(x, SC_TC_);
1984                    toggle_tc();
1985                } else if (n_bits < params.wl()) {
1986                    scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits);
1987                    scfx_index x4 = calc_indices(params.iwl() - n_bits);
1988
1989                    // wrap-around least significant 'wl - n_bits' bits;
1990                    // saturate most significant 'n_bits' bits
1991                    toggle_tc();
1992                    if (is_neg() == o_bit_at(x4))
1993                        o_invert(x2);
1994                    o_set(x, x3, SC_TC_, under);
1995                    o_extend(x, SC_TC_);
1996                    toggle_tc();
1997                } else {
1998                    if (under)
1999                        o_set_low(x, SC_TC_);
2000                    else
2001                        o_set_high(x, x2, SC_TC_);
2002                }
2003                break;
2004            }
2005          default:
2006            ;
2007        }
2008
2009        find_sw();
2010    }
2011}
2012
2013
2014// ----------------------------------------------------------------------------
2015//  PUBLIC METHOD : cast
2016//
2017//  Performs a destructive cast operation on a scfx_rep.
2018// ----------------------------------------------------------------------------
2019
2020void
2021scfx_rep::cast(const scfx_params &params, bool &q_flag, bool &o_flag)
2022{
2023    q_flag = false;
2024    o_flag = false;
2025
2026    // check for special cases
2027    if (is_zero()) {
2028        if (is_neg())
2029            m_sign = 1;
2030        return;
2031    }
2032
2033    // perform casting
2034    quantization(params, q_flag);
2035    overflow(params, o_flag);
2036
2037    // check for special case: -0
2038    if (is_zero() && is_neg())
2039        m_sign = 1;
2040}
2041
2042
2043// ----------------------------------------------------------------------------
2044//  make sure, the two mantissas are aligned
2045// ----------------------------------------------------------------------------
2046
2047void
2048align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp,
2049      int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant)
2050{
2051    bool need_lhs = true;
2052    bool need_rhs = true;
2053
2054    if (lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size()) {
2055        int lower_bound_lhs = lhs.m_lsw - lhs.m_wp;
2056        int upper_bound_lhs = lhs.m_msw - lhs.m_wp;
2057        int lower_bound_rhs = rhs.m_lsw - rhs.m_wp;
2058        int upper_bound_rhs = rhs.m_msw - rhs.m_wp;
2059
2060        int lower_bound = sc_min(lower_bound_lhs, lower_bound_rhs);
2061        int upper_bound = sc_max(upper_bound_lhs, upper_bound_rhs);
2062
2063        new_wp = -lower_bound;
2064        len_mant = sc_max(min_mant, upper_bound - lower_bound + 1);
2065
2066        if (new_wp != lhs.m_wp || len_mant != lhs.size()) {
2067            lhs_mant = lhs.resize(len_mant, new_wp);
2068            need_lhs = false;
2069        }
2070
2071        if (new_wp != rhs.m_wp || len_mant != rhs.size()) {
2072            rhs_mant = rhs.resize(len_mant, new_wp);
2073            need_rhs = false;
2074        }
2075    }
2076
2077    if (need_lhs) {
2078        lhs_mant = lhs.m_mant;
2079    }
2080
2081    if (need_rhs) {
2082        rhs_mant = rhs.m_mant;
2083    }
2084}
2085
2086
2087// ----------------------------------------------------------------------------
2088//  compare two mantissas
2089// ----------------------------------------------------------------------------
2090
2091int
2092compare_msw_ff(const scfx_rep &lhs, const scfx_rep &rhs)
2093{
2094    // special case: rhs.m_mant[rhs.m_msw + 1] == 1
2095    if (rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0) {
2096        return -1;
2097    }
2098
2099    int lhs_size = lhs.m_msw - lhs.m_lsw + 1;
2100    int rhs_size = rhs.m_msw - rhs.m_lsw + 1;
2101
2102    int size = sc_min(lhs_size, rhs_size);
2103
2104    int lhs_index = lhs.m_msw;
2105    int rhs_index = rhs.m_msw;
2106
2107    int i;
2108
2109    for (i = 0;
2110         i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index];
2111         i++) {
2112        lhs_index--;
2113        rhs_index--;
2114    }
2115
2116    if (i == size) {
2117        if (lhs_size == rhs_size) {
2118            return 0;
2119        }
2120
2121        if (lhs_size < rhs_size) {
2122            return -1;
2123        } else {
2124            return 1;
2125        }
2126    }
2127
2128    if (lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index]) {
2129        return -1;
2130    } else {
2131        return 1;
2132    }
2133}
2134
2135
2136// ----------------------------------------------------------------------------
2137//  divide the mantissa by ten
2138// ----------------------------------------------------------------------------
2139
2140unsigned int
2141scfx_rep::divide_by_ten()
2142{
2143#if defined(SC_BOOST_BIG_ENDIAN)
2144    half_word *hw = (half_word *)&m_mant[m_msw];
2145#elif defined(SC_BOOST_LITTLE_ENDIAN)
2146    half_word *hw = ((half_word *)&m_mant[m_msw]) + 1;
2147#endif
2148
2149    unsigned int remainder = 0;
2150
2151    word_short ls;
2152    ls.l = 0;
2153
2154#if defined(SC_BOOST_BIG_ENDIAN)
2155    for (int i = 0, end = (m_msw - m_wp + 1) * 2; i < end; i++) {
2156#elif defined(SC_BOOST_LITTLE_ENDIAN)
2157    for (int i = 0, end = -(m_msw - m_wp + 1) * 2; i > end; i--) {
2158#endif
2159        ls.s.u = static_cast<half_word>(remainder);
2160        ls.s.l = hw[i];
2161        remainder = ls.l % 10;
2162        ls.l /= 10;
2163        hw[i] = ls.s.l;
2164    }
2165
2166    return remainder;
2167}
2168
2169
2170// ----------------------------------------------------------------------------
2171//  multiply the mantissa by ten
2172// ----------------------------------------------------------------------------
2173
2174void
2175scfx_rep::multiply_by_ten()
2176{
2177    int size = m_mant.size() + 1;
2178
2179    scfx_mant mant8(size);
2180    scfx_mant mant2(size);
2181
2182    size--;
2183
2184    mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3));
2185    mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1));
2186
2187    while (--size) {
2188        mant8[size] = (m_mant[size] << 3) |
2189                      (m_mant[size - 1] >> (bits_in_word - 3));
2190        mant2[size] = (m_mant[size] << 1) |
2191                      (m_mant[size - 1] >> (bits_in_word - 1));
2192    }
2193
2194    mant8[0] = (m_mant[0] << 3);
2195    mant2[0] = (m_mant[0] << 1);
2196
2197    add_mants(m_mant.size(), m_mant, mant8, mant2);
2198}
2199
2200
2201// ----------------------------------------------------------------------------
2202//  normalize
2203// ----------------------------------------------------------------------------
2204
2205void
2206scfx_rep::normalize(int exponent)
2207{
2208    int shift = exponent % bits_in_word;
2209    if (shift < 0) {
2210        shift += bits_in_word;
2211    }
2212
2213    if (shift) {
2214        shift_left(shift);
2215    }
2216
2217    find_sw();
2218
2219    m_wp = (shift - exponent) / bits_in_word;
2220}
2221
2222
2223// ----------------------------------------------------------------------------
2224//  return a new mantissa that is aligned and resized
2225// ----------------------------------------------------------------------------
2226
2227scfx_mant *
2228scfx_rep::resize(int new_size, int new_wp) const
2229{
2230    scfx_mant *result = new scfx_mant(new_size);
2231
2232    result->clear();
2233
2234    int shift = new_wp - m_wp;
2235
2236    for (int j = m_lsw; j <= m_msw; j++) {
2237        (*result)[j + shift] = m_mant[j];
2238    }
2239
2240    return result;
2241}
2242
2243
2244// ----------------------------------------------------------------------------
2245//  set a single bit
2246// ----------------------------------------------------------------------------
2247
2248void
2249scfx_rep::set_bin(int i)
2250{
2251    m_mant[i >> 5] |= 1 << (i & 31);
2252}
2253
2254
2255// ----------------------------------------------------------------------------
2256//  set three bits
2257// ----------------------------------------------------------------------------
2258
2259void
2260scfx_rep::set_oct(int i, int n)
2261{
2262    if (n & 1) {
2263        m_mant[i >> 5] |= 1 << (i & 31);
2264    }
2265    i++;
2266    if (n & 2) {
2267        m_mant[i >> 5] |= 1 << (i & 31);
2268    }
2269    i++;
2270    if (n & 4) {
2271        m_mant[i >> 5] |= 1 << (i & 31);
2272    }
2273}
2274
2275
2276// ----------------------------------------------------------------------------
2277//  set four bits
2278// ----------------------------------------------------------------------------
2279
2280void
2281scfx_rep::set_hex(int i, int n)
2282{
2283    if (n & 1) {
2284        m_mant[i >> 5] |= 1 << (i & 31);
2285    }
2286    i++;
2287    if (n & 2) {
2288        m_mant[i >> 5] |= 1 << (i & 31);
2289    }
2290    i++;
2291    if (n & 4) {
2292        m_mant[i >> 5] |= 1 << (i & 31);
2293    }
2294    i++;
2295    if (n & 8) {
2296        m_mant[i >> 5] |= 1 << (i & 31);
2297    }
2298}
2299
2300
2301// ----------------------------------------------------------------------------
2302//  PRIVATE METHOD : shift_left
2303//
2304//  Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits.
2305// ----------------------------------------------------------------------------
2306
2307void
2308scfx_rep::shift_left(int n)
2309{
2310    if (n != 0) {
2311        int shift_left = n;
2312        int shift_right = bits_in_word - n;
2313
2314        SC_ASSERT_(!(m_mant[size() - 1] >> shift_right),
2315                   "shift_left overflow");
2316
2317        for (int i = size() - 1; i > 0; i--) {
2318            m_mant[i] = (m_mant[i] << shift_left) |
2319                        (m_mant[i - 1] >> shift_right);
2320        }
2321        m_mant[0] <<= shift_left;
2322    }
2323}
2324
2325
2326// ----------------------------------------------------------------------------
2327//  PRIVATE METHOD : shift_right
2328//
2329//  Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits.
2330// ----------------------------------------------------------------------------
2331
2332void
2333scfx_rep::shift_right(int n)
2334{
2335    if (n != 0) {
2336        int shift_left = bits_in_word - n;
2337        int shift_right = n;
2338
2339        SC_ASSERT_(!(m_mant[0] << shift_left), "shift_right overflow");
2340
2341        for (int i = 0; i < size() - 1; i++) {
2342            m_mant[i] = (m_mant[i] >> shift_right) |
2343                        (m_mant[i + 1] << shift_left);
2344        }
2345        m_mant[size() - 1] >>= shift_right;
2346    }
2347}
2348
2349
2350// ----------------------------------------------------------------------------
2351//  METHOD : get_bit
2352//
2353//  Tests a bit, in two's complement.
2354// ----------------------------------------------------------------------------
2355
2356bool
2357scfx_rep::get_bit(int i) const
2358{
2359    if (!is_normal())
2360        return false;
2361
2362    scfx_index x = calc_indices(i);
2363
2364    if (x.wi() >= size())
2365        return is_neg();
2366
2367    if (x.wi() < 0)
2368        return false;
2369
2370    const_cast<scfx_rep*>(this)->toggle_tc();
2371
2372    bool result = (m_mant[x.wi()] & (1 << x.bi())) != 0;
2373
2374    const_cast<scfx_rep *>(this)->toggle_tc();
2375
2376    return result;
2377}
2378
2379
2380// ----------------------------------------------------------------------------
2381//  METHOD : set
2382//
2383//  Sets a bit, in two's complement, between iwl-1 and -fwl.
2384// ----------------------------------------------------------------------------
2385
2386bool
2387scfx_rep::set(int i, const scfx_params &params)
2388{
2389    if (!is_normal())
2390        return false;
2391
2392    scfx_index x = calc_indices(i);
2393
2394    if (x.wi() >= size()) {
2395        if (is_neg())
2396            return true;
2397        else
2398            resize_to(x.wi() + 1, 1);
2399    } else if (x.wi() < 0) {
2400        resize_to(size() - x.wi(), -1);
2401        x.wi(0);
2402    }
2403
2404    toggle_tc();
2405
2406    m_mant[x.wi()] |= 1 << x.bi();
2407
2408    if (i == params.iwl() - 1)
2409        o_extend(x, params.enc()); // sign extension
2410
2411    toggle_tc();
2412
2413    find_sw();
2414
2415    return true;
2416}
2417
2418
2419// ----------------------------------------------------------------------------
2420//  METHOD : clear
2421//
2422//  Clears a bit, in two's complement, between iwl-1 and -fwl.
2423// ----------------------------------------------------------------------------
2424
2425bool
2426scfx_rep::clear(int i, const scfx_params &params)
2427{
2428    if (!is_normal())
2429        return false;
2430
2431    scfx_index x = calc_indices(i);
2432
2433    if (x.wi() >= size()) {
2434        if (!is_neg())
2435            return true;
2436        else
2437            resize_to(x.wi() + 1, 1);
2438    } else if (x.wi() < 0) {
2439        return true;
2440    }
2441
2442    toggle_tc();
2443
2444    m_mant[x.wi()] &= ~(1 << x.bi());
2445
2446    if (i == params.iwl() - 1)
2447        o_extend(x, params.enc()); // sign extension
2448
2449    toggle_tc();
2450
2451    find_sw();
2452
2453    return true;
2454}
2455
2456
2457// ----------------------------------------------------------------------------
2458//  METHOD : get_slice
2459// ----------------------------------------------------------------------------
2460
2461bool
2462scfx_rep::get_slice(int i, int j, const scfx_params &, sc_bv_base &bv) const
2463{
2464    if (is_nan() || is_inf())
2465        return false;
2466
2467    // get the bits
2468
2469    int l = j;
2470    for (int k = 0; k < bv.length(); ++k) {
2471        bv[k] = get_bit(l);
2472
2473        if (i >= j)
2474            ++l;
2475        else
2476            --l;
2477    }
2478
2479    return true;
2480}
2481
2482bool
2483scfx_rep::set_slice(int i, int j, const scfx_params &params,
2484                    const sc_bv_base &bv)
2485{
2486    if (is_nan() || is_inf())
2487        return false;
2488
2489    // set the bits
2490    int l = j;
2491    for (int k = 0; k < bv.length(); ++k) {
2492        if (bv[k].to_bool())
2493            set(l, params);
2494        else
2495            clear(l, params);
2496
2497        if (i >= j)
2498            ++l;
2499        else
2500            --l;
2501    }
2502
2503    return true;
2504}
2505
2506
2507// ----------------------------------------------------------------------------
2508//  METHOD : print
2509// ----------------------------------------------------------------------------
2510
2511void
2512scfx_rep::print(::std::ostream &os) const
2513{
2514    os << to_string(SC_DEC, -1, SC_E);
2515}
2516
2517
2518// ----------------------------------------------------------------------------
2519//  METHOD : dump
2520// ----------------------------------------------------------------------------
2521
2522void
2523scfx_rep::dump(::std::ostream &os) const
2524{
2525    os << "scfx_rep" << ::std::endl;
2526    os << "(" << ::std::endl;
2527
2528    os << "mant  =" << ::std::endl;
2529    for (int i = size() - 1; i >= 0; i--) {
2530        char buf[BUFSIZ];
2531        std::sprintf(buf, " %d: %10u (%8x)", i,
2532                     (int)m_mant[i], (int)m_mant[i]);
2533        os << buf << ::std::endl;
2534    }
2535
2536    os << "wp = " << m_wp << ::std::endl;
2537    os << "sign = " << m_sign << ::std::endl;
2538
2539    os << "state = ";
2540    switch (m_state) {
2541      case normal:
2542        os << "normal";
2543        break;
2544      case infinity:
2545        os << "infinity";
2546        break;
2547      case not_a_number:
2548        os << "not_a_number";
2549        break;
2550      default:
2551        os << "unknown";
2552    }
2553    os << ::std::endl;
2554
2555    os << "msw = " << m_msw << ::std::endl;
2556    os << "lsw = " << m_lsw << ::std::endl;
2557
2558    os << ")" << ::std::endl;
2559}
2560
2561
2562// ----------------------------------------------------------------------------
2563//  METHOD : get_type
2564// ----------------------------------------------------------------------------
2565
2566void
2567scfx_rep::get_type(int &wl, int &iwl, sc_enc &enc) const
2568{
2569    if (is_nan() || is_inf()) {
2570        wl  = 0;
2571        iwl = 0;
2572        enc = SC_TC_;
2573        return;
2574    }
2575
2576    if (is_zero()) {
2577        wl  = 1;
2578        iwl = 1;
2579        enc = SC_US_;
2580        return;
2581    }
2582
2583    int msb = (m_msw - m_wp) * bits_in_word +
2584              scfx_find_msb(m_mant[ m_msw ]) + 1;
2585    while (get_bit(msb) == get_bit(msb - 1)) {
2586        --msb;
2587    }
2588
2589    int lsb = (m_lsw - m_wp) * bits_in_word +
2590              scfx_find_lsb(m_mant[m_lsw]);
2591
2592    if (is_neg()) {
2593        wl  = msb - lsb + 1;
2594        iwl = msb + 1;
2595        enc = SC_TC_;
2596    } else {
2597        wl  = msb - lsb;
2598        iwl = msb;
2599        enc = SC_US_;
2600    }
2601}
2602
2603
2604// ----------------------------------------------------------------------------
2605//  PRIVATE METHOD : round
2606//
2607//  Performs convergent rounding (rounding to even) as in floating-point.
2608// ----------------------------------------------------------------------------
2609
2610void
2611scfx_rep::round(int wl)
2612{
2613    // check for special cases
2614
2615    if (is_nan() || is_inf() || is_zero())
2616        return;
2617
2618    // estimate effective wordlength and compare
2619    int wl_effective;
2620    wl_effective = (m_msw - m_lsw + 1) * bits_in_word;
2621    if (wl_effective <= wl)
2622        return;
2623
2624    // calculate effective wordlength and compare
2625    int msb = scfx_find_msb(m_mant[m_msw]);
2626    int lsb = scfx_find_lsb(m_mant[m_lsw]);
2627    wl_effective = (m_msw * bits_in_word + msb) -
2628                   (m_lsw * bits_in_word + lsb) + 1;
2629    if (wl_effective <= wl)
2630        return;
2631
2632    // perform rounding
2633    int wi = m_msw - (wl - 1) / bits_in_word;
2634    int bi = msb - (wl - 1) % bits_in_word;
2635    if (bi < 0) {
2636        --wi;
2637        bi += bits_in_word;
2638    }
2639
2640    scfx_index x(wi, bi);
2641
2642    if ((q_bit(x) && ! q_zero(x)) || (q_bit(x) && q_zero(x) && q_odd(x))) {
2643        q_incr(x);
2644    }
2645    q_clear(x);
2646
2647    find_sw();
2648
2649    m_r_flag = true;
2650}
2651
2652} // namespace sc_dt
2653