scfx_rep.cpp revision 12027
16145Snate@binkert.org/***************************************************************************** 26145Snate@binkert.org 36145Snate@binkert.org Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 46145Snate@binkert.org more contributor license agreements. See the NOTICE file distributed 56145Snate@binkert.org with this work for additional information regarding copyright ownership. 66145Snate@binkert.org Accellera licenses this file to you under the Apache License, Version 2.0 76145Snate@binkert.org (the "License"); you may not use this file except in compliance with the 86145Snate@binkert.org License. You may obtain a copy of the License at 96145Snate@binkert.org 106145Snate@binkert.org http://www.apache.org/licenses/LICENSE-2.0 116145Snate@binkert.org 126145Snate@binkert.org Unless required by applicable law or agreed to in writing, software 136145Snate@binkert.org distributed under the License is distributed on an "AS IS" BASIS, 146145Snate@binkert.org WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 156145Snate@binkert.org implied. See the License for the specific language governing 166145Snate@binkert.org permissions and limitations under the License. 176145Snate@binkert.org 186145Snate@binkert.org *****************************************************************************/ 196145Snate@binkert.org 206145Snate@binkert.org/***************************************************************************** 216145Snate@binkert.org 226145Snate@binkert.org scfx_rep.cpp - 236145Snate@binkert.org 246145Snate@binkert.org Original Author: Robert Graulich, Synopsys, Inc. 256145Snate@binkert.org Martin Janssen, Synopsys, Inc. 266145Snate@binkert.org 276145Snate@binkert.org *****************************************************************************/ 286145Snate@binkert.org 297832Snate@binkert.org/***************************************************************************** 307547SBrad.Beckmann@amd.com 317547SBrad.Beckmann@amd.com MODIFICATION LOG - modifiers, enter your name, affiliation, date and 328645Snilay@cs.wisc.edu changes you are making here. 337454Snate@binkert.org 347054Snate@binkert.org Name, Affiliation, Date: 357054Snate@binkert.org Description of Modification: 367054Snate@binkert.org 378257SBrad.Beckmann@amd.com *****************************************************************************/ 388258SBrad.Beckmann@amd.com 396154Snate@binkert.org 407054Snate@binkert.org// $Log: scfx_rep.cpp,v $ 417547SBrad.Beckmann@amd.com// Revision 1.4 2011/08/24 22:05:43 acg 428255SBrad.Beckmann@amd.com// Torsten Maehne: initialization changes to remove warnings. 436154Snate@binkert.org// 446154Snate@binkert.org// Revision 1.3 2011/08/15 16:43:24 acg 456145Snate@binkert.org// Torsten Maehne: changes to remove unused argument warnings. 467055Snate@binkert.org// 477454Snate@binkert.org// Revision 1.2 2009/02/28 00:26:20 acg 487055Snate@binkert.org// Andy Goodrich: bug fixes. 496876Ssteve.reinhardt@amd.com// 506876Ssteve.reinhardt@amd.com// Revision 1.2 2008/11/06 17:22:47 acg 516285Snate@binkert.org// Andy Goodrich: bug fixes for 2.2.1. 528259SBrad.Beckmann@amd.com// 538259SBrad.Beckmann@amd.com// Revision 1.1.1.1 2006/12/15 20:31:36 acg 548259SBrad.Beckmann@amd.com// SystemC 2.2 558259SBrad.Beckmann@amd.com// 567054Snate@binkert.org// Revision 1.3 2006/01/13 18:53:58 acg 577054Snate@binkert.org// Andy Goodrich: added $Log command so that CVS comments are reproduced in 587054Snate@binkert.org// the source. 596285Snate@binkert.org// 607454Snate@binkert.org 616285Snate@binkert.org#include "sysc/utils/sc_machine.h" 627454Snate@binkert.org#include "sysc/datatypes/fx/scfx_rep.h" 637454Snate@binkert.org 647054Snate@binkert.org#include "sysc/datatypes/fx/scfx_ieee.h" 657054Snate@binkert.org#include "sysc/datatypes/fx/scfx_pow10.h" 667054Snate@binkert.org#include "sysc/datatypes/fx/scfx_utils.h" 676285Snate@binkert.org 687054Snate@binkert.org#include "sysc/datatypes/bit/sc_bv_base.h" 697054Snate@binkert.org 707454Snate@binkert.org#include <ctype.h> 717454Snate@binkert.org#include <cstdio> 727054Snate@binkert.org#include <stdlib.h> 737454Snate@binkert.org#include <math.h> 747454Snate@binkert.org 757054Snate@binkert.org 767056Snate@binkert.orgnamespace sc_dt 777056Snate@binkert.org{ 787056Snate@binkert.org 797056Snate@binkert.org// ---------------------------------------------------------------------------- 807054Snate@binkert.org// some utilities 817054Snate@binkert.org// ---------------------------------------------------------------------------- 826881SBrad.Beckmann@amd.com 836285Snate@binkert.orgstatic scfx_pow10 pow10_fx; 847054Snate@binkert.org 857054Snate@binkert.orgstatic const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int; 866881SBrad.Beckmann@amd.com 877054Snate@binkert.orgstatic inline 886881SBrad.Beckmann@amd.comint 897054Snate@binkert.orgn_word( int x ) 907054Snate@binkert.org{ 917054Snate@binkert.org return ( x + bits_in_word - 1 ) / bits_in_word; 927054Snate@binkert.org} 937054Snate@binkert.org 947454Snate@binkert.org 957054Snate@binkert.org// ---------------------------------------------------------------------------- 966881SBrad.Beckmann@amd.com// CONSTRUCTORS 977054Snate@binkert.org// ---------------------------------------------------------------------------- 987054Snate@binkert.org 996285Snate@binkert.orgscfx_rep::scfx_rep() 1006145Snate@binkert.org: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 1017054Snate@binkert.org m_r_flag( false ) 1027054Snate@binkert.org{ 1036145Snate@binkert.org set_zero(); 1047054Snate@binkert.org} 1057054Snate@binkert.org 1067054Snate@binkert.orgscfx_rep::scfx_rep( int a ) 1077054Snate@binkert.org: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 1087054Snate@binkert.org m_r_flag( false ) 1096145Snate@binkert.org{ 1106145Snate@binkert.org if( a != 0 ) 1117054Snate@binkert.org { 1127054Snate@binkert.org m_mant.clear(); 1137054Snate@binkert.org m_wp = m_msw = m_lsw = 2; 1146145Snate@binkert.org m_state = normal; 1156145Snate@binkert.org if( a > 0 ) 1166145Snate@binkert.org { 1176145Snate@binkert.org m_mant[2] = a; 1187054Snate@binkert.org m_sign = 1; 1197454Snate@binkert.org } 1207454Snate@binkert.org else 1217054Snate@binkert.org { 1227454Snate@binkert.org m_mant[2] = -a; 1237454Snate@binkert.org m_sign = -1; 1247054Snate@binkert.org } 1256145Snate@binkert.org } 1266145Snate@binkert.org else 1276145Snate@binkert.org set_zero(); 1287054Snate@binkert.org} 1298257SBrad.Beckmann@amd.com 1308257SBrad.Beckmann@amd.comscfx_rep::scfx_rep( unsigned int a ) 1318257SBrad.Beckmann@amd.com: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 1328257SBrad.Beckmann@amd.com m_r_flag( false ) 1336145Snate@binkert.org{ 1347054Snate@binkert.org if( a != 0 ) 1357054Snate@binkert.org { 1367054Snate@binkert.org m_mant.clear(); 1377054Snate@binkert.org m_wp = m_msw = m_lsw = 2; 1387054Snate@binkert.org m_state = normal; 1397054Snate@binkert.org m_mant[2] = a; 1407054Snate@binkert.org m_sign = 1; 1417054Snate@binkert.org } 1427054Snate@binkert.org else 1438258SBrad.Beckmann@amd.com set_zero(); 1448258SBrad.Beckmann@amd.com} 1457054Snate@binkert.org 1468257SBrad.Beckmann@amd.comscfx_rep::scfx_rep( long a ) 1478258SBrad.Beckmann@amd.com: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 1488258SBrad.Beckmann@amd.com m_r_flag( false ) 1498257SBrad.Beckmann@amd.com{ 1506145Snate@binkert.org if( a != 0 ) 1516145Snate@binkert.org { 1526145Snate@binkert.org m_mant.clear(); 1536145Snate@binkert.org m_state = normal; 1547054Snate@binkert.org if ( a > 0 ) 1558257SBrad.Beckmann@amd.com { 1568257SBrad.Beckmann@amd.com m_sign = 1; 1578257SBrad.Beckmann@amd.com } 1588257SBrad.Beckmann@amd.com else 1596145Snate@binkert.org { 1607054Snate@binkert.org a = -a; 1617054Snate@binkert.org m_sign = -1; 1627054Snate@binkert.org } 1637054Snate@binkert.org# if defined(SC_LONG_64) 1647054Snate@binkert.org m_wp = 1; 1657054Snate@binkert.org m_mant[1] = static_cast<word>( a ); 1666145Snate@binkert.org m_mant[2] = static_cast<word>( a >> bits_in_word ); 1676145Snate@binkert.org find_sw(); 1686145Snate@binkert.org# else 1696145Snate@binkert.org m_wp = 2; 1707054Snate@binkert.org m_msw = 2; 1718257SBrad.Beckmann@amd.com m_lsw = 2; 1728257SBrad.Beckmann@amd.com m_mant[2] = a; 1738257SBrad.Beckmann@amd.com# endif 1748257SBrad.Beckmann@amd.com 1756145Snate@binkert.org } 1767054Snate@binkert.org else 1777054Snate@binkert.org set_zero(); 1787054Snate@binkert.org} 1797054Snate@binkert.org 1807054Snate@binkert.orgscfx_rep::scfx_rep( unsigned long a ) 1816145Snate@binkert.org: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 1827454Snate@binkert.org m_r_flag( false ) 1836145Snate@binkert.org{ 1847054Snate@binkert.org if( a != 0 ) 1857054Snate@binkert.org { 1867054Snate@binkert.org m_mant.clear(); 1877054Snate@binkert.org m_wp = m_msw = m_lsw = 2; 1887454Snate@binkert.org m_state = normal; 1897054Snate@binkert.org# if defined(SC_LONG_64) 1907454Snate@binkert.org m_wp = 1; 1917054Snate@binkert.org m_mant[1] = static_cast<word>( a ); 1927454Snate@binkert.org m_mant[2] = static_cast<word>( a >> bits_in_word ); 1937054Snate@binkert.org find_sw(); 1947054Snate@binkert.org# else 1958258SBrad.Beckmann@amd.com m_wp = 2; 1968258SBrad.Beckmann@amd.com m_msw = 2; 1977054Snate@binkert.org m_lsw = 2; 1987054Snate@binkert.org m_mant[2] = a; 1998258SBrad.Beckmann@amd.com# endif 2008258SBrad.Beckmann@amd.com m_sign = 1; 2017054Snate@binkert.org } 2027054Snate@binkert.org else 2037054Snate@binkert.org set_zero(); 2047054Snate@binkert.org} 2057054Snate@binkert.org 2067832Snate@binkert.orgscfx_rep::scfx_rep( double a ) 2077832Snate@binkert.org: m_mant( min_mant ), m_wp( 0 ), m_sign(), m_state( normal ), m_msw( 0 ), 2087054Snate@binkert.org m_lsw( 0 ), m_r_flag( false ) 2097054Snate@binkert.org{ 2107054Snate@binkert.org m_mant.clear(); 2117054Snate@binkert.org 2127054Snate@binkert.org scfx_ieee_double id( a ); 2137054Snate@binkert.org 2147054Snate@binkert.org m_sign = id.negative() ? -1 : 1; 2157054Snate@binkert.org 2168308Stushar@csail.mit.edu if( id.is_nan() ) 2178308Stushar@csail.mit.edu m_state = not_a_number; 2187054Snate@binkert.org else if( id.is_inf() ) 2197054Snate@binkert.org m_state = infinity; 2207054Snate@binkert.org else if( id.is_subnormal() ) 2217054Snate@binkert.org { 2227054Snate@binkert.org m_mant[0] = id.mantissa1(); 2237054Snate@binkert.org m_mant[1] = id.mantissa0(); 2248308Stushar@csail.mit.edu normalize( id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE ); 2258308Stushar@csail.mit.edu } 2267054Snate@binkert.org else if( id.is_normal() ) 2277054Snate@binkert.org { 2287054Snate@binkert.org m_mant[0] = id.mantissa1(); 2297054Snate@binkert.org m_mant[1] = id.mantissa0() | ( 1 << mantissa0_size ); 2307054Snate@binkert.org normalize( id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE ); 2317454Snate@binkert.org } 2327054Snate@binkert.org} 2337054Snate@binkert.org 2347054Snate@binkert.orgscfx_rep::scfx_rep( int64 a ) 2357054Snate@binkert.org: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 2367054Snate@binkert.org m_r_flag( false ) 2377054Snate@binkert.org{ 2387054Snate@binkert.org if( a != 0 ) 2397054Snate@binkert.org { 2407054Snate@binkert.org m_mant.clear(); 2417054Snate@binkert.org m_wp = 1; 2427054Snate@binkert.org m_state = normal; 2437054Snate@binkert.org if( a > 0 ) 2447054Snate@binkert.org { 2457054Snate@binkert.org m_mant[1] = static_cast<word>( a ); 2467054Snate@binkert.org m_mant[2] = static_cast<word>( a >> bits_in_word ); 2477547SBrad.Beckmann@amd.com m_sign = 1; 2487547SBrad.Beckmann@amd.com } 2497547SBrad.Beckmann@amd.com else 2507547SBrad.Beckmann@amd.com { 2517547SBrad.Beckmann@amd.com m_mant[1] = static_cast<word>( -a ); 2527547SBrad.Beckmann@amd.com m_mant[2] = static_cast<word>( (-a) >> bits_in_word ); 2537547SBrad.Beckmann@amd.com m_sign = -1; 2547547SBrad.Beckmann@amd.com } 2557547SBrad.Beckmann@amd.com find_sw(); 2567547SBrad.Beckmann@amd.com } 2577547SBrad.Beckmann@amd.com else 2587547SBrad.Beckmann@amd.com set_zero(); 2597547SBrad.Beckmann@amd.com} 2607547SBrad.Beckmann@amd.com 2617547SBrad.Beckmann@amd.comscfx_rep::scfx_rep( uint64 a ) 2627547SBrad.Beckmann@amd.com: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 2637547SBrad.Beckmann@amd.com m_r_flag( false ) 2647547SBrad.Beckmann@amd.com{ 2657547SBrad.Beckmann@amd.com if( a != 0 ) 2667547SBrad.Beckmann@amd.com { 2677547SBrad.Beckmann@amd.com m_mant.clear(); 2687547SBrad.Beckmann@amd.com m_wp = 1; 2697547SBrad.Beckmann@amd.com m_state = normal; 2707547SBrad.Beckmann@amd.com m_mant[1] = static_cast<word>( a ); 2717547SBrad.Beckmann@amd.com m_mant[2] = static_cast<word>( a >> bits_in_word ); 2727547SBrad.Beckmann@amd.com m_sign = 1; 2737547SBrad.Beckmann@amd.com find_sw(); 2747547SBrad.Beckmann@amd.com } 2757547SBrad.Beckmann@amd.com else 2767547SBrad.Beckmann@amd.com set_zero(); 2777547SBrad.Beckmann@amd.com} 2787547SBrad.Beckmann@amd.com 2797547SBrad.Beckmann@amd.comscfx_rep::scfx_rep( const sc_signed& a ) 2807547SBrad.Beckmann@amd.com: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 2817547SBrad.Beckmann@amd.com m_r_flag( false ) 2827547SBrad.Beckmann@amd.com{ 2837547SBrad.Beckmann@amd.com if( a.iszero() ) 2847547SBrad.Beckmann@amd.com set_zero(); 2857547SBrad.Beckmann@amd.com else 2867547SBrad.Beckmann@amd.com { 2877547SBrad.Beckmann@amd.com int words = n_word( a.length() ); 2887547SBrad.Beckmann@amd.com if( words > size() ) 2897547SBrad.Beckmann@amd.com resize_to( words ); 2907547SBrad.Beckmann@amd.com m_mant.clear(); 2917547SBrad.Beckmann@amd.com m_wp = 0; 2927547SBrad.Beckmann@amd.com m_state = normal; 2937547SBrad.Beckmann@amd.com if( a.sign() ) 2947547SBrad.Beckmann@amd.com { 2957547SBrad.Beckmann@amd.com sc_signed a2 = -a; 2967547SBrad.Beckmann@amd.com for( int i = 0; i < a2.length(); ++ i ) 2977547SBrad.Beckmann@amd.com { 2987547SBrad.Beckmann@amd.com if( a2[i] ) 2997547SBrad.Beckmann@amd.com { 3007547SBrad.Beckmann@amd.com scfx_index x = calc_indices( i ); 3017547SBrad.Beckmann@amd.com m_mant[x.wi()] |= 1 << x.bi(); 3027054Snate@binkert.org } 3037054Snate@binkert.org } 3047054Snate@binkert.org m_sign = -1; 3057054Snate@binkert.org } 3067054Snate@binkert.org else 3077054Snate@binkert.org { 3087054Snate@binkert.org for( int i = 0; i < a.length(); ++ i ) 3097054Snate@binkert.org { 3107054Snate@binkert.org if( a[i] ) 3117054Snate@binkert.org { 3127054Snate@binkert.org scfx_index x = calc_indices( i ); 3137054Snate@binkert.org m_mant[x.wi()] |= 1 << x.bi(); 3147054Snate@binkert.org } 3157054Snate@binkert.org } 3167054Snate@binkert.org m_sign = 1; 3177054Snate@binkert.org } 3187054Snate@binkert.org find_sw(); 3197054Snate@binkert.org } 3207054Snate@binkert.org} 3217054Snate@binkert.org 3227054Snate@binkert.orgscfx_rep::scfx_rep( const sc_unsigned& a ) 3237054Snate@binkert.org: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 3247054Snate@binkert.org m_r_flag( false ) 3257054Snate@binkert.org{ 3267054Snate@binkert.org if( a.iszero() ) 3277054Snate@binkert.org set_zero(); 3287054Snate@binkert.org else 3297054Snate@binkert.org { 3307054Snate@binkert.org int words = n_word( a.length() ); 3317054Snate@binkert.org if( words > size() ) 3327054Snate@binkert.org resize_to( words ); 3337054Snate@binkert.org m_mant.clear(); 3347054Snate@binkert.org m_wp = 0; 3357054Snate@binkert.org m_state = normal; 3367054Snate@binkert.org for( int i = 0; i < a.length(); ++ i ) 3377054Snate@binkert.org { 3387054Snate@binkert.org if( a[i] ) 3397054Snate@binkert.org { 3407054Snate@binkert.org scfx_index x = calc_indices( i ); 3417054Snate@binkert.org m_mant[x.wi()] |= 1 << x.bi(); 3427054Snate@binkert.org } 3437054Snate@binkert.org } 3446145Snate@binkert.org m_sign = 1; 3456145Snate@binkert.org find_sw(); 3467054Snate@binkert.org } 3476145Snate@binkert.org} 3486145Snate@binkert.org 3497054Snate@binkert.org 3507054Snate@binkert.org// copy constructor 3516145Snate@binkert.org 3527054Snate@binkert.orgscfx_rep::scfx_rep( const scfx_rep& a ) 3536145Snate@binkert.org: m_mant( a.m_mant ), m_wp( a.m_wp ), m_sign( a.m_sign ), m_state( a.m_state ), 3546876Ssteve.reinhardt@amd.com m_msw( a.m_msw ), m_lsw( a.m_lsw ), m_r_flag( false ) 3556876Ssteve.reinhardt@amd.com{} 3566876Ssteve.reinhardt@amd.com 3576876Ssteve.reinhardt@amd.com 3586876Ssteve.reinhardt@amd.com// ---------------------------------------------------------------------------- 3596876Ssteve.reinhardt@amd.com// OPERATORS : new, delete 3606876Ssteve.reinhardt@amd.com// 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