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