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