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:
1081 SC_REPORT_FATAL("assertion failed", "unexpected sc_numrep");
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