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