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

Generated on Tue Jun 18 2024 16:24:06 for gem5 by doxygen 1.11.0