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:
|
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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms) 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 ¶ms) 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 ¶ms, 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
|