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