scfx_rep.cc revision 13322
112854Sgabeblack@google.com/***************************************************************************** 212854Sgabeblack@google.com 312854Sgabeblack@google.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 412854Sgabeblack@google.com more contributor license agreements. See the NOTICE file distributed 512854Sgabeblack@google.com with this work for additional information regarding copyright ownership. 612854Sgabeblack@google.com Accellera licenses this file to you under the Apache License, Version 2.0 712854Sgabeblack@google.com (the "License"); you may not use this file except in compliance with the 812854Sgabeblack@google.com License. You may obtain a copy of the License at 912854Sgabeblack@google.com 1012854Sgabeblack@google.com http://www.apache.org/licenses/LICENSE-2.0 1112854Sgabeblack@google.com 1212854Sgabeblack@google.com Unless required by applicable law or agreed to in writing, software 1312854Sgabeblack@google.com distributed under the License is distributed on an "AS IS" BASIS, 1412854Sgabeblack@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1512854Sgabeblack@google.com implied. See the License for the specific language governing 1612854Sgabeblack@google.com permissions and limitations under the License. 1712854Sgabeblack@google.com 1812854Sgabeblack@google.com *****************************************************************************/ 1912854Sgabeblack@google.com 2012854Sgabeblack@google.com/***************************************************************************** 2112854Sgabeblack@google.com 2212854Sgabeblack@google.com scfx_rep.cpp - 2312854Sgabeblack@google.com 2412854Sgabeblack@google.com Original Author: Robert Graulich, Synopsys, Inc. 2512854Sgabeblack@google.com Martin Janssen, Synopsys, Inc. 2612854Sgabeblack@google.com 2712854Sgabeblack@google.com *****************************************************************************/ 2812854Sgabeblack@google.com 2912854Sgabeblack@google.com/***************************************************************************** 3012854Sgabeblack@google.com 3112854Sgabeblack@google.com MODIFICATION LOG - modifiers, enter your name, affiliation, date and 3212854Sgabeblack@google.com changes you are making here. 3312854Sgabeblack@google.com 3412854Sgabeblack@google.com Name, Affiliation, Date: 3512854Sgabeblack@google.com Description of Modification: 3612854Sgabeblack@google.com 3712854Sgabeblack@google.com *****************************************************************************/ 3812854Sgabeblack@google.com 3912854Sgabeblack@google.com 4012854Sgabeblack@google.com// $Log: scfx_rep.cpp,v $ 4112854Sgabeblack@google.com// Revision 1.4 2011/08/24 22:05:43 acg 4212854Sgabeblack@google.com// Torsten Maehne: initialization changes to remove warnings. 4312854Sgabeblack@google.com// 4412854Sgabeblack@google.com// Revision 1.3 2011/08/15 16:43:24 acg 4512854Sgabeblack@google.com// Torsten Maehne: changes to remove unused argument warnings. 4612854Sgabeblack@google.com// 4712854Sgabeblack@google.com// Revision 1.2 2009/02/28 00:26:20 acg 4812854Sgabeblack@google.com// Andy Goodrich: bug fixes. 4912854Sgabeblack@google.com// 5012854Sgabeblack@google.com// Revision 1.2 2008/11/06 17:22:47 acg 5112854Sgabeblack@google.com// Andy Goodrich: bug fixes for 2.2.1. 5212854Sgabeblack@google.com// 5312854Sgabeblack@google.com// Revision 1.1.1.1 2006/12/15 20:31:36 acg 5412854Sgabeblack@google.com// SystemC 2.2 5512854Sgabeblack@google.com// 5612854Sgabeblack@google.com// Revision 1.3 2006/01/13 18:53:58 acg 5712854Sgabeblack@google.com// Andy Goodrich: added $Log command so that CVS comments are reproduced in 5812854Sgabeblack@google.com// the source. 5912854Sgabeblack@google.com// 6012854Sgabeblack@google.com 6112854Sgabeblack@google.com#include <cctype> 6212854Sgabeblack@google.com#include <cmath> 6312854Sgabeblack@google.com#include <cstdio> 6412854Sgabeblack@google.com#include <cstdlib> 6512854Sgabeblack@google.com 6612854Sgabeblack@google.com#include "base/compiler.hh" 6712854Sgabeblack@google.com#include "systemc/ext/dt/bit/sc_bv_base.hh" 6812854Sgabeblack@google.com#include "systemc/ext/dt/bit/sc_lv_base.hh" 6912854Sgabeblack@google.com#include "systemc/ext/dt/fx/scfx_ieee.hh" 7012854Sgabeblack@google.com#include "systemc/ext/dt/fx/scfx_pow10.hh" 7112854Sgabeblack@google.com#include "systemc/ext/dt/fx/scfx_rep.hh" 7212854Sgabeblack@google.com#include "systemc/ext/dt/fx/scfx_utils.hh" 7312854Sgabeblack@google.com#include "systemc/ext/utils/endian.hh" 7413322Sgabeblack@google.com#include "systemc/ext/utils/messages.hh" 7512854Sgabeblack@google.com 7612854Sgabeblack@google.comnamespace sc_dt 7712854Sgabeblack@google.com{ 7812854Sgabeblack@google.com 7912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 8012854Sgabeblack@google.com// some utilities 8112854Sgabeblack@google.com// ---------------------------------------------------------------------------- 8212854Sgabeblack@google.com 8312854Sgabeblack@google.comstatic scfx_pow10 pow10_fx; 8412854Sgabeblack@google.com 8512854Sgabeblack@google.comstatic const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int; 8612854Sgabeblack@google.com 8712854Sgabeblack@google.comstatic inline int 8812854Sgabeblack@google.comn_word(int x) 8912854Sgabeblack@google.com{ 9012854Sgabeblack@google.com return (x + bits_in_word - 1) / bits_in_word; 9112854Sgabeblack@google.com} 9212854Sgabeblack@google.com 9312854Sgabeblack@google.com 9412854Sgabeblack@google.com// ---------------------------------------------------------------------------- 9512854Sgabeblack@google.com// CONSTRUCTORS 9612854Sgabeblack@google.com// ---------------------------------------------------------------------------- 9712854Sgabeblack@google.com 9812854Sgabeblack@google.comscfx_rep::scfx_rep() : 9912854Sgabeblack@google.com m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 10012854Sgabeblack@google.com m_r_flag(false) 10112854Sgabeblack@google.com{ 10212854Sgabeblack@google.com set_zero(); 10312854Sgabeblack@google.com} 10412854Sgabeblack@google.com 10512854Sgabeblack@google.comscfx_rep::scfx_rep(int a) : m_mant(min_mant), m_wp(), m_sign(), m_state(), 10612854Sgabeblack@google.com m_msw(), m_lsw(), m_r_flag(false) 10712854Sgabeblack@google.com{ 10812854Sgabeblack@google.com if (a != 0) { 10912854Sgabeblack@google.com m_mant.clear(); 11012854Sgabeblack@google.com m_wp = m_msw = m_lsw = 2; 11112854Sgabeblack@google.com m_state = normal; 11212854Sgabeblack@google.com if (a > 0) { 11312854Sgabeblack@google.com m_mant[2] = a; 11412854Sgabeblack@google.com m_sign = 1; 11512854Sgabeblack@google.com } else { 11612854Sgabeblack@google.com m_mant[2] = -a; 11712854Sgabeblack@google.com m_sign = -1; 11812854Sgabeblack@google.com } 11912854Sgabeblack@google.com } else { 12012854Sgabeblack@google.com set_zero(); 12112854Sgabeblack@google.com } 12212854Sgabeblack@google.com} 12312854Sgabeblack@google.com 12412854Sgabeblack@google.comscfx_rep::scfx_rep(unsigned int a) : m_mant(min_mant), m_wp(), m_sign(), 12512854Sgabeblack@google.com m_state(), m_msw(), m_lsw(), m_r_flag(false) 12612854Sgabeblack@google.com{ 12712854Sgabeblack@google.com if (a != 0) { 12812854Sgabeblack@google.com m_mant.clear(); 12912854Sgabeblack@google.com m_wp = m_msw = m_lsw = 2; 13012854Sgabeblack@google.com m_state = normal; 13112854Sgabeblack@google.com m_mant[2] = a; 13212854Sgabeblack@google.com m_sign = 1; 13312854Sgabeblack@google.com } else { 13412854Sgabeblack@google.com set_zero(); 13512854Sgabeblack@google.com } 13612854Sgabeblack@google.com} 13712854Sgabeblack@google.com 13812854Sgabeblack@google.comscfx_rep::scfx_rep(long a) : 13912854Sgabeblack@google.com m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 14012854Sgabeblack@google.com m_r_flag(false) 14112854Sgabeblack@google.com{ 14212854Sgabeblack@google.com if (a != 0) { 14312854Sgabeblack@google.com m_mant.clear(); 14412854Sgabeblack@google.com m_state = normal; 14512854Sgabeblack@google.com if (a > 0) { 14612854Sgabeblack@google.com m_sign = 1; 14712854Sgabeblack@google.com } else { 14812854Sgabeblack@google.com a = -a; 14912854Sgabeblack@google.com m_sign = -1; 15012854Sgabeblack@google.com } 15113197Sgabeblack@google.com# if SC_LONG_64 15212854Sgabeblack@google.com m_wp = 1; 15312854Sgabeblack@google.com m_mant[1] = static_cast<word>(a); 15412854Sgabeblack@google.com m_mant[2] = static_cast<word>(a >> bits_in_word); 15512854Sgabeblack@google.com find_sw(); 15612854Sgabeblack@google.com# else 15712854Sgabeblack@google.com m_wp = 2; 15812854Sgabeblack@google.com m_msw = 2; 15912854Sgabeblack@google.com m_lsw = 2; 16012854Sgabeblack@google.com m_mant[2] = a; 16112854Sgabeblack@google.com# endif 16212854Sgabeblack@google.com } else { 16312854Sgabeblack@google.com set_zero(); 16412854Sgabeblack@google.com } 16512854Sgabeblack@google.com} 16612854Sgabeblack@google.com 16712854Sgabeblack@google.comscfx_rep::scfx_rep(unsigned long a) : 16812854Sgabeblack@google.com m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 16912854Sgabeblack@google.com m_r_flag(false) 17012854Sgabeblack@google.com{ 17112854Sgabeblack@google.com if (a != 0) { 17212854Sgabeblack@google.com m_mant.clear(); 17312854Sgabeblack@google.com m_wp = m_msw = m_lsw = 2; 17412854Sgabeblack@google.com m_state = normal; 17513197Sgabeblack@google.com# if SC_LONG_64 17612854Sgabeblack@google.com m_wp = 1; 17712854Sgabeblack@google.com m_mant[1] = static_cast<word>(a); 17812854Sgabeblack@google.com m_mant[2] = static_cast<word>(a >> bits_in_word); 17912854Sgabeblack@google.com find_sw(); 18012854Sgabeblack@google.com# else 18112854Sgabeblack@google.com m_wp = 2; 18212854Sgabeblack@google.com m_msw = 2; 18312854Sgabeblack@google.com m_lsw = 2; 18412854Sgabeblack@google.com m_mant[2] = a; 18512854Sgabeblack@google.com# endif 18612854Sgabeblack@google.com m_sign = 1; 18712854Sgabeblack@google.com } 18812854Sgabeblack@google.com else 18912854Sgabeblack@google.com set_zero(); 19012854Sgabeblack@google.com} 19112854Sgabeblack@google.com 19212854Sgabeblack@google.comscfx_rep::scfx_rep(double a) : 19312854Sgabeblack@google.com m_mant(min_mant), m_wp(0), m_sign(), m_state(normal), m_msw(0), 19412854Sgabeblack@google.com m_lsw(0), m_r_flag(false) 19512854Sgabeblack@google.com{ 19612854Sgabeblack@google.com m_mant.clear(); 19712854Sgabeblack@google.com 19812854Sgabeblack@google.com scfx_ieee_double id(a); 19912854Sgabeblack@google.com 20012854Sgabeblack@google.com m_sign = id.negative() ? -1 : 1; 20112854Sgabeblack@google.com 20212854Sgabeblack@google.com if (id.is_nan()) { 20312854Sgabeblack@google.com m_state = not_a_number; 20412854Sgabeblack@google.com } else if (id.is_inf()) { 20512854Sgabeblack@google.com m_state = infinity; 20612854Sgabeblack@google.com } else if (id.is_subnormal()) { 20712854Sgabeblack@google.com m_mant[0] = id.mantissa1(); 20812854Sgabeblack@google.com m_mant[1] = id.mantissa0(); 20912854Sgabeblack@google.com normalize(id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE); 21012854Sgabeblack@google.com } else if (id.is_normal()) { 21112854Sgabeblack@google.com m_mant[0] = id.mantissa1(); 21212854Sgabeblack@google.com m_mant[1] = id.mantissa0() | (1 << mantissa0_size); 21312854Sgabeblack@google.com normalize(id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE); 21412854Sgabeblack@google.com } 21512854Sgabeblack@google.com} 21612854Sgabeblack@google.com 21712854Sgabeblack@google.comscfx_rep::scfx_rep(int64 a) : 21812854Sgabeblack@google.com m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 21912854Sgabeblack@google.com m_r_flag(false) 22012854Sgabeblack@google.com{ 22112854Sgabeblack@google.com if (a != 0) { 22212854Sgabeblack@google.com m_mant.clear(); 22312854Sgabeblack@google.com m_wp = 1; 22412854Sgabeblack@google.com m_state = normal; 22512854Sgabeblack@google.com if (a > 0) { 22612854Sgabeblack@google.com m_mant[1] = static_cast<word>(a); 22712854Sgabeblack@google.com m_mant[2] = static_cast<word>(a >> bits_in_word); 22812854Sgabeblack@google.com m_sign = 1; 22912854Sgabeblack@google.com } else { 23012854Sgabeblack@google.com m_mant[1] = static_cast<word>(-a); 23112854Sgabeblack@google.com m_mant[2] = static_cast<word>((-a) >> bits_in_word); 23212854Sgabeblack@google.com m_sign = -1; 23312854Sgabeblack@google.com } 23412854Sgabeblack@google.com find_sw(); 23512854Sgabeblack@google.com } else { 23612854Sgabeblack@google.com set_zero(); 23712854Sgabeblack@google.com } 23812854Sgabeblack@google.com} 23912854Sgabeblack@google.com 24012854Sgabeblack@google.comscfx_rep::scfx_rep(uint64 a) : 24112854Sgabeblack@google.com m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 24212854Sgabeblack@google.com m_r_flag(false) 24312854Sgabeblack@google.com{ 24412854Sgabeblack@google.com if (a != 0) { 24512854Sgabeblack@google.com m_mant.clear(); 24612854Sgabeblack@google.com m_wp = 1; 24712854Sgabeblack@google.com m_state = normal; 24812854Sgabeblack@google.com m_mant[1] = static_cast<word>(a); 24912854Sgabeblack@google.com m_mant[2] = static_cast<word>(a >> bits_in_word); 25012854Sgabeblack@google.com m_sign = 1; 25112854Sgabeblack@google.com find_sw(); 25212854Sgabeblack@google.com } else { 25312854Sgabeblack@google.com set_zero(); 25412854Sgabeblack@google.com } 25512854Sgabeblack@google.com} 25612854Sgabeblack@google.com 25712854Sgabeblack@google.comscfx_rep::scfx_rep(const sc_signed &a) : 25812854Sgabeblack@google.com m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 25912854Sgabeblack@google.com m_r_flag(false) 26012854Sgabeblack@google.com{ 26112854Sgabeblack@google.com if (a.iszero()) { 26212854Sgabeblack@google.com set_zero(); 26312854Sgabeblack@google.com } else { 26412854Sgabeblack@google.com int words = n_word(a.length()); 26512854Sgabeblack@google.com if (words > size()) 26612854Sgabeblack@google.com resize_to(words); 26712854Sgabeblack@google.com m_mant.clear(); 26812854Sgabeblack@google.com m_wp = 0; 26912854Sgabeblack@google.com m_state = normal; 27012854Sgabeblack@google.com if (a.sign()) { 27112854Sgabeblack@google.com sc_signed a2 = -a; 27212854Sgabeblack@google.com for (int i = 0; i < a2.length(); ++i) { 27312854Sgabeblack@google.com if (a2[i]) { 27412854Sgabeblack@google.com scfx_index x = calc_indices(i); 27512854Sgabeblack@google.com m_mant[x.wi()] |= 1 << x.bi(); 27612854Sgabeblack@google.com } 27712854Sgabeblack@google.com } 27812854Sgabeblack@google.com m_sign = -1; 27912854Sgabeblack@google.com } else { 28012854Sgabeblack@google.com for (int i = 0; i < a.length(); ++i) { 28112854Sgabeblack@google.com if (a[i]) { 28212854Sgabeblack@google.com scfx_index x = calc_indices(i); 28312854Sgabeblack@google.com m_mant[x.wi()] |= 1 << x.bi(); 28412854Sgabeblack@google.com } 28512854Sgabeblack@google.com } 28612854Sgabeblack@google.com m_sign = 1; 28712854Sgabeblack@google.com } 28812854Sgabeblack@google.com find_sw(); 28912854Sgabeblack@google.com } 29012854Sgabeblack@google.com} 29112854Sgabeblack@google.com 29212854Sgabeblack@google.comscfx_rep::scfx_rep(const sc_unsigned &a) : 29312854Sgabeblack@google.com m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 29412854Sgabeblack@google.com m_r_flag(false) 29512854Sgabeblack@google.com{ 29612854Sgabeblack@google.com if (a.iszero()) { 29712854Sgabeblack@google.com set_zero(); 29812854Sgabeblack@google.com } else { 29912854Sgabeblack@google.com int words = n_word(a.length()); 30012854Sgabeblack@google.com if (words > size()) 30112854Sgabeblack@google.com resize_to(words); 30212854Sgabeblack@google.com m_mant.clear(); 30312854Sgabeblack@google.com m_wp = 0; 30412854Sgabeblack@google.com m_state = normal; 30512854Sgabeblack@google.com for (int i = 0; i < a.length(); ++i) { 30612854Sgabeblack@google.com if (a[i]) { 30712854Sgabeblack@google.com scfx_index x = calc_indices(i); 30812854Sgabeblack@google.com m_mant[x.wi()] |= 1 << x.bi(); 30912854Sgabeblack@google.com } 31012854Sgabeblack@google.com } 31112854Sgabeblack@google.com m_sign = 1; 31212854Sgabeblack@google.com find_sw(); 31312854Sgabeblack@google.com } 31412854Sgabeblack@google.com} 31512854Sgabeblack@google.com 31612854Sgabeblack@google.com// copy constructor 31712854Sgabeblack@google.comscfx_rep::scfx_rep(const scfx_rep &a) : 31812854Sgabeblack@google.com m_mant(a.m_mant), m_wp(a.m_wp), m_sign(a.m_sign), m_state(a.m_state), 31912854Sgabeblack@google.com m_msw(a.m_msw), m_lsw(a.m_lsw), m_r_flag(false) 32012854Sgabeblack@google.com{} 32112854Sgabeblack@google.com 32212854Sgabeblack@google.com 32312854Sgabeblack@google.com// ---------------------------------------------------------------------------- 32412854Sgabeblack@google.com// OPERATORS : new, delete 32512854Sgabeblack@google.com// 32612854Sgabeblack@google.com// Memory management for class scfx_rep. 32712854Sgabeblack@google.com// ---------------------------------------------------------------------------- 32812854Sgabeblack@google.com 32912854Sgabeblack@google.comunion scfx_rep_node 33012854Sgabeblack@google.com{ 33112854Sgabeblack@google.com char data[sizeof(scfx_rep)]; 33212854Sgabeblack@google.com scfx_rep_node *next; 33312854Sgabeblack@google.com}; 33412854Sgabeblack@google.com 33512854Sgabeblack@google.comstatic scfx_rep_node *list = 0; 33612854Sgabeblack@google.com 33712854Sgabeblack@google.comvoid * 33812854Sgabeblack@google.comscfx_rep::operator new(std::size_t size) 33912854Sgabeblack@google.com{ 34012854Sgabeblack@google.com const int ALLOC_SIZE = 1024; 34112854Sgabeblack@google.com 34212854Sgabeblack@google.com if (size != sizeof(scfx_rep)) 34312854Sgabeblack@google.com return ::operator new(size); 34412854Sgabeblack@google.com 34512854Sgabeblack@google.com if (!list) { 34612854Sgabeblack@google.com list = new scfx_rep_node[ALLOC_SIZE]; 34712854Sgabeblack@google.com for (int i = 0; i < ALLOC_SIZE - 1; i++) 34812854Sgabeblack@google.com list[i].next = list + i + 1; 34912854Sgabeblack@google.com list[ALLOC_SIZE - 1].next = 0; 35012854Sgabeblack@google.com } 35112854Sgabeblack@google.com 35212854Sgabeblack@google.com scfx_rep *ptr = reinterpret_cast<scfx_rep *>(list->data); 35312854Sgabeblack@google.com list = list->next; 35412854Sgabeblack@google.com 35512854Sgabeblack@google.com return ptr; 35612854Sgabeblack@google.com} 35712854Sgabeblack@google.com 35812854Sgabeblack@google.comvoid 35912854Sgabeblack@google.comscfx_rep::operator delete(void *ptr, std::size_t size) 36012854Sgabeblack@google.com{ 36112854Sgabeblack@google.com if (size != sizeof(scfx_rep)) { 36212854Sgabeblack@google.com ::operator delete(ptr); 36312854Sgabeblack@google.com return; 36412854Sgabeblack@google.com } 36512854Sgabeblack@google.com 36612854Sgabeblack@google.com scfx_rep_node *node = static_cast<scfx_rep_node *>(ptr); 36712854Sgabeblack@google.com node->next = list; 36812854Sgabeblack@google.com list = node; 36912854Sgabeblack@google.com} 37012854Sgabeblack@google.com 37112854Sgabeblack@google.com 37212854Sgabeblack@google.com// ---------------------------------------------------------------------------- 37312854Sgabeblack@google.com// METHOD : from_string 37412854Sgabeblack@google.com// 37512854Sgabeblack@google.com// Convert from character string to sc_fxrep. 37612854Sgabeblack@google.com// ---------------------------------------------------------------------------- 37712854Sgabeblack@google.com 37812854Sgabeblack@google.com#define SCFX_FAIL_IF_(cnd) \ 37912854Sgabeblack@google.com{ \ 38012854Sgabeblack@google.com if ((cnd)) { \ 38112854Sgabeblack@google.com m_state = not_a_number; \ 38212854Sgabeblack@google.com m_mant.clear(); /* to avoid Purify UMRs during assignment */ \ 38312854Sgabeblack@google.com return; \ 38412854Sgabeblack@google.com } \ 38512854Sgabeblack@google.com} 38612854Sgabeblack@google.com 38712854Sgabeblack@google.comvoid 38812854Sgabeblack@google.comscfx_rep::from_string(const char *s, int cte_wl) 38912854Sgabeblack@google.com{ 39012854Sgabeblack@google.com SCFX_FAIL_IF_(s == 0 || *s == 0); 39112854Sgabeblack@google.com 39212854Sgabeblack@google.com scfx_string s2; 39312854Sgabeblack@google.com s2 += s; 39412854Sgabeblack@google.com s2 += '\0'; 39512854Sgabeblack@google.com 39612854Sgabeblack@google.com bool sign_char; 39712854Sgabeblack@google.com m_sign = scfx_parse_sign(s, sign_char); 39812854Sgabeblack@google.com 39912854Sgabeblack@google.com sc_numrep numrep = scfx_parse_prefix(s); 40012854Sgabeblack@google.com 40112854Sgabeblack@google.com int base = 0; 40212854Sgabeblack@google.com 40312854Sgabeblack@google.com switch (numrep) { 40412854Sgabeblack@google.com case SC_DEC: 40512854Sgabeblack@google.com { 40612854Sgabeblack@google.com base = 10; 40712854Sgabeblack@google.com if (scfx_is_nan(s)) { // special case: NaN 40812854Sgabeblack@google.com m_state = not_a_number; 40912854Sgabeblack@google.com m_mant.clear(); /* to avoid Purify UMRs during assignment */ 41012854Sgabeblack@google.com return; 41112854Sgabeblack@google.com } 41212854Sgabeblack@google.com if (scfx_is_inf(s)) { // special case: Infinity 41312854Sgabeblack@google.com m_state = infinity; 41412854Sgabeblack@google.com m_mant.clear(); /* to avoid Purify UMRs during assignment */ 41512854Sgabeblack@google.com return; 41612854Sgabeblack@google.com } 41712854Sgabeblack@google.com break; 41812854Sgabeblack@google.com } 41912854Sgabeblack@google.com case SC_BIN: 42012854Sgabeblack@google.com case SC_BIN_US: 42112854Sgabeblack@google.com { 42212854Sgabeblack@google.com SCFX_FAIL_IF_(sign_char); 42312854Sgabeblack@google.com base = 2; 42412854Sgabeblack@google.com break; 42512854Sgabeblack@google.com } 42612854Sgabeblack@google.com 42712854Sgabeblack@google.com case SC_BIN_SM: 42812854Sgabeblack@google.com { 42912854Sgabeblack@google.com base = 2; 43012854Sgabeblack@google.com break; 43112854Sgabeblack@google.com } 43212854Sgabeblack@google.com case SC_OCT: 43312854Sgabeblack@google.com case SC_OCT_US: 43412854Sgabeblack@google.com { 43512854Sgabeblack@google.com SCFX_FAIL_IF_(sign_char); 43612854Sgabeblack@google.com base = 8; 43712854Sgabeblack@google.com break; 43812854Sgabeblack@google.com } 43912854Sgabeblack@google.com case SC_OCT_SM: 44012854Sgabeblack@google.com { 44112854Sgabeblack@google.com base = 8; 44212854Sgabeblack@google.com break; 44312854Sgabeblack@google.com } 44412854Sgabeblack@google.com case SC_HEX: 44512854Sgabeblack@google.com case SC_HEX_US: 44612854Sgabeblack@google.com { 44712854Sgabeblack@google.com SCFX_FAIL_IF_(sign_char); 44812854Sgabeblack@google.com base = 16; 44912854Sgabeblack@google.com break; 45012854Sgabeblack@google.com } 45112854Sgabeblack@google.com case SC_HEX_SM: 45212854Sgabeblack@google.com { 45312854Sgabeblack@google.com base = 16; 45412854Sgabeblack@google.com break; 45512854Sgabeblack@google.com } 45612854Sgabeblack@google.com case SC_CSD: 45712854Sgabeblack@google.com { 45812854Sgabeblack@google.com SCFX_FAIL_IF_(sign_char); 45912854Sgabeblack@google.com base = 2; 46012854Sgabeblack@google.com scfx_csd2tc(s2); 46112854Sgabeblack@google.com s = (const char *)s2 + 4; 46212854Sgabeblack@google.com numrep = SC_BIN; 46312854Sgabeblack@google.com break; 46412854Sgabeblack@google.com } 46512854Sgabeblack@google.com default: 46612854Sgabeblack@google.com ; 46712854Sgabeblack@google.com } 46812854Sgabeblack@google.com 46912854Sgabeblack@google.com // 47012854Sgabeblack@google.com // find end of mantissa and count the digits and points 47112854Sgabeblack@google.com // 47212854Sgabeblack@google.com 47312854Sgabeblack@google.com const char *end = s; 47412854Sgabeblack@google.com bool based_point = false; 47512854Sgabeblack@google.com int int_digits = 0; 47612854Sgabeblack@google.com int frac_digits = 0; 47712854Sgabeblack@google.com 47812854Sgabeblack@google.com while (*end) { 47912854Sgabeblack@google.com if (scfx_exp_start(end)) 48012854Sgabeblack@google.com break; 48112854Sgabeblack@google.com 48212854Sgabeblack@google.com if (*end == '.') { 48312854Sgabeblack@google.com SCFX_FAIL_IF_(based_point); 48412854Sgabeblack@google.com based_point = true; 48512854Sgabeblack@google.com } else { 48612854Sgabeblack@google.com SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep)); 48712854Sgabeblack@google.com if (based_point) 48812854Sgabeblack@google.com frac_digits++; 48912854Sgabeblack@google.com else 49012854Sgabeblack@google.com int_digits++; 49112854Sgabeblack@google.com } 49212854Sgabeblack@google.com 49312854Sgabeblack@google.com ++end; 49412854Sgabeblack@google.com } 49512854Sgabeblack@google.com 49612854Sgabeblack@google.com SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0); 49712854Sgabeblack@google.com 49812854Sgabeblack@google.com // [ exponent ] 49912854Sgabeblack@google.com int exponent = 0; 50012854Sgabeblack@google.com 50112854Sgabeblack@google.com if (*end) { 50212854Sgabeblack@google.com for (const char *e = end + 2; *e; ++e) 50312854Sgabeblack@google.com SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC)); 50412854Sgabeblack@google.com exponent = std::atoi(end + 1); 50512854Sgabeblack@google.com } 50612854Sgabeblack@google.com 50712854Sgabeblack@google.com // 50812854Sgabeblack@google.com // check if the mantissa is negative 50912854Sgabeblack@google.com // 51012854Sgabeblack@google.com bool mant_is_neg = false; 51112854Sgabeblack@google.com switch (numrep) { 51212854Sgabeblack@google.com case SC_BIN: 51312854Sgabeblack@google.com case SC_OCT: 51412854Sgabeblack@google.com case SC_HEX: 51512854Sgabeblack@google.com { 51612854Sgabeblack@google.com const char *p = s; 51712854Sgabeblack@google.com if (*p == '.') 51812854Sgabeblack@google.com ++p; 51912854Sgabeblack@google.com 52012854Sgabeblack@google.com mant_is_neg = (scfx_to_digit(* p, numrep) >= (base >> 1)); 52112854Sgabeblack@google.com break; 52212854Sgabeblack@google.com } 52312854Sgabeblack@google.com default: 52412854Sgabeblack@google.com ; 52512854Sgabeblack@google.com } 52612854Sgabeblack@google.com 52712854Sgabeblack@google.com // 52812854Sgabeblack@google.com // convert the mantissa 52912854Sgabeblack@google.com // 53012854Sgabeblack@google.com 53112854Sgabeblack@google.com switch (base) { 53212854Sgabeblack@google.com case 2: 53312854Sgabeblack@google.com { 53412854Sgabeblack@google.com int bit_offset = exponent % bits_in_word; 53512854Sgabeblack@google.com int word_offset = exponent / bits_in_word; 53612854Sgabeblack@google.com 53712854Sgabeblack@google.com int_digits += bit_offset; 53812854Sgabeblack@google.com frac_digits -= bit_offset; 53912854Sgabeblack@google.com 54012854Sgabeblack@google.com int words = n_word(int_digits) + n_word(frac_digits); 54112854Sgabeblack@google.com if (words > size()) 54212854Sgabeblack@google.com resize_to(words); 54312854Sgabeblack@google.com m_mant.clear(); 54412854Sgabeblack@google.com 54512854Sgabeblack@google.com int j = n_word(frac_digits) * bits_in_word + int_digits - 1; 54612854Sgabeblack@google.com 54712854Sgabeblack@google.com for (; s < end; s++) { 54812854Sgabeblack@google.com switch (*s) { 54912854Sgabeblack@google.com case '1': 55012854Sgabeblack@google.com set_bin(j); 55112854Sgabeblack@google.com M5_FALLTHROUGH; 55212854Sgabeblack@google.com case '0': 55312854Sgabeblack@google.com j--; 55412854Sgabeblack@google.com M5_FALLTHROUGH; 55512854Sgabeblack@google.com case '.': 55612854Sgabeblack@google.com break; 55712854Sgabeblack@google.com default: 55812854Sgabeblack@google.com SCFX_FAIL_IF_(true); // should not happen 55912854Sgabeblack@google.com } 56012854Sgabeblack@google.com } 56112854Sgabeblack@google.com 56212854Sgabeblack@google.com m_wp = n_word(frac_digits) - word_offset; 56312854Sgabeblack@google.com break; 56412854Sgabeblack@google.com } 56512854Sgabeblack@google.com case 8: 56612854Sgabeblack@google.com { 56712854Sgabeblack@google.com exponent *= 3; 56812854Sgabeblack@google.com int_digits *= 3; 56912854Sgabeblack@google.com frac_digits *= 3; 57012854Sgabeblack@google.com 57112854Sgabeblack@google.com int bit_offset = exponent % bits_in_word; 57212854Sgabeblack@google.com int word_offset = exponent / bits_in_word; 57312854Sgabeblack@google.com 57412854Sgabeblack@google.com int_digits += bit_offset; 57512854Sgabeblack@google.com frac_digits -= bit_offset; 57612854Sgabeblack@google.com 57712854Sgabeblack@google.com int words = n_word(int_digits) + n_word(frac_digits); 57812854Sgabeblack@google.com if (words > size()) 57912854Sgabeblack@google.com resize_to(words); 58012854Sgabeblack@google.com m_mant.clear(); 58112854Sgabeblack@google.com 58212854Sgabeblack@google.com int j = n_word(frac_digits) * bits_in_word + int_digits - 3; 58312854Sgabeblack@google.com 58412854Sgabeblack@google.com for (; s < end; s++) { 58512854Sgabeblack@google.com switch (*s) { 58612854Sgabeblack@google.com case '7': case '6': case '5': case '4': 58712854Sgabeblack@google.com case '3': case '2': case '1': 58812854Sgabeblack@google.com set_oct(j, *s - '0'); 58912854Sgabeblack@google.com M5_FALLTHROUGH; 59012854Sgabeblack@google.com case '0': 59112854Sgabeblack@google.com j -= 3; 59212854Sgabeblack@google.com M5_FALLTHROUGH; 59312854Sgabeblack@google.com case '.': 59412854Sgabeblack@google.com break; 59512854Sgabeblack@google.com default: 59612854Sgabeblack@google.com SCFX_FAIL_IF_(true); // should not happen 59712854Sgabeblack@google.com } 59812854Sgabeblack@google.com } 59912854Sgabeblack@google.com 60012854Sgabeblack@google.com m_wp = n_word(frac_digits) - word_offset; 60112854Sgabeblack@google.com break; 60212854Sgabeblack@google.com } 60312854Sgabeblack@google.com case 10: 60412854Sgabeblack@google.com { 60512854Sgabeblack@google.com word carry, temp; 60612854Sgabeblack@google.com int length = int_digits + frac_digits; 60712854Sgabeblack@google.com resize_to(sc_max(min_mant, n_word(4 * length))); 60812854Sgabeblack@google.com 60912854Sgabeblack@google.com m_mant.clear(); 61012854Sgabeblack@google.com m_msw = m_lsw = 0; 61112854Sgabeblack@google.com 61212854Sgabeblack@google.com for (; s < end; s++) { 61312854Sgabeblack@google.com switch (*s) { 61412854Sgabeblack@google.com case '9': case '8': case '7': case '6': case '5': 61512854Sgabeblack@google.com case '4': case '3': case '2': case '1': case '0': 61612854Sgabeblack@google.com multiply_by_ten(); 61712854Sgabeblack@google.com carry = *s - '0'; 61812854Sgabeblack@google.com for (int i = 0; carry && i < m_mant.size(); i++) { 61912854Sgabeblack@google.com temp = m_mant[i]; 62012854Sgabeblack@google.com temp += carry; 62112854Sgabeblack@google.com carry = temp < m_mant[i]; 62212854Sgabeblack@google.com m_mant[i] = temp; 62312854Sgabeblack@google.com } 62412854Sgabeblack@google.com case '.': 62512854Sgabeblack@google.com break; 62612854Sgabeblack@google.com default: 62712854Sgabeblack@google.com SCFX_FAIL_IF_(true); // should not happen 62812854Sgabeblack@google.com } 62912854Sgabeblack@google.com } 63012854Sgabeblack@google.com 63112854Sgabeblack@google.com m_wp = 0; 63212854Sgabeblack@google.com find_sw(); 63312854Sgabeblack@google.com 63412854Sgabeblack@google.com int denominator = frac_digits - exponent; 63512854Sgabeblack@google.com 63612854Sgabeblack@google.com if (denominator) { 63712854Sgabeblack@google.com scfx_rep frac_num = pow10_fx(denominator); 63812854Sgabeblack@google.com scfx_rep *temp_num = 63912854Sgabeblack@google.com div_scfx_rep(const_cast<const scfx_rep &>(*this), 64012854Sgabeblack@google.com frac_num, cte_wl); 64112854Sgabeblack@google.com *this = *temp_num; 64212854Sgabeblack@google.com delete temp_num; 64312854Sgabeblack@google.com } 64412854Sgabeblack@google.com 64512854Sgabeblack@google.com break; 64612854Sgabeblack@google.com } 64712854Sgabeblack@google.com case 16: 64812854Sgabeblack@google.com { 64912854Sgabeblack@google.com exponent *= 4; 65012854Sgabeblack@google.com int_digits *= 4; 65112854Sgabeblack@google.com frac_digits *= 4; 65212854Sgabeblack@google.com 65312854Sgabeblack@google.com int bit_offset = exponent % bits_in_word; 65412854Sgabeblack@google.com int word_offset = exponent / bits_in_word; 65512854Sgabeblack@google.com 65612854Sgabeblack@google.com int_digits += bit_offset; 65712854Sgabeblack@google.com frac_digits -= bit_offset; 65812854Sgabeblack@google.com 65912854Sgabeblack@google.com int words = n_word(int_digits) + n_word(frac_digits); 66012854Sgabeblack@google.com if (words > size()) 66112854Sgabeblack@google.com resize_to(words); 66212854Sgabeblack@google.com m_mant.clear(); 66312854Sgabeblack@google.com 66412854Sgabeblack@google.com int j = n_word(frac_digits) * bits_in_word + int_digits - 4; 66512854Sgabeblack@google.com 66612854Sgabeblack@google.com for (; s < end; s ++) { 66712854Sgabeblack@google.com switch (*s) { 66812854Sgabeblack@google.com case 'f': case 'e': case 'd': case 'c': case 'b': case 'a': 66912854Sgabeblack@google.com set_hex(j, *s - 'a' + 10); 67012854Sgabeblack@google.com j -= 4; 67112854Sgabeblack@google.com break; 67212854Sgabeblack@google.com case 'F': case 'E': case 'D': case 'C': case 'B': case 'A': 67312854Sgabeblack@google.com set_hex(j, *s - 'A' + 10); 67412854Sgabeblack@google.com j -= 4; 67512854Sgabeblack@google.com break; 67612854Sgabeblack@google.com case '9': case '8': case '7': case '6': case '5': 67712854Sgabeblack@google.com case '4': case '3': case '2': case '1': 67812854Sgabeblack@google.com set_hex(j, *s - '0'); 67912854Sgabeblack@google.com M5_FALLTHROUGH; 68012854Sgabeblack@google.com case '0': 68112854Sgabeblack@google.com j -= 4; 68212854Sgabeblack@google.com M5_FALLTHROUGH; 68312854Sgabeblack@google.com case '.': 68412854Sgabeblack@google.com break; 68512854Sgabeblack@google.com default: 68612854Sgabeblack@google.com SCFX_FAIL_IF_(true); // should not happen 68712854Sgabeblack@google.com } 68812854Sgabeblack@google.com } 68912854Sgabeblack@google.com 69012854Sgabeblack@google.com m_wp = n_word(frac_digits) - word_offset; 69112854Sgabeblack@google.com break; 69212854Sgabeblack@google.com } 69312854Sgabeblack@google.com } 69412854Sgabeblack@google.com 69512854Sgabeblack@google.com m_state = normal; 69612854Sgabeblack@google.com find_sw(); 69712854Sgabeblack@google.com 69812854Sgabeblack@google.com // 69912854Sgabeblack@google.com // two's complement of mantissa if it is negative 70012854Sgabeblack@google.com // 70112854Sgabeblack@google.com if (mant_is_neg) { 70212854Sgabeblack@google.com m_mant[m_msw] |= ~0U << scfx_find_msb(m_mant[m_msw]); 70312854Sgabeblack@google.com for (int i = m_msw + 1; i < m_mant.size(); ++i) 70412854Sgabeblack@google.com m_mant[i] = static_cast<word>(-1); 70512854Sgabeblack@google.com complement(m_mant, m_mant, m_mant.size()); 70612854Sgabeblack@google.com inc(m_mant); 70712854Sgabeblack@google.com m_sign *= -1; 70812854Sgabeblack@google.com find_sw(); 70912854Sgabeblack@google.com } 71012854Sgabeblack@google.com} 71112854Sgabeblack@google.com 71212854Sgabeblack@google.com#undef SCFX_FAIL_IF_ 71312854Sgabeblack@google.com 71412854Sgabeblack@google.com// ---------------------------------------------------------------------------- 71512854Sgabeblack@google.com// METHOD : to_double 71612854Sgabeblack@google.com// 71712854Sgabeblack@google.com// Convert from scfx_rep to double. 71812854Sgabeblack@google.com// ---------------------------------------------------------------------------- 71912854Sgabeblack@google.com 72012854Sgabeblack@google.comdouble 72112854Sgabeblack@google.comscfx_rep::to_double() const 72212854Sgabeblack@google.com{ 72312854Sgabeblack@google.com scfx_ieee_double id; 72412854Sgabeblack@google.com 72512854Sgabeblack@google.com // handle special cases 72612854Sgabeblack@google.com if (is_nan()) { 72712854Sgabeblack@google.com id.set_nan(); 72812854Sgabeblack@google.com return id; 72912854Sgabeblack@google.com } 73012854Sgabeblack@google.com 73112854Sgabeblack@google.com if (is_inf()) { 73212854Sgabeblack@google.com id.set_inf(); 73312854Sgabeblack@google.com id.negative(m_sign < 0); 73412854Sgabeblack@google.com return id; 73512854Sgabeblack@google.com } 73612854Sgabeblack@google.com 73712854Sgabeblack@google.com if (is_zero()) { 73812854Sgabeblack@google.com id = 0.; 73912854Sgabeblack@google.com id.negative(m_sign < 0); 74012854Sgabeblack@google.com return id; 74112854Sgabeblack@google.com } 74212854Sgabeblack@google.com 74312854Sgabeblack@google.com int msb = scfx_find_msb(m_mant[m_msw]); 74412854Sgabeblack@google.com 74512854Sgabeblack@google.com int exp = (m_msw - m_wp) * bits_in_word + msb; 74612854Sgabeblack@google.com 74712854Sgabeblack@google.com if (exp > SCFX_IEEE_DOUBLE_E_MAX) { 74812854Sgabeblack@google.com id.set_inf(); 74912854Sgabeblack@google.com id.negative(m_sign < 0); 75012854Sgabeblack@google.com return id; 75112854Sgabeblack@google.com } 75212854Sgabeblack@google.com 75312854Sgabeblack@google.com if (exp < SCFX_IEEE_DOUBLE_E_MIN - 75412854Sgabeblack@google.com static_cast<int>(SCFX_IEEE_DOUBLE_M_SIZE)) 75512854Sgabeblack@google.com { 75612854Sgabeblack@google.com id = 0.; 75712854Sgabeblack@google.com return id; 75812854Sgabeblack@google.com } 75912854Sgabeblack@google.com 76012854Sgabeblack@google.com int shift = mantissa0_size - msb; 76112854Sgabeblack@google.com 76212854Sgabeblack@google.com unsigned int m0; 76312854Sgabeblack@google.com unsigned int m1 = 0; 76412854Sgabeblack@google.com unsigned int guard = 0; 76512854Sgabeblack@google.com 76612854Sgabeblack@google.com if (shift == 0) { 76712854Sgabeblack@google.com m0 = m_mant[m_msw] & ~(1 << mantissa0_size); 76812854Sgabeblack@google.com if (m_msw > m_lsw) { 76912854Sgabeblack@google.com m1 = m_mant[m_msw - 1]; 77012854Sgabeblack@google.com if (m_msw - 1 > m_lsw) 77112854Sgabeblack@google.com guard = m_mant[m_msw - 2] >> (bits_in_word - 1); 77212854Sgabeblack@google.com } 77312854Sgabeblack@google.com } else if (shift < 0) { 77412854Sgabeblack@google.com m0 = (m_mant[m_msw] >> -shift) & ~(1 << mantissa0_size); 77512854Sgabeblack@google.com m1 = m_mant[m_msw] << (bits_in_word + shift); 77612854Sgabeblack@google.com if (m_msw > m_lsw) { 77712854Sgabeblack@google.com m1 |= m_mant[m_msw - 1] >> -shift; 77812854Sgabeblack@google.com guard = (m_mant[m_msw - 1] >> (-shift - 1)) & 1; 77912854Sgabeblack@google.com } 78012854Sgabeblack@google.com } else { 78112854Sgabeblack@google.com m0 = (m_mant[m_msw] << shift) & ~(1 << mantissa0_size); 78212854Sgabeblack@google.com if (m_msw > m_lsw) { 78312854Sgabeblack@google.com m0 |= m_mant[m_msw - 1] >> (bits_in_word - shift); 78412854Sgabeblack@google.com m1 = m_mant[m_msw - 1] << shift; 78512854Sgabeblack@google.com if (m_msw - 1 > m_lsw) { 78612854Sgabeblack@google.com m1 |= m_mant[m_msw - 2] >> (bits_in_word - shift); 78712854Sgabeblack@google.com guard = (m_mant[m_msw - 2] >> (bits_in_word - shift - 1)) & 1; 78812854Sgabeblack@google.com } 78912854Sgabeblack@google.com } 79012854Sgabeblack@google.com } 79112854Sgabeblack@google.com 79212854Sgabeblack@google.com if (exp < SCFX_IEEE_DOUBLE_E_MIN) { 79312854Sgabeblack@google.com m0 |= (1 << mantissa0_size); 79412854Sgabeblack@google.com 79512854Sgabeblack@google.com int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp; 79612854Sgabeblack@google.com 79712854Sgabeblack@google.com if (subnormal_shift < bits_in_word) { 79812854Sgabeblack@google.com m1 = m1 >> subnormal_shift | 79912854Sgabeblack@google.com m0 << (bits_in_word - subnormal_shift); 80012854Sgabeblack@google.com m0 = m0 >> subnormal_shift; 80112854Sgabeblack@google.com } else { 80212854Sgabeblack@google.com m1 = m0 >> (subnormal_shift - bits_in_word); 80312854Sgabeblack@google.com m0 = 0; 80412854Sgabeblack@google.com } 80512854Sgabeblack@google.com 80612854Sgabeblack@google.com guard = 0; 80712854Sgabeblack@google.com 80812854Sgabeblack@google.com exp = SCFX_IEEE_DOUBLE_E_MIN - 1; 80912854Sgabeblack@google.com } 81012854Sgabeblack@google.com 81112854Sgabeblack@google.com id.mantissa0(m0); 81212854Sgabeblack@google.com id.mantissa1(m1); 81312854Sgabeblack@google.com id.exponent(exp); 81412854Sgabeblack@google.com id.negative(m_sign < 0); 81512854Sgabeblack@google.com 81612854Sgabeblack@google.com double result = id; 81712854Sgabeblack@google.com 81812854Sgabeblack@google.com if (guard != 0) 81912854Sgabeblack@google.com result += m_sign * scfx_pow2(exp - SCFX_IEEE_DOUBLE_M_SIZE); 82012854Sgabeblack@google.com 82112854Sgabeblack@google.com return result; 82212854Sgabeblack@google.com} 82312854Sgabeblack@google.com 82412854Sgabeblack@google.com 82512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 82612854Sgabeblack@google.com// METHOD : to_uint64 82712854Sgabeblack@google.com// 82812854Sgabeblack@google.com// Convert from scfx_rep to uint64. 82912854Sgabeblack@google.com// Truncates towards 0 _then_ wraps; infinities and NaN go to zero. 83012854Sgabeblack@google.com// ---------------------------------------------------------------------------- 83112854Sgabeblack@google.com 83212854Sgabeblack@google.comuint64 83312854Sgabeblack@google.comscfx_rep::to_uint64() const 83412854Sgabeblack@google.com{ 83512854Sgabeblack@google.com if (!is_normal() || is_zero()) { 83612854Sgabeblack@google.com return 0; 83712854Sgabeblack@google.com } 83812854Sgabeblack@google.com 83912854Sgabeblack@google.com uint64 result = 0; 84012854Sgabeblack@google.com int shift = 0; 84112854Sgabeblack@google.com int idx = m_wp; 84212854Sgabeblack@google.com 84312854Sgabeblack@google.com // Ignore bits off the top; they modulo out. 84412854Sgabeblack@google.com // Ignore bits off the bottom; we're truncating. 84512854Sgabeblack@google.com while (shift < 64 && m_msw >= idx && idx >= m_lsw) { 84612854Sgabeblack@google.com result += static_cast<uint64>(m_mant[idx]) << shift; 84712854Sgabeblack@google.com shift += bits_in_word; 84812854Sgabeblack@google.com idx += 1; 84912854Sgabeblack@google.com } 85012854Sgabeblack@google.com 85112854Sgabeblack@google.com return m_sign > 0 ? result : -result; 85212854Sgabeblack@google.com} 85312854Sgabeblack@google.com 85412854Sgabeblack@google.com 85512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 85612854Sgabeblack@google.com// METHOD : to_string 85712854Sgabeblack@google.com// 85812854Sgabeblack@google.com// Convert from scfx_rep to character string. 85912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 86012854Sgabeblack@google.com 86112854Sgabeblack@google.comvoid 86212854Sgabeblack@google.comprint_dec(scfx_string &s, const scfx_rep &num, int w_prefix, sc_fmt fmt) 86312854Sgabeblack@google.com{ 86412854Sgabeblack@google.com if (num.is_neg()) 86512854Sgabeblack@google.com s += '-'; 86612854Sgabeblack@google.com 86712854Sgabeblack@google.com if (w_prefix == 1) { 86812854Sgabeblack@google.com scfx_print_prefix(s, SC_DEC); 86912854Sgabeblack@google.com } 87012854Sgabeblack@google.com 87112854Sgabeblack@google.com if (num.is_zero()) { 87212854Sgabeblack@google.com s += '0'; 87312854Sgabeblack@google.com return; 87412854Sgabeblack@google.com } 87512854Sgabeblack@google.com 87612854Sgabeblack@google.com // split 'num' into its integer and fractional part 87712854Sgabeblack@google.com scfx_rep int_part = num; 87812854Sgabeblack@google.com scfx_rep frac_part = num; 87912854Sgabeblack@google.com 88012854Sgabeblack@google.com int i; 88112854Sgabeblack@google.com 88212854Sgabeblack@google.com for (i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i++) 88312854Sgabeblack@google.com int_part.m_mant[i] = 0; 88412854Sgabeblack@google.com int_part.find_sw(); 88512854Sgabeblack@google.com if (int_part.m_wp < int_part.m_lsw) 88612854Sgabeblack@google.com int_part.resize_to(int_part.size() - int_part.m_wp, -1); 88712854Sgabeblack@google.com 88812854Sgabeblack@google.com for (i = frac_part.m_msw; 88912854Sgabeblack@google.com i >= frac_part.m_lsw && i >= frac_part.m_wp; i--) 89012854Sgabeblack@google.com frac_part.m_mant[i] = 0; 89112854Sgabeblack@google.com frac_part.find_sw(); 89212854Sgabeblack@google.com if (frac_part.m_msw == frac_part.size() - 1) 89312854Sgabeblack@google.com frac_part.resize_to(frac_part.size() + 1, 1); 89412854Sgabeblack@google.com 89512854Sgabeblack@google.com // print integer part 89612854Sgabeblack@google.com int int_digits = 0; 89712854Sgabeblack@google.com int int_zeros = 0; 89812854Sgabeblack@google.com 89912854Sgabeblack@google.com if (!int_part.is_zero()) { 90012854Sgabeblack@google.com double int_wl = (int_part.m_msw - int_part.m_wp) * bits_in_word + 90112854Sgabeblack@google.com scfx_find_msb(int_part.m_mant[int_part.m_msw]) + 1; 90212854Sgabeblack@google.com int_digits = (int)std::ceil(int_wl * std::log10(2.)); 90312854Sgabeblack@google.com 90412854Sgabeblack@google.com int len = s.length(); 90512854Sgabeblack@google.com s.append(int_digits); 90612854Sgabeblack@google.com 90712854Sgabeblack@google.com bool zero_digits = (frac_part.is_zero() && fmt != SC_F); 90812854Sgabeblack@google.com 90912854Sgabeblack@google.com for (i = int_digits + len - 1; i >= len; i--) { 91012854Sgabeblack@google.com unsigned int remainder = int_part.divide_by_ten(); 91112854Sgabeblack@google.com s[i] = static_cast<char>('0' + remainder); 91212854Sgabeblack@google.com 91312854Sgabeblack@google.com if (zero_digits) { 91412854Sgabeblack@google.com if (remainder == 0) 91512854Sgabeblack@google.com int_zeros++; 91612854Sgabeblack@google.com else 91712854Sgabeblack@google.com zero_digits = false; 91812854Sgabeblack@google.com } 91912854Sgabeblack@google.com } 92012854Sgabeblack@google.com 92112854Sgabeblack@google.com // discard trailing zeros from int_part 92212854Sgabeblack@google.com s.discard(int_zeros); 92312854Sgabeblack@google.com 92412854Sgabeblack@google.com if (s[len] == '0') { 92512854Sgabeblack@google.com // int_digits was overestimated by one 92612854Sgabeblack@google.com s.remove(len); 92712854Sgabeblack@google.com --int_digits; 92812854Sgabeblack@google.com } 92912854Sgabeblack@google.com } 93012854Sgabeblack@google.com 93112854Sgabeblack@google.com // print fractional part 93212854Sgabeblack@google.com int frac_digits = 0; 93312854Sgabeblack@google.com int frac_zeros = 0; 93412854Sgabeblack@google.com 93512854Sgabeblack@google.com if (!frac_part.is_zero()) { 93612854Sgabeblack@google.com s += '.'; 93712854Sgabeblack@google.com 93812854Sgabeblack@google.com bool zero_digits = (int_digits == 0 && fmt != SC_F); 93912854Sgabeblack@google.com 94012854Sgabeblack@google.com double frac_wl = (frac_part.m_wp - frac_part.m_msw) * bits_in_word - 94112854Sgabeblack@google.com scfx_find_msb(frac_part.m_mant[frac_part.m_msw]) - 1; 94212854Sgabeblack@google.com frac_zeros = (int)std::floor(frac_wl * std::log10(2.)); 94312854Sgabeblack@google.com 94412854Sgabeblack@google.com scfx_rep temp; 94512854Sgabeblack@google.com sc_dt::multiply(temp, frac_part, pow10_fx(frac_zeros)); 94612854Sgabeblack@google.com frac_part = temp; 94712854Sgabeblack@google.com if (frac_part.m_msw == frac_part.size() - 1) 94812854Sgabeblack@google.com frac_part.resize_to(frac_part.size() + 1, 1); 94912854Sgabeblack@google.com 95012854Sgabeblack@google.com frac_digits = frac_zeros; 95112854Sgabeblack@google.com if (!zero_digits) { 95212854Sgabeblack@google.com for (i = 0; i < frac_zeros; i++) 95312854Sgabeblack@google.com s += '0'; 95412854Sgabeblack@google.com frac_zeros = 0; 95512854Sgabeblack@google.com } 95612854Sgabeblack@google.com 95712854Sgabeblack@google.com while (!frac_part.is_zero()) { 95812854Sgabeblack@google.com frac_part.multiply_by_ten(); 95912854Sgabeblack@google.com int n = frac_part.m_mant[frac_part.m_msw + 1]; 96012854Sgabeblack@google.com 96112854Sgabeblack@google.com if (zero_digits) { 96212854Sgabeblack@google.com if (n == 0) 96312854Sgabeblack@google.com frac_zeros++; 96412854Sgabeblack@google.com else 96512854Sgabeblack@google.com zero_digits = false; 96612854Sgabeblack@google.com } 96712854Sgabeblack@google.com 96812854Sgabeblack@google.com if (! zero_digits) 96912854Sgabeblack@google.com s += static_cast<char>('0' + n); 97012854Sgabeblack@google.com 97112854Sgabeblack@google.com frac_part.m_mant[frac_part.m_msw + 1] = 0; 97212854Sgabeblack@google.com frac_digits++; 97312854Sgabeblack@google.com } 97412854Sgabeblack@google.com } 97512854Sgabeblack@google.com 97612854Sgabeblack@google.com // print exponent 97712854Sgabeblack@google.com if (fmt != SC_F) { 97812854Sgabeblack@google.com if (frac_digits == 0) 97912854Sgabeblack@google.com scfx_print_exp(s, int_zeros); 98012854Sgabeblack@google.com else if (int_digits == 0) 98112854Sgabeblack@google.com scfx_print_exp(s, -frac_zeros); 98212854Sgabeblack@google.com } 98312854Sgabeblack@google.com} 98412854Sgabeblack@google.com 98512854Sgabeblack@google.comvoid 98612854Sgabeblack@google.comprint_other(scfx_string &s, const scfx_rep &a, sc_numrep numrep, int w_prefix, 98712854Sgabeblack@google.com sc_fmt fmt, const scfx_params *params) 98812854Sgabeblack@google.com{ 98912854Sgabeblack@google.com scfx_rep b = a; 99012854Sgabeblack@google.com 99112854Sgabeblack@google.com sc_numrep numrep2 = numrep; 99212854Sgabeblack@google.com 99312854Sgabeblack@google.com bool numrep_is_sm = (numrep == SC_BIN_SM || 99412854Sgabeblack@google.com numrep == SC_OCT_SM || 99512854Sgabeblack@google.com numrep == SC_HEX_SM); 99612854Sgabeblack@google.com 99712854Sgabeblack@google.com if (numrep_is_sm) { 99812854Sgabeblack@google.com if (b.is_neg()) { 99912854Sgabeblack@google.com s += '-'; 100012854Sgabeblack@google.com b = *neg_scfx_rep(a); 100112854Sgabeblack@google.com } 100212854Sgabeblack@google.com switch (numrep) { 100312854Sgabeblack@google.com case SC_BIN_SM: 100412854Sgabeblack@google.com numrep2 = SC_BIN_US; 100512854Sgabeblack@google.com break; 100612854Sgabeblack@google.com case SC_OCT_SM: 100712854Sgabeblack@google.com numrep2 = SC_OCT_US; 100812854Sgabeblack@google.com break; 100912854Sgabeblack@google.com case SC_HEX_SM: 101012854Sgabeblack@google.com numrep2 = SC_HEX_US; 101112854Sgabeblack@google.com break; 101212854Sgabeblack@google.com default: 101312854Sgabeblack@google.com ; 101412854Sgabeblack@google.com } 101512854Sgabeblack@google.com } 101612854Sgabeblack@google.com 101712854Sgabeblack@google.com if (w_prefix != 0) { 101812854Sgabeblack@google.com scfx_print_prefix(s, numrep); 101912854Sgabeblack@google.com } 102012854Sgabeblack@google.com 102112854Sgabeblack@google.com numrep = numrep2; 102212854Sgabeblack@google.com 102312854Sgabeblack@google.com int msb, lsb; 102412854Sgabeblack@google.com 102512854Sgabeblack@google.com if (params != 0) { 102612854Sgabeblack@google.com msb = params->iwl() - 1; 102712854Sgabeblack@google.com lsb = params->iwl() - params->wl(); 102812854Sgabeblack@google.com 102912854Sgabeblack@google.com if (params->enc() == SC_TC_ && 103012854Sgabeblack@google.com (numrep == SC_BIN_US || 103112854Sgabeblack@google.com numrep == SC_OCT_US || 103212854Sgabeblack@google.com numrep == SC_HEX_US) && 103312854Sgabeblack@google.com !numrep_is_sm && 103412854Sgabeblack@google.com params->wl() > 1) { 103512854Sgabeblack@google.com --msb; 103612854Sgabeblack@google.com } else if (params->enc() == SC_US_ && 103712854Sgabeblack@google.com (numrep == SC_BIN || 103812854Sgabeblack@google.com numrep == SC_OCT || 103912854Sgabeblack@google.com numrep == SC_HEX || 104012854Sgabeblack@google.com numrep == SC_CSD)) { 104112854Sgabeblack@google.com ++msb; 104212854Sgabeblack@google.com } 104312854Sgabeblack@google.com } else { 104412854Sgabeblack@google.com if (b.is_zero()) { 104512854Sgabeblack@google.com msb = 0; 104612854Sgabeblack@google.com lsb = 0; 104712854Sgabeblack@google.com } else { 104812854Sgabeblack@google.com msb = (b.m_msw - b.m_wp) * bits_in_word 104912854Sgabeblack@google.com + scfx_find_msb(b.m_mant[ b.m_msw ]) + 1; 105012854Sgabeblack@google.com while (b.get_bit(msb) == b.get_bit(msb - 1)) 105112854Sgabeblack@google.com --msb; 105212854Sgabeblack@google.com 105312854Sgabeblack@google.com if (numrep == SC_BIN_US || 105412854Sgabeblack@google.com numrep == SC_OCT_US || 105512854Sgabeblack@google.com numrep == SC_HEX_US) { 105612854Sgabeblack@google.com --msb; 105712854Sgabeblack@google.com } 105812854Sgabeblack@google.com 105912854Sgabeblack@google.com lsb = (b.m_lsw - b.m_wp) * bits_in_word + 106012854Sgabeblack@google.com scfx_find_lsb(b.m_mant[b.m_lsw]); 106113197Sgabeblack@google.com 106212854Sgabeblack@google.com } 106312854Sgabeblack@google.com } 106412854Sgabeblack@google.com 106512854Sgabeblack@google.com int step; 106612854Sgabeblack@google.com 106712854Sgabeblack@google.com switch (numrep) { 106812854Sgabeblack@google.com case SC_BIN: 106912854Sgabeblack@google.com case SC_BIN_US: 107012854Sgabeblack@google.com case SC_CSD: 107112854Sgabeblack@google.com step = 1; 107212854Sgabeblack@google.com break; 107312854Sgabeblack@google.com case SC_OCT: 107412854Sgabeblack@google.com case SC_OCT_US: 107512854Sgabeblack@google.com step = 3; 107612854Sgabeblack@google.com break; 107712854Sgabeblack@google.com case SC_HEX: 107812854Sgabeblack@google.com case SC_HEX_US: 107912854Sgabeblack@google.com step = 4; 108012854Sgabeblack@google.com break; 108112854Sgabeblack@google.com default: 108213322Sgabeblack@google.com SC_REPORT_FATAL(sc_core::SC_ID_ASSERTION_FAILED_, 108313322Sgabeblack@google.com "unexpected sc_numrep"); 108412854Sgabeblack@google.com sc_core::sc_abort(); 108512854Sgabeblack@google.com } 108612854Sgabeblack@google.com 108712854Sgabeblack@google.com msb = (int)std::ceil(double(msb + 1) / step) * step - 1; 108812854Sgabeblack@google.com 108912854Sgabeblack@google.com lsb = (int)std::floor(double(lsb) / step) * step; 109012854Sgabeblack@google.com 109112854Sgabeblack@google.com if (msb < 0) { 109212854Sgabeblack@google.com s += '.'; 109312854Sgabeblack@google.com if (fmt == SC_F) { 109412854Sgabeblack@google.com int sign = (b.is_neg()) ? (1 << step) - 1 : 0; 109512854Sgabeblack@google.com for (int i = (msb + 1) / step; i < 0; i++) { 109612854Sgabeblack@google.com if (sign < 10) 109712854Sgabeblack@google.com s += static_cast<char>(sign + '0'); 109812854Sgabeblack@google.com else 109912854Sgabeblack@google.com s += static_cast<char>(sign + 'a' - 10); 110012854Sgabeblack@google.com } 110112854Sgabeblack@google.com } 110212854Sgabeblack@google.com } 110312854Sgabeblack@google.com 110412854Sgabeblack@google.com int i = msb; 110512854Sgabeblack@google.com while (i >= lsb) { 110612854Sgabeblack@google.com int value = 0; 110712854Sgabeblack@google.com for (int j = step - 1; j >= 0; --j) { 110812854Sgabeblack@google.com value += static_cast<int>(b.get_bit(i)) << j; 110912854Sgabeblack@google.com --i; 111012854Sgabeblack@google.com } 111112854Sgabeblack@google.com if (value < 10) 111212854Sgabeblack@google.com s += static_cast<char>(value + '0'); 111312854Sgabeblack@google.com else 111412854Sgabeblack@google.com s += static_cast<char>(value + 'a' - 10); 111512854Sgabeblack@google.com if (i == -1) 111612854Sgabeblack@google.com s += '.'; 111712854Sgabeblack@google.com } 111812854Sgabeblack@google.com 111912854Sgabeblack@google.com if (lsb > 0 && fmt == SC_F) { 112012854Sgabeblack@google.com for (int i = lsb / step; i > 0; i--) 112112854Sgabeblack@google.com s += '0'; 112212854Sgabeblack@google.com } 112312854Sgabeblack@google.com 112412854Sgabeblack@google.com if (s[s.length() - 1] == '.') 112512854Sgabeblack@google.com s.discard(1); 112612854Sgabeblack@google.com 112712854Sgabeblack@google.com if (fmt != SC_F) { 112812854Sgabeblack@google.com if (msb < 0) 112912854Sgabeblack@google.com scfx_print_exp(s, (msb + 1) / step); 113012854Sgabeblack@google.com else if (lsb > 0) 113112854Sgabeblack@google.com scfx_print_exp(s, lsb / step); 113212854Sgabeblack@google.com } 113312854Sgabeblack@google.com 113412854Sgabeblack@google.com if (numrep == SC_CSD) 113512854Sgabeblack@google.com scfx_tc2csd(s, w_prefix); 113612854Sgabeblack@google.com} 113712854Sgabeblack@google.com 113812854Sgabeblack@google.comconst char * 113912854Sgabeblack@google.comscfx_rep::to_string(sc_numrep numrep, int w_prefix, 114012854Sgabeblack@google.com sc_fmt fmt, const scfx_params *params) const 114112854Sgabeblack@google.com{ 114212854Sgabeblack@google.com static scfx_string s; 114312854Sgabeblack@google.com 114412854Sgabeblack@google.com s.clear(); 114512854Sgabeblack@google.com 114612854Sgabeblack@google.com if (is_nan()) { 114712854Sgabeblack@google.com scfx_print_nan(s); 114812854Sgabeblack@google.com } else if (is_inf()) { 114912854Sgabeblack@google.com scfx_print_inf(s, is_neg()); 115012854Sgabeblack@google.com } else if (is_neg() && !is_zero() && 115112854Sgabeblack@google.com (numrep == SC_BIN_US || 115212854Sgabeblack@google.com numrep == SC_OCT_US || 115312854Sgabeblack@google.com numrep == SC_HEX_US)) { 115412854Sgabeblack@google.com s += "negative"; 115512854Sgabeblack@google.com } else if (numrep == SC_DEC || numrep == SC_NOBASE) { 115612854Sgabeblack@google.com sc_dt::print_dec(s, *this, w_prefix, fmt); 115712854Sgabeblack@google.com } else { 115812854Sgabeblack@google.com sc_dt::print_other(s, *this, numrep, w_prefix, fmt, params); 115912854Sgabeblack@google.com } 116012854Sgabeblack@google.com 116112854Sgabeblack@google.com return s; 116212854Sgabeblack@google.com} 116312854Sgabeblack@google.com 116412854Sgabeblack@google.com 116512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 116612854Sgabeblack@google.com// ADD 116712854Sgabeblack@google.com// 116812854Sgabeblack@google.com// add two mantissas of the same size 116912854Sgabeblack@google.com// result has the same size 117012854Sgabeblack@google.com// returns carry of operation 117112854Sgabeblack@google.com// ---------------------------------------------------------------------------- 117212854Sgabeblack@google.com 117312854Sgabeblack@google.comstatic inline int 117412854Sgabeblack@google.comadd_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b) 117512854Sgabeblack@google.com{ 117612854Sgabeblack@google.com unsigned int carry = 0; 117712854Sgabeblack@google.com 117812854Sgabeblack@google.com int index = 0; 117912854Sgabeblack@google.com 118012854Sgabeblack@google.com do { 118112854Sgabeblack@google.com word x = a[index]; 118212854Sgabeblack@google.com word y = b[index]; 118312854Sgabeblack@google.com 118412854Sgabeblack@google.com y += carry; 118512854Sgabeblack@google.com carry = y < carry; 118612854Sgabeblack@google.com y += x; 118712854Sgabeblack@google.com carry += y < x; 118812854Sgabeblack@google.com result[index] = y; 118912854Sgabeblack@google.com } while (++index < size); 119012854Sgabeblack@google.com 119112854Sgabeblack@google.com return (carry ? 1 : 0); 119212854Sgabeblack@google.com} 119312854Sgabeblack@google.com 119412854Sgabeblack@google.comstatic inline int 119512854Sgabeblack@google.comsub_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b) 119612854Sgabeblack@google.com{ 119712854Sgabeblack@google.com unsigned carry = 0; 119812854Sgabeblack@google.com 119912854Sgabeblack@google.com int index = 0; 120012854Sgabeblack@google.com 120112854Sgabeblack@google.com do { 120212854Sgabeblack@google.com word x = a[index]; 120312854Sgabeblack@google.com word y = b[index]; 120412854Sgabeblack@google.com 120512854Sgabeblack@google.com y += carry; 120612854Sgabeblack@google.com carry = y < carry; 120712854Sgabeblack@google.com y = x - y; 120812854Sgabeblack@google.com carry += y > x; 120912854Sgabeblack@google.com result[index] = y; 121012854Sgabeblack@google.com } while (++index < size); 121112854Sgabeblack@google.com 121212854Sgabeblack@google.com return (carry ? 1 : 0); 121312854Sgabeblack@google.com} 121412854Sgabeblack@google.com 121512854Sgabeblack@google.comscfx_rep * 121612854Sgabeblack@google.comadd_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl) 121712854Sgabeblack@google.com{ 121812854Sgabeblack@google.com scfx_rep &result = *new scfx_rep; 121912854Sgabeblack@google.com 122012854Sgabeblack@google.com // 122112854Sgabeblack@google.com // check for special cases 122212854Sgabeblack@google.com // 122312854Sgabeblack@google.com if (lhs.is_nan() || rhs.is_nan() || 122412854Sgabeblack@google.com (lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign)) { 122512854Sgabeblack@google.com result.set_nan(); 122612854Sgabeblack@google.com return &result; 122712854Sgabeblack@google.com } 122812854Sgabeblack@google.com 122912854Sgabeblack@google.com if (lhs.is_inf()) { 123012854Sgabeblack@google.com result.set_inf(lhs.m_sign); 123112854Sgabeblack@google.com return &result; 123212854Sgabeblack@google.com } 123312854Sgabeblack@google.com 123412854Sgabeblack@google.com if (rhs.is_inf()) { 123512854Sgabeblack@google.com result.set_inf(rhs.m_sign); 123612854Sgabeblack@google.com return &result; 123712854Sgabeblack@google.com } 123812854Sgabeblack@google.com 123912854Sgabeblack@google.com // 124012854Sgabeblack@google.com // align operands if needed 124112854Sgabeblack@google.com // 124212854Sgabeblack@google.com scfx_mant_ref lhs_mant; 124312854Sgabeblack@google.com scfx_mant_ref rhs_mant; 124412854Sgabeblack@google.com 124512854Sgabeblack@google.com int len_mant = lhs.size(); 124612854Sgabeblack@google.com int new_wp = lhs.m_wp; 124712854Sgabeblack@google.com 124812854Sgabeblack@google.com align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant); 124912854Sgabeblack@google.com 125012854Sgabeblack@google.com // 125112854Sgabeblack@google.com // size the result mantissa 125212854Sgabeblack@google.com // 125312854Sgabeblack@google.com result.resize_to(len_mant); 125412854Sgabeblack@google.com result.m_wp = new_wp; 125512854Sgabeblack@google.com 125612854Sgabeblack@google.com // 125712854Sgabeblack@google.com // do it 125812854Sgabeblack@google.com // 125912854Sgabeblack@google.com if (lhs.m_sign == rhs.m_sign) { 126012854Sgabeblack@google.com add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 126112854Sgabeblack@google.com result.m_sign = lhs.m_sign; 126212854Sgabeblack@google.com } else { 126312854Sgabeblack@google.com int cmp = compare_abs(lhs, rhs); 126412854Sgabeblack@google.com 126512854Sgabeblack@google.com if (cmp == 1) { 126612854Sgabeblack@google.com sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 126712854Sgabeblack@google.com result.m_sign = lhs.m_sign; 126812854Sgabeblack@google.com } else if (cmp == -1) { 126912854Sgabeblack@google.com sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant); 127012854Sgabeblack@google.com result.m_sign = rhs.m_sign; 127112854Sgabeblack@google.com } else { 127212854Sgabeblack@google.com result.m_mant.clear(); 127312854Sgabeblack@google.com result.m_sign = 1; 127412854Sgabeblack@google.com } 127512854Sgabeblack@google.com } 127612854Sgabeblack@google.com 127712854Sgabeblack@google.com result.find_sw(); 127812854Sgabeblack@google.com result.round(max_wl); 127912854Sgabeblack@google.com 128012854Sgabeblack@google.com return &result; 128112854Sgabeblack@google.com} 128212854Sgabeblack@google.com 128312854Sgabeblack@google.com 128412854Sgabeblack@google.com// ---------------------------------------------------------------------------- 128512854Sgabeblack@google.com// SUB 128612854Sgabeblack@google.com// 128712854Sgabeblack@google.com// sub two word's of the same size 128812854Sgabeblack@google.com// result has the same size 128912854Sgabeblack@google.com// returns carry of operation 129012854Sgabeblack@google.com// ---------------------------------------------------------------------------- 129112854Sgabeblack@google.com 129212854Sgabeblack@google.comstatic inline int 129312854Sgabeblack@google.comsub_with_index(scfx_mant &a, int a_msw, int /*a_lsw*/, 129412854Sgabeblack@google.com const scfx_mant &b, int b_msw, int b_lsw) 129512854Sgabeblack@google.com{ 129612854Sgabeblack@google.com unsigned carry = 0; 129712854Sgabeblack@google.com 129812854Sgabeblack@google.com int size = b_msw - b_lsw; 129912854Sgabeblack@google.com int a_index = a_msw - size; 130012854Sgabeblack@google.com int b_index = b_msw - size; 130112854Sgabeblack@google.com 130212854Sgabeblack@google.com do { 130312854Sgabeblack@google.com word x = a[a_index]; 130412854Sgabeblack@google.com word y = b[b_index]; 130512854Sgabeblack@google.com 130612854Sgabeblack@google.com y += carry; 130712854Sgabeblack@google.com carry = y < carry; 130812854Sgabeblack@google.com y = x - y; 130912854Sgabeblack@google.com carry += y > x; 131012854Sgabeblack@google.com a[a_index] = y; 131112854Sgabeblack@google.com 131212854Sgabeblack@google.com a_index++; 131312854Sgabeblack@google.com b_index++; 131412854Sgabeblack@google.com } while (size--); 131512854Sgabeblack@google.com 131612854Sgabeblack@google.com if (carry) { 131712854Sgabeblack@google.com // special case: a[a_msw + 1] == 1 131812854Sgabeblack@google.com a[a_msw + 1] = 0; 131912854Sgabeblack@google.com } 132012854Sgabeblack@google.com 132112854Sgabeblack@google.com return (carry ? 1 : 0); 132212854Sgabeblack@google.com} 132312854Sgabeblack@google.com 132412854Sgabeblack@google.comscfx_rep * 132512854Sgabeblack@google.comsub_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl) 132612854Sgabeblack@google.com{ 132712854Sgabeblack@google.com scfx_rep &result = *new scfx_rep; 132812854Sgabeblack@google.com 132912854Sgabeblack@google.com // 133012854Sgabeblack@google.com // check for special cases 133112854Sgabeblack@google.com // 133212854Sgabeblack@google.com if (lhs.is_nan() || rhs.is_nan() || 133312854Sgabeblack@google.com (lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign)) { 133412854Sgabeblack@google.com result.set_nan(); 133512854Sgabeblack@google.com return &result; 133612854Sgabeblack@google.com } 133712854Sgabeblack@google.com 133812854Sgabeblack@google.com if (lhs.is_inf()) { 133912854Sgabeblack@google.com result.set_inf(lhs.m_sign); 134012854Sgabeblack@google.com return &result; 134112854Sgabeblack@google.com } 134212854Sgabeblack@google.com 134312854Sgabeblack@google.com if (rhs.is_inf()) { 134412854Sgabeblack@google.com result.set_inf(-1 * rhs.m_sign); 134512854Sgabeblack@google.com return &result; 134612854Sgabeblack@google.com } 134712854Sgabeblack@google.com 134812854Sgabeblack@google.com // 134912854Sgabeblack@google.com // align operands if needed 135012854Sgabeblack@google.com // 135112854Sgabeblack@google.com scfx_mant_ref lhs_mant; 135212854Sgabeblack@google.com scfx_mant_ref rhs_mant; 135312854Sgabeblack@google.com 135412854Sgabeblack@google.com int len_mant = lhs.size(); 135512854Sgabeblack@google.com int new_wp = lhs.m_wp; 135612854Sgabeblack@google.com 135712854Sgabeblack@google.com align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant); 135812854Sgabeblack@google.com 135912854Sgabeblack@google.com // 136012854Sgabeblack@google.com // size the result mantissa 136112854Sgabeblack@google.com // 136212854Sgabeblack@google.com result.resize_to(len_mant); 136312854Sgabeblack@google.com result.m_wp = new_wp; 136412854Sgabeblack@google.com 136512854Sgabeblack@google.com // 136612854Sgabeblack@google.com // do it 136712854Sgabeblack@google.com // 136812854Sgabeblack@google.com if (lhs.m_sign != rhs.m_sign) { 136912854Sgabeblack@google.com add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 137012854Sgabeblack@google.com result.m_sign = lhs.m_sign; 137112854Sgabeblack@google.com } else { 137212854Sgabeblack@google.com int cmp = compare_abs(lhs, rhs); 137312854Sgabeblack@google.com 137412854Sgabeblack@google.com if (cmp == 1) { 137512854Sgabeblack@google.com sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 137612854Sgabeblack@google.com result.m_sign = lhs.m_sign; 137712854Sgabeblack@google.com } else if (cmp == -1) { 137812854Sgabeblack@google.com sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant); 137912854Sgabeblack@google.com result.m_sign = -rhs.m_sign; 138012854Sgabeblack@google.com } else { 138112854Sgabeblack@google.com result.m_mant.clear(); 138212854Sgabeblack@google.com result.m_sign = 1; 138312854Sgabeblack@google.com } 138412854Sgabeblack@google.com } 138512854Sgabeblack@google.com 138612854Sgabeblack@google.com result.find_sw(); 138712854Sgabeblack@google.com result.round(max_wl); 138812854Sgabeblack@google.com 138912854Sgabeblack@google.com return &result; 139012854Sgabeblack@google.com} 139112854Sgabeblack@google.com 139212854Sgabeblack@google.com 139312854Sgabeblack@google.com// ---------------------------------------------------------------------------- 139412854Sgabeblack@google.com// MUL 139512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 139612854Sgabeblack@google.com 139712854Sgabeblack@google.comunion word_short 139812854Sgabeblack@google.com{ 139912854Sgabeblack@google.com word l; 140012854Sgabeblack@google.com struct 140112854Sgabeblack@google.com { 140212854Sgabeblack@google.com#if defined(SC_BOOST_BIG_ENDIAN) 140312854Sgabeblack@google.com half_word u; 140412854Sgabeblack@google.com half_word l; 140512854Sgabeblack@google.com#elif defined(SC_BOOST_LITTLE_ENDIAN) 140612854Sgabeblack@google.com half_word l; 140712854Sgabeblack@google.com half_word u; 140812854Sgabeblack@google.com#endif 140912854Sgabeblack@google.com } s; 141012854Sgabeblack@google.com}; 141112854Sgabeblack@google.com 141212854Sgabeblack@google.com#if defined(SC_BOOST_BIG_ENDIAN) 141312854Sgabeblack@google.comstatic const int half_word_incr = -1; 141412854Sgabeblack@google.com#elif defined(SC_BOOST_LITTLE_ENDIAN) 141512854Sgabeblack@google.comstatic const int half_word_incr = 1; 141612854Sgabeblack@google.com#endif 141712854Sgabeblack@google.com 141812854Sgabeblack@google.comvoid 141912854Sgabeblack@google.commultiply(scfx_rep &result, const scfx_rep &lhs, const scfx_rep &rhs, 142012854Sgabeblack@google.com int max_wl) 142112854Sgabeblack@google.com{ 142212854Sgabeblack@google.com // 142312854Sgabeblack@google.com // check for special cases 142412854Sgabeblack@google.com // 142512854Sgabeblack@google.com if (lhs.is_nan() || rhs.is_nan() || 142612854Sgabeblack@google.com (lhs.is_inf() && rhs.is_zero()) || 142712854Sgabeblack@google.com (lhs.is_zero() && rhs.is_inf())) { 142812854Sgabeblack@google.com result.set_nan(); 142912854Sgabeblack@google.com return; 143012854Sgabeblack@google.com } 143112854Sgabeblack@google.com 143212854Sgabeblack@google.com if (lhs.is_inf() || rhs.is_inf()) { 143312854Sgabeblack@google.com result.set_inf(lhs.m_sign * rhs.m_sign); 143412854Sgabeblack@google.com return; 143512854Sgabeblack@google.com } 143612854Sgabeblack@google.com 143712854Sgabeblack@google.com if (lhs.is_zero() || rhs.is_zero()) { 143812854Sgabeblack@google.com result.set_zero(lhs.m_sign * rhs.m_sign); 143912854Sgabeblack@google.com return; 144012854Sgabeblack@google.com } 144112854Sgabeblack@google.com 144212854Sgabeblack@google.com // 144312854Sgabeblack@google.com // do it 144412854Sgabeblack@google.com // 144512854Sgabeblack@google.com int len_lhs = lhs.m_msw - lhs.m_lsw + 1; 144612854Sgabeblack@google.com int len_rhs = rhs.m_msw - rhs.m_lsw + 1; 144712854Sgabeblack@google.com 144812854Sgabeblack@google.com int new_size = sc_max(min_mant, len_lhs + len_rhs); 144912854Sgabeblack@google.com int new_wp = (lhs.m_wp - lhs.m_lsw) + (rhs.m_wp - rhs.m_lsw); 145012854Sgabeblack@google.com int new_sign = lhs.m_sign * rhs.m_sign; 145112854Sgabeblack@google.com 145212854Sgabeblack@google.com result.resize_to(new_size); 145312854Sgabeblack@google.com result.m_mant.clear(); 145412854Sgabeblack@google.com result.m_wp = new_wp; 145512854Sgabeblack@google.com result.m_sign = new_sign; 145612854Sgabeblack@google.com result.m_state = scfx_rep::normal; 145712854Sgabeblack@google.com 145812854Sgabeblack@google.com half_word *s1 = lhs.m_mant.half_addr(lhs.m_lsw); 145912854Sgabeblack@google.com half_word *s2 = rhs.m_mant.half_addr(rhs.m_lsw); 146012854Sgabeblack@google.com 146112854Sgabeblack@google.com half_word *t = result.m_mant.half_addr(); 146212854Sgabeblack@google.com 146312854Sgabeblack@google.com len_lhs <<= 1; 146412854Sgabeblack@google.com len_rhs <<= 1; 146512854Sgabeblack@google.com 146612854Sgabeblack@google.com int i1, i2; 146712854Sgabeblack@google.com 146812854Sgabeblack@google.com for (i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr) { 146912854Sgabeblack@google.com word_short ls; 147012854Sgabeblack@google.com ls.l = 0; 147112854Sgabeblack@google.com 147212854Sgabeblack@google.com half_word v1 = s1[i1]; 147312854Sgabeblack@google.com 147412854Sgabeblack@google.com for (i2 = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr) { 147512854Sgabeblack@google.com ls.l += v1 * s2[i2]; 147612854Sgabeblack@google.com ls.s.l = ls.s.u + ((t[i2] += ls.s.l) < ls.s.l); 147712854Sgabeblack@google.com ls.s.u = 0; 147812854Sgabeblack@google.com } 147912854Sgabeblack@google.com 148012854Sgabeblack@google.com t[i2] = ls.s.l; 148112854Sgabeblack@google.com t += half_word_incr; 148212854Sgabeblack@google.com } 148312854Sgabeblack@google.com 148412854Sgabeblack@google.com result.find_sw(); 148512854Sgabeblack@google.com result.round(max_wl); 148612854Sgabeblack@google.com} 148712854Sgabeblack@google.com 148812854Sgabeblack@google.com 148912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 149012854Sgabeblack@google.com// DIV 149112854Sgabeblack@google.com// ---------------------------------------------------------------------------- 149212854Sgabeblack@google.com 149312854Sgabeblack@google.comscfx_rep * 149412854Sgabeblack@google.comdiv_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int div_wl) 149512854Sgabeblack@google.com{ 149612854Sgabeblack@google.com scfx_rep &result = *new scfx_rep; 149712854Sgabeblack@google.com 149812854Sgabeblack@google.com // 149912854Sgabeblack@google.com // check for special cases 150012854Sgabeblack@google.com // 150112854Sgabeblack@google.com if (lhs.is_nan() || rhs.is_nan() || (lhs.is_inf() && rhs.is_inf()) || 150212854Sgabeblack@google.com (lhs.is_zero() && rhs.is_zero())) { 150312854Sgabeblack@google.com result.set_nan(); 150412854Sgabeblack@google.com return &result; 150512854Sgabeblack@google.com } 150612854Sgabeblack@google.com 150712854Sgabeblack@google.com if (lhs.is_inf() || rhs.is_zero()) { 150812854Sgabeblack@google.com result.set_inf(lhs.m_sign * rhs.m_sign); 150912854Sgabeblack@google.com return &result; 151012854Sgabeblack@google.com } 151112854Sgabeblack@google.com 151212854Sgabeblack@google.com if (lhs.is_zero() || rhs.is_inf()) { 151312854Sgabeblack@google.com result.set_zero(lhs.m_sign * rhs.m_sign); 151412854Sgabeblack@google.com return &result; 151512854Sgabeblack@google.com } 151612854Sgabeblack@google.com 151712854Sgabeblack@google.com // 151812854Sgabeblack@google.com // do it 151912854Sgabeblack@google.com // 152012854Sgabeblack@google.com 152112854Sgabeblack@google.com // compute one bit more for rounding 152212854Sgabeblack@google.com div_wl++; 152312854Sgabeblack@google.com 152412854Sgabeblack@google.com result.resize_to(sc_max(n_word(div_wl) + 1, min_mant)); 152512854Sgabeblack@google.com result.m_mant.clear(); 152612854Sgabeblack@google.com result.m_sign = lhs.m_sign * rhs.m_sign; 152712854Sgabeblack@google.com 152812854Sgabeblack@google.com int msb_lhs = scfx_find_msb(lhs.m_mant[lhs.m_msw]) + 152912854Sgabeblack@google.com (lhs.m_msw - lhs.m_wp) * bits_in_word; 153012854Sgabeblack@google.com int msb_rhs = scfx_find_msb(rhs.m_mant[rhs.m_msw]) + 153112854Sgabeblack@google.com (rhs.m_msw - rhs.m_wp) * bits_in_word; 153212854Sgabeblack@google.com 153312854Sgabeblack@google.com int msb_res = msb_lhs - msb_rhs; 153412854Sgabeblack@google.com int to_shift = -msb_res % bits_in_word; 153512854Sgabeblack@google.com int result_index; 153612854Sgabeblack@google.com 153712854Sgabeblack@google.com int c = (msb_res % bits_in_word >= 0) ? 1 : 0; 153812854Sgabeblack@google.com 153912854Sgabeblack@google.com result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word; 154012854Sgabeblack@google.com result.m_wp = (result.size() - c) - msb_res / bits_in_word; 154112854Sgabeblack@google.com 154212854Sgabeblack@google.com scfx_rep remainder = lhs; 154312854Sgabeblack@google.com 154412854Sgabeblack@google.com // align msb from remainder to msb from rhs 154512854Sgabeblack@google.com remainder.lshift(to_shift); 154612854Sgabeblack@google.com 154712854Sgabeblack@google.com // make sure msw(remainder) < size - 1 154812854Sgabeblack@google.com if (remainder.m_msw == remainder.size() - 1) 154912854Sgabeblack@google.com remainder.resize_to(remainder.size() + 1, 1); 155012854Sgabeblack@google.com 155112854Sgabeblack@google.com // make sure msw(remainder) >= msw(rhs)! 155212854Sgabeblack@google.com int msw_diff = rhs.m_msw - remainder.m_msw; 155312854Sgabeblack@google.com if (msw_diff > 0) 155412854Sgabeblack@google.com remainder.resize_to(remainder.size() + msw_diff, -1); 155512854Sgabeblack@google.com 155612854Sgabeblack@google.com int counter; 155712854Sgabeblack@google.com 155812854Sgabeblack@google.com for (counter = div_wl; counter && !remainder.is_zero(); counter--) { 155912854Sgabeblack@google.com if (compare_msw_ff(rhs, remainder) <= 0) { 156012854Sgabeblack@google.com result.set_bin(result_index); 156112854Sgabeblack@google.com sub_with_index(remainder.m_mant, remainder.m_msw, remainder.m_lsw, 156212854Sgabeblack@google.com rhs.m_mant, rhs.m_msw, rhs.m_lsw); 156312854Sgabeblack@google.com } 156412854Sgabeblack@google.com result_index--; 156512854Sgabeblack@google.com remainder.shift_left(1); 156612854Sgabeblack@google.com remainder.m_lsw = remainder.find_lsw(); 156712854Sgabeblack@google.com } 156812854Sgabeblack@google.com 156912854Sgabeblack@google.com // perform convergent rounding, if needed 157012854Sgabeblack@google.com if (counter == 0) { 157112854Sgabeblack@google.com int index = result_index + 1 - result.m_wp * bits_in_word; 157212854Sgabeblack@google.com 157312854Sgabeblack@google.com scfx_index x = result.calc_indices(index); 157412854Sgabeblack@google.com scfx_index x1 = result.calc_indices(index + 1); 157512854Sgabeblack@google.com 157612854Sgabeblack@google.com if (result.o_bit_at(x) && result.o_bit_at(x1)) 157712854Sgabeblack@google.com result.q_incr(x); 157812854Sgabeblack@google.com 157912854Sgabeblack@google.com result.m_r_flag = true; 158012854Sgabeblack@google.com } 158112854Sgabeblack@google.com 158212854Sgabeblack@google.com result.find_sw(); 158312854Sgabeblack@google.com 158412854Sgabeblack@google.com return &result; 158512854Sgabeblack@google.com} 158612854Sgabeblack@google.com 158712854Sgabeblack@google.com// ---------------------------------------------------------------------------- 158812854Sgabeblack@google.com// destructive shift mantissa to the left 158912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 159012854Sgabeblack@google.com 159112854Sgabeblack@google.comvoid 159212854Sgabeblack@google.comscfx_rep::lshift(int n) 159312854Sgabeblack@google.com{ 159412854Sgabeblack@google.com if (n == 0) 159512854Sgabeblack@google.com return; 159612854Sgabeblack@google.com 159712854Sgabeblack@google.com if (n < 0) { 159812854Sgabeblack@google.com rshift(-n); 159912854Sgabeblack@google.com return; 160012854Sgabeblack@google.com } 160112854Sgabeblack@google.com 160212854Sgabeblack@google.com if (is_normal()) { 160312854Sgabeblack@google.com int shift_bits = n % bits_in_word; 160412854Sgabeblack@google.com int shift_words = n / bits_in_word; 160512854Sgabeblack@google.com 160612854Sgabeblack@google.com // resize if needed 160712854Sgabeblack@google.com if (m_msw == size() - 1 && 160812854Sgabeblack@google.com scfx_find_msb(m_mant[m_msw]) >= bits_in_word - shift_bits) 160912854Sgabeblack@google.com resize_to(size() + 1, 1); 161012854Sgabeblack@google.com 161112854Sgabeblack@google.com // do it 161212854Sgabeblack@google.com m_wp -= shift_words; 161312854Sgabeblack@google.com shift_left(shift_bits); 161412854Sgabeblack@google.com find_sw(); 161512854Sgabeblack@google.com } 161612854Sgabeblack@google.com} 161712854Sgabeblack@google.com 161812854Sgabeblack@google.com// ---------------------------------------------------------------------------- 161912854Sgabeblack@google.com// destructive shift mantissa to the right 162012854Sgabeblack@google.com// ---------------------------------------------------------------------------- 162112854Sgabeblack@google.com 162212854Sgabeblack@google.comvoid 162312854Sgabeblack@google.comscfx_rep::rshift(int n) 162412854Sgabeblack@google.com{ 162512854Sgabeblack@google.com if (n == 0) 162612854Sgabeblack@google.com return; 162712854Sgabeblack@google.com 162812854Sgabeblack@google.com if (n < 0) { 162912854Sgabeblack@google.com lshift(-n); 163012854Sgabeblack@google.com return; 163112854Sgabeblack@google.com } 163212854Sgabeblack@google.com 163312854Sgabeblack@google.com if (is_normal()) { 163412854Sgabeblack@google.com int shift_bits = n % bits_in_word; 163512854Sgabeblack@google.com int shift_words = n / bits_in_word; 163612854Sgabeblack@google.com 163712854Sgabeblack@google.com // resize if needed 163812854Sgabeblack@google.com if (m_lsw == 0 && scfx_find_lsb(m_mant[m_lsw]) < shift_bits) 163912854Sgabeblack@google.com resize_to(size() + 1, -1); 164012854Sgabeblack@google.com 164112854Sgabeblack@google.com // do it 164212854Sgabeblack@google.com m_wp += shift_words; 164312854Sgabeblack@google.com shift_right(shift_bits); 164412854Sgabeblack@google.com find_sw(); 164512854Sgabeblack@google.com } 164612854Sgabeblack@google.com} 164712854Sgabeblack@google.com 164812854Sgabeblack@google.com 164912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 165012854Sgabeblack@google.com// FRIEND FUNCTION : compare_abs 165112854Sgabeblack@google.com// 165212854Sgabeblack@google.com// Compares the absolute values of two scfx_reps, excluding the special cases. 165312854Sgabeblack@google.com// ---------------------------------------------------------------------------- 165412854Sgabeblack@google.com 165512854Sgabeblack@google.comint 165612854Sgabeblack@google.comcompare_abs(const scfx_rep &a, const scfx_rep &b) 165712854Sgabeblack@google.com{ 165812854Sgabeblack@google.com // check for zero 165912854Sgabeblack@google.com word a_word = a.m_mant[a.m_msw]; 166012854Sgabeblack@google.com word b_word = b.m_mant[b.m_msw]; 166112854Sgabeblack@google.com 166212854Sgabeblack@google.com if (a_word == 0 || b_word == 0) { 166312854Sgabeblack@google.com if (a_word != 0) 166412854Sgabeblack@google.com return 1; 166512854Sgabeblack@google.com if (b_word != 0) 166612854Sgabeblack@google.com return -1; 166712854Sgabeblack@google.com return 0; 166812854Sgabeblack@google.com } 166912854Sgabeblack@google.com 167012854Sgabeblack@google.com // compare msw index 167112854Sgabeblack@google.com int a_msw = a.m_msw - a.m_wp; 167212854Sgabeblack@google.com int b_msw = b.m_msw - b.m_wp; 167312854Sgabeblack@google.com 167412854Sgabeblack@google.com if (a_msw > b_msw) 167512854Sgabeblack@google.com return 1; 167612854Sgabeblack@google.com 167712854Sgabeblack@google.com if (a_msw < b_msw) 167812854Sgabeblack@google.com return -1; 167912854Sgabeblack@google.com 168012854Sgabeblack@google.com // compare content 168112854Sgabeblack@google.com int a_i = a.m_msw; 168212854Sgabeblack@google.com int b_i = b.m_msw; 168312854Sgabeblack@google.com 168412854Sgabeblack@google.com while (a_i >= a.m_lsw && b_i >= b.m_lsw) { 168512854Sgabeblack@google.com a_word = a.m_mant[a_i]; 168612854Sgabeblack@google.com b_word = b.m_mant[b_i]; 168712854Sgabeblack@google.com if (a_word > b_word) 168812854Sgabeblack@google.com return 1; 168912854Sgabeblack@google.com if (a_word < b_word) 169012854Sgabeblack@google.com return -1; 169112854Sgabeblack@google.com --a_i; 169212854Sgabeblack@google.com --b_i; 169312854Sgabeblack@google.com } 169412854Sgabeblack@google.com 169512854Sgabeblack@google.com bool a_zero = true; 169612854Sgabeblack@google.com while (a_i >= a.m_lsw) { 169712854Sgabeblack@google.com a_zero = a_zero && (a.m_mant[a_i] == 0); 169812854Sgabeblack@google.com --a_i; 169912854Sgabeblack@google.com } 170012854Sgabeblack@google.com 170112854Sgabeblack@google.com bool b_zero = true; 170212854Sgabeblack@google.com while (b_i >= b.m_lsw) { 170312854Sgabeblack@google.com b_zero = b_zero && (b.m_mant[b_i] == 0); 170412854Sgabeblack@google.com --b_i; 170512854Sgabeblack@google.com } 170612854Sgabeblack@google.com 170712854Sgabeblack@google.com // assertion: a_zero || b_zero 170812854Sgabeblack@google.com 170912854Sgabeblack@google.com if (!a_zero && b_zero) 171012854Sgabeblack@google.com return 1; 171112854Sgabeblack@google.com 171212854Sgabeblack@google.com if (a_zero && !b_zero) 171312854Sgabeblack@google.com return -1; 171412854Sgabeblack@google.com 171512854Sgabeblack@google.com return 0; 171612854Sgabeblack@google.com} 171712854Sgabeblack@google.com 171812854Sgabeblack@google.com// ---------------------------------------------------------------------------- 171912854Sgabeblack@google.com// FRIEND FUNCTION : cmp_scfx_rep 172012854Sgabeblack@google.com// 172112854Sgabeblack@google.com// Compares the values of two scfx_reps, including the special cases. 172212854Sgabeblack@google.com// ---------------------------------------------------------------------------- 172312854Sgabeblack@google.com 172412854Sgabeblack@google.comint 172512854Sgabeblack@google.comcmp_scfx_rep(const scfx_rep &a, const scfx_rep &b) 172612854Sgabeblack@google.com{ 172712854Sgabeblack@google.com // handle special cases 172812854Sgabeblack@google.com 172912854Sgabeblack@google.com if (a.is_nan() || b.is_nan()) { 173012854Sgabeblack@google.com return 2; 173112854Sgabeblack@google.com } 173212854Sgabeblack@google.com 173312854Sgabeblack@google.com if (a.is_inf() || b.is_inf()) { 173412854Sgabeblack@google.com if (a.is_inf()) { 173512854Sgabeblack@google.com if (!a.is_neg()) { 173612854Sgabeblack@google.com if (b.is_inf() && !b.is_neg()) { 173712854Sgabeblack@google.com return 0; 173812854Sgabeblack@google.com } else { 173912854Sgabeblack@google.com return 1; 174012854Sgabeblack@google.com } 174112854Sgabeblack@google.com } else { 174212854Sgabeblack@google.com if (b.is_inf() && b.is_neg()) { 174312854Sgabeblack@google.com return 0; 174412854Sgabeblack@google.com } else { 174512854Sgabeblack@google.com return -1; 174612854Sgabeblack@google.com } 174712854Sgabeblack@google.com } 174812854Sgabeblack@google.com } 174912854Sgabeblack@google.com if (b.is_inf()) { 175012854Sgabeblack@google.com if (!b.is_neg()) { 175112854Sgabeblack@google.com return -1; 175212854Sgabeblack@google.com } else { 175312854Sgabeblack@google.com return 1; 175412854Sgabeblack@google.com } 175512854Sgabeblack@google.com } 175612854Sgabeblack@google.com } 175712854Sgabeblack@google.com 175812854Sgabeblack@google.com if (a.is_zero() && b.is_zero()) { 175912854Sgabeblack@google.com return 0; 176012854Sgabeblack@google.com } 176112854Sgabeblack@google.com 176212854Sgabeblack@google.com // compare sign 176312854Sgabeblack@google.com if (a.m_sign != b.m_sign) { 176412854Sgabeblack@google.com return a.m_sign; 176512854Sgabeblack@google.com } 176612854Sgabeblack@google.com 176712854Sgabeblack@google.com return (a.m_sign * compare_abs(a, b)); 176812854Sgabeblack@google.com} 176912854Sgabeblack@google.com 177012854Sgabeblack@google.com 177112854Sgabeblack@google.com// ---------------------------------------------------------------------------- 177212854Sgabeblack@google.com// PRIVATE METHOD : quantization 177312854Sgabeblack@google.com// 177412854Sgabeblack@google.com// Performs destructive quantization. 177512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 177612854Sgabeblack@google.com 177712854Sgabeblack@google.comvoid 177812854Sgabeblack@google.comscfx_rep::quantization(const scfx_params ¶ms, bool &q_flag) 177912854Sgabeblack@google.com{ 178012854Sgabeblack@google.com scfx_index x = calc_indices(params.iwl() - params.wl()); 178112854Sgabeblack@google.com 178212854Sgabeblack@google.com if (x.wi() < 0) 178312854Sgabeblack@google.com return; 178412854Sgabeblack@google.com 178512854Sgabeblack@google.com if (x.wi() >= size()) 178612854Sgabeblack@google.com resize_to(x.wi() + 1, 1); 178712854Sgabeblack@google.com 178812854Sgabeblack@google.com bool qb = q_bit(x); 178912854Sgabeblack@google.com bool qz = q_zero(x); 179012854Sgabeblack@google.com 179112854Sgabeblack@google.com q_flag = (qb || ! qz); 179212854Sgabeblack@google.com 179312854Sgabeblack@google.com if (q_flag) { 179412854Sgabeblack@google.com switch (params.q_mode()) { 179512854Sgabeblack@google.com case SC_TRN: // truncation 179612854Sgabeblack@google.com { 179712854Sgabeblack@google.com if (is_neg()) 179812854Sgabeblack@google.com q_incr(x); 179912854Sgabeblack@google.com break; 180012854Sgabeblack@google.com } 180112854Sgabeblack@google.com case SC_RND: // rounding to plus infinity 180212854Sgabeblack@google.com { 180312854Sgabeblack@google.com if (!is_neg()) { 180412854Sgabeblack@google.com if (qb) 180512854Sgabeblack@google.com q_incr(x); 180612854Sgabeblack@google.com } else { 180712854Sgabeblack@google.com if (qb && !qz) 180812854Sgabeblack@google.com q_incr(x); 180912854Sgabeblack@google.com } 181012854Sgabeblack@google.com break; 181112854Sgabeblack@google.com } 181212854Sgabeblack@google.com case SC_TRN_ZERO: // truncation to zero 181312854Sgabeblack@google.com { 181412854Sgabeblack@google.com break; 181512854Sgabeblack@google.com } 181612854Sgabeblack@google.com case SC_RND_INF: // rounding to infinity 181712854Sgabeblack@google.com { 181812854Sgabeblack@google.com if (qb) 181912854Sgabeblack@google.com q_incr(x); 182012854Sgabeblack@google.com break; 182112854Sgabeblack@google.com } 182212854Sgabeblack@google.com case SC_RND_CONV: // convergent rounding 182312854Sgabeblack@google.com { 182412854Sgabeblack@google.com if ((qb && !qz) || (qb && qz && q_odd(x))) 182512854Sgabeblack@google.com q_incr(x); 182612854Sgabeblack@google.com break; 182712854Sgabeblack@google.com } 182812854Sgabeblack@google.com case SC_RND_ZERO: // rounding to zero 182912854Sgabeblack@google.com { 183012854Sgabeblack@google.com if (qb && !qz) 183112854Sgabeblack@google.com q_incr(x); 183212854Sgabeblack@google.com break; 183312854Sgabeblack@google.com } 183412854Sgabeblack@google.com case SC_RND_MIN_INF: // rounding to minus infinity 183512854Sgabeblack@google.com { 183612854Sgabeblack@google.com if (!is_neg()) { 183712854Sgabeblack@google.com if (qb && !qz) 183812854Sgabeblack@google.com q_incr(x); 183912854Sgabeblack@google.com } else { 184012854Sgabeblack@google.com if (qb) 184112854Sgabeblack@google.com q_incr(x); 184212854Sgabeblack@google.com } 184312854Sgabeblack@google.com break; 184412854Sgabeblack@google.com } 184512854Sgabeblack@google.com default: 184612854Sgabeblack@google.com ; 184712854Sgabeblack@google.com } 184812854Sgabeblack@google.com q_clear(x); 184912854Sgabeblack@google.com 185012854Sgabeblack@google.com find_sw(); 185112854Sgabeblack@google.com } 185212854Sgabeblack@google.com} 185312854Sgabeblack@google.com 185412854Sgabeblack@google.com 185512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 185612854Sgabeblack@google.com// PRIVATE METHOD : overflow 185712854Sgabeblack@google.com// 185812854Sgabeblack@google.com// Performs destructive overflow handling. 185912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 186012854Sgabeblack@google.com 186112854Sgabeblack@google.comvoid 186212854Sgabeblack@google.comscfx_rep::overflow(const scfx_params ¶ms, bool &o_flag) 186312854Sgabeblack@google.com{ 186412854Sgabeblack@google.com scfx_index x = calc_indices(params.iwl() - 1); 186512854Sgabeblack@google.com 186612854Sgabeblack@google.com if (x.wi() >= size()) 186712854Sgabeblack@google.com resize_to(x.wi() + 1, 1); 186812854Sgabeblack@google.com 186912854Sgabeblack@google.com if (x.wi() < 0) { 187012854Sgabeblack@google.com resize_to(size() - x.wi(), -1); 187112854Sgabeblack@google.com x.wi(0); 187212854Sgabeblack@google.com } 187312854Sgabeblack@google.com 187412854Sgabeblack@google.com bool zero_left = o_zero_left(x); 187512854Sgabeblack@google.com bool bit_at = o_bit_at(x); 187612854Sgabeblack@google.com bool zero_right = o_zero_right(x); 187712854Sgabeblack@google.com 187812854Sgabeblack@google.com bool under = false; 187912854Sgabeblack@google.com bool over = false; 188012854Sgabeblack@google.com 188112854Sgabeblack@google.com sc_enc enc = params.enc(); 188212854Sgabeblack@google.com 188312854Sgabeblack@google.com if (enc == SC_TC_) { 188412854Sgabeblack@google.com if (is_neg()) { 188512854Sgabeblack@google.com if (params.o_mode() == SC_SAT_SYM) 188612854Sgabeblack@google.com under = (!zero_left || bit_at); 188712854Sgabeblack@google.com else 188812854Sgabeblack@google.com under = (!zero_left || (zero_left && bit_at && ! zero_right)); 188912854Sgabeblack@google.com } else { 189012854Sgabeblack@google.com over = (! zero_left || bit_at); 189112854Sgabeblack@google.com } 189212854Sgabeblack@google.com } else { 189312854Sgabeblack@google.com if (is_neg()) 189412854Sgabeblack@google.com under = (!is_zero()); 189512854Sgabeblack@google.com else 189612854Sgabeblack@google.com over = (!zero_left); 189712854Sgabeblack@google.com } 189812854Sgabeblack@google.com 189912854Sgabeblack@google.com o_flag = (under || over); 190012854Sgabeblack@google.com 190112854Sgabeblack@google.com if (o_flag) { 190212854Sgabeblack@google.com scfx_index x2 = calc_indices(params.iwl() - params.wl()); 190312854Sgabeblack@google.com 190412854Sgabeblack@google.com if (x2.wi() < 0) { 190512854Sgabeblack@google.com resize_to(size() - x2.wi(), -1); 190612854Sgabeblack@google.com x.wi(x.wi() - x2.wi()); 190712854Sgabeblack@google.com x2.wi(0); 190812854Sgabeblack@google.com } 190912854Sgabeblack@google.com 191012854Sgabeblack@google.com switch (params.o_mode()) { 191112854Sgabeblack@google.com case SC_WRAP: // wrap-around 191212854Sgabeblack@google.com { 191312854Sgabeblack@google.com int n_bits = params.n_bits(); 191412854Sgabeblack@google.com 191512854Sgabeblack@google.com if (n_bits == 0) { 191612854Sgabeblack@google.com // wrap-around all 'wl' bits 191712854Sgabeblack@google.com toggle_tc(); 191812854Sgabeblack@google.com o_extend(x, enc); 191912854Sgabeblack@google.com toggle_tc(); 192012854Sgabeblack@google.com } else if (n_bits < params.wl()) { 192112854Sgabeblack@google.com scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits); 192212854Sgabeblack@google.com 192312854Sgabeblack@google.com // wrap-around least significant 'wl - n_bits' bits; 192412854Sgabeblack@google.com // saturate most significant 'n_bits' bits 192512854Sgabeblack@google.com toggle_tc(); 192612854Sgabeblack@google.com o_set(x, x3, enc, under); 192712854Sgabeblack@google.com o_extend(x, enc); 192812854Sgabeblack@google.com toggle_tc(); 192912854Sgabeblack@google.com } else { 193012854Sgabeblack@google.com // saturate all 'wl' bits 193112854Sgabeblack@google.com if (under) 193212854Sgabeblack@google.com o_set_low(x, enc); 193312854Sgabeblack@google.com else 193412854Sgabeblack@google.com o_set_high(x, x2, enc); 193512854Sgabeblack@google.com } 193612854Sgabeblack@google.com break; 193712854Sgabeblack@google.com } 193812854Sgabeblack@google.com case SC_SAT: // saturation 193912854Sgabeblack@google.com { 194012854Sgabeblack@google.com if (under) 194112854Sgabeblack@google.com o_set_low(x, enc); 194212854Sgabeblack@google.com else 194312854Sgabeblack@google.com o_set_high(x, x2, enc); 194412854Sgabeblack@google.com break; 194512854Sgabeblack@google.com } 194612854Sgabeblack@google.com case SC_SAT_SYM: // symmetrical saturation 194712854Sgabeblack@google.com { 194812854Sgabeblack@google.com if (under) { 194912854Sgabeblack@google.com if (enc == SC_TC_) 195012854Sgabeblack@google.com o_set_high(x, x2, SC_TC_, -1); 195112854Sgabeblack@google.com else 195212854Sgabeblack@google.com o_set_low(x, SC_US_); 195312854Sgabeblack@google.com } else { 195412854Sgabeblack@google.com o_set_high(x, x2, enc); 195512854Sgabeblack@google.com } 195612854Sgabeblack@google.com break; 195712854Sgabeblack@google.com } 195812854Sgabeblack@google.com case SC_SAT_ZERO: // saturation to zero 195912854Sgabeblack@google.com { 196012854Sgabeblack@google.com set_zero(); 196112854Sgabeblack@google.com break; 196212854Sgabeblack@google.com } 196312854Sgabeblack@google.com case SC_WRAP_SM: // sign magnitude wrap-around 196412854Sgabeblack@google.com { 196512854Sgabeblack@google.com SC_ERROR_IF_(enc == SC_US_, 196612854Sgabeblack@google.com "SC_WRAP_SM not defined for unsigned numbers"); 196712854Sgabeblack@google.com 196812854Sgabeblack@google.com int n_bits = params.n_bits(); 196912854Sgabeblack@google.com 197012854Sgabeblack@google.com if (n_bits == 0) { 197112854Sgabeblack@google.com scfx_index x4 = calc_indices(params.iwl()); 197212854Sgabeblack@google.com 197312854Sgabeblack@google.com if (x4.wi() >= size()) 197412854Sgabeblack@google.com resize_to(x4.wi() + 1, 1); 197512854Sgabeblack@google.com 197612854Sgabeblack@google.com toggle_tc(); 197712854Sgabeblack@google.com if (o_bit_at(x4) != o_bit_at(x)) 197812854Sgabeblack@google.com o_invert(x2); 197912854Sgabeblack@google.com o_extend(x, SC_TC_); 198012854Sgabeblack@google.com toggle_tc(); 198112854Sgabeblack@google.com } else if (n_bits == 1) { 198212854Sgabeblack@google.com toggle_tc(); 198312854Sgabeblack@google.com if (is_neg() != o_bit_at(x)) 198412854Sgabeblack@google.com o_invert(x2); 198512854Sgabeblack@google.com o_extend(x, SC_TC_); 198612854Sgabeblack@google.com toggle_tc(); 198712854Sgabeblack@google.com } else if (n_bits < params.wl()) { 198812854Sgabeblack@google.com scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits); 198912854Sgabeblack@google.com scfx_index x4 = calc_indices(params.iwl() - n_bits); 199012854Sgabeblack@google.com 199112854Sgabeblack@google.com // wrap-around least significant 'wl - n_bits' bits; 199212854Sgabeblack@google.com // saturate most significant 'n_bits' bits 199312854Sgabeblack@google.com toggle_tc(); 199412854Sgabeblack@google.com if (is_neg() == o_bit_at(x4)) 199512854Sgabeblack@google.com o_invert(x2); 199612854Sgabeblack@google.com o_set(x, x3, SC_TC_, under); 199712854Sgabeblack@google.com o_extend(x, SC_TC_); 199812854Sgabeblack@google.com toggle_tc(); 199912854Sgabeblack@google.com } else { 200012854Sgabeblack@google.com if (under) 200112854Sgabeblack@google.com o_set_low(x, SC_TC_); 200212854Sgabeblack@google.com else 200312854Sgabeblack@google.com o_set_high(x, x2, SC_TC_); 200412854Sgabeblack@google.com } 200512854Sgabeblack@google.com break; 200612854Sgabeblack@google.com } 200712854Sgabeblack@google.com default: 200812854Sgabeblack@google.com ; 200912854Sgabeblack@google.com } 201012854Sgabeblack@google.com 201112854Sgabeblack@google.com find_sw(); 201212854Sgabeblack@google.com } 201312854Sgabeblack@google.com} 201412854Sgabeblack@google.com 201512854Sgabeblack@google.com 201612854Sgabeblack@google.com// ---------------------------------------------------------------------------- 201712854Sgabeblack@google.com// PUBLIC METHOD : cast 201812854Sgabeblack@google.com// 201912854Sgabeblack@google.com// Performs a destructive cast operation on a scfx_rep. 202012854Sgabeblack@google.com// ---------------------------------------------------------------------------- 202112854Sgabeblack@google.com 202212854Sgabeblack@google.comvoid 202312854Sgabeblack@google.comscfx_rep::cast(const scfx_params ¶ms, bool &q_flag, bool &o_flag) 202412854Sgabeblack@google.com{ 202512854Sgabeblack@google.com q_flag = false; 202612854Sgabeblack@google.com o_flag = false; 202712854Sgabeblack@google.com 202812854Sgabeblack@google.com // check for special cases 202912854Sgabeblack@google.com if (is_zero()) { 203012854Sgabeblack@google.com if (is_neg()) 203112854Sgabeblack@google.com m_sign = 1; 203212854Sgabeblack@google.com return; 203312854Sgabeblack@google.com } 203412854Sgabeblack@google.com 203512854Sgabeblack@google.com // perform casting 203612854Sgabeblack@google.com quantization(params, q_flag); 203712854Sgabeblack@google.com overflow(params, o_flag); 203812854Sgabeblack@google.com 203912854Sgabeblack@google.com // check for special case: -0 204012854Sgabeblack@google.com if (is_zero() && is_neg()) 204112854Sgabeblack@google.com m_sign = 1; 204212854Sgabeblack@google.com} 204312854Sgabeblack@google.com 204412854Sgabeblack@google.com 204512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 204612854Sgabeblack@google.com// make sure, the two mantissas are aligned 204712854Sgabeblack@google.com// ---------------------------------------------------------------------------- 204812854Sgabeblack@google.com 204912854Sgabeblack@google.comvoid 205012854Sgabeblack@google.comalign(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp, 205112854Sgabeblack@google.com int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant) 205212854Sgabeblack@google.com{ 205312854Sgabeblack@google.com bool need_lhs = true; 205412854Sgabeblack@google.com bool need_rhs = true; 205512854Sgabeblack@google.com 205612854Sgabeblack@google.com if (lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size()) { 205712854Sgabeblack@google.com int lower_bound_lhs = lhs.m_lsw - lhs.m_wp; 205812854Sgabeblack@google.com int upper_bound_lhs = lhs.m_msw - lhs.m_wp; 205912854Sgabeblack@google.com int lower_bound_rhs = rhs.m_lsw - rhs.m_wp; 206012854Sgabeblack@google.com int upper_bound_rhs = rhs.m_msw - rhs.m_wp; 206112854Sgabeblack@google.com 206212854Sgabeblack@google.com int lower_bound = sc_min(lower_bound_lhs, lower_bound_rhs); 206312854Sgabeblack@google.com int upper_bound = sc_max(upper_bound_lhs, upper_bound_rhs); 206412854Sgabeblack@google.com 206512854Sgabeblack@google.com new_wp = -lower_bound; 206612854Sgabeblack@google.com len_mant = sc_max(min_mant, upper_bound - lower_bound + 1); 206712854Sgabeblack@google.com 206812854Sgabeblack@google.com if (new_wp != lhs.m_wp || len_mant != lhs.size()) { 206912854Sgabeblack@google.com lhs_mant = lhs.resize(len_mant, new_wp); 207012854Sgabeblack@google.com need_lhs = false; 207112854Sgabeblack@google.com } 207212854Sgabeblack@google.com 207312854Sgabeblack@google.com if (new_wp != rhs.m_wp || len_mant != rhs.size()) { 207412854Sgabeblack@google.com rhs_mant = rhs.resize(len_mant, new_wp); 207512854Sgabeblack@google.com need_rhs = false; 207612854Sgabeblack@google.com } 207712854Sgabeblack@google.com } 207812854Sgabeblack@google.com 207912854Sgabeblack@google.com if (need_lhs) { 208012854Sgabeblack@google.com lhs_mant = lhs.m_mant; 208112854Sgabeblack@google.com } 208212854Sgabeblack@google.com 208312854Sgabeblack@google.com if (need_rhs) { 208412854Sgabeblack@google.com rhs_mant = rhs.m_mant; 208512854Sgabeblack@google.com } 208612854Sgabeblack@google.com} 208712854Sgabeblack@google.com 208812854Sgabeblack@google.com 208912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 209012854Sgabeblack@google.com// compare two mantissas 209112854Sgabeblack@google.com// ---------------------------------------------------------------------------- 209212854Sgabeblack@google.com 209312854Sgabeblack@google.comint 209412854Sgabeblack@google.comcompare_msw_ff(const scfx_rep &lhs, const scfx_rep &rhs) 209512854Sgabeblack@google.com{ 209612854Sgabeblack@google.com // special case: rhs.m_mant[rhs.m_msw + 1] == 1 209712854Sgabeblack@google.com if (rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0) { 209812854Sgabeblack@google.com return -1; 209912854Sgabeblack@google.com } 210012854Sgabeblack@google.com 210112854Sgabeblack@google.com int lhs_size = lhs.m_msw - lhs.m_lsw + 1; 210212854Sgabeblack@google.com int rhs_size = rhs.m_msw - rhs.m_lsw + 1; 210312854Sgabeblack@google.com 210412854Sgabeblack@google.com int size = sc_min(lhs_size, rhs_size); 210512854Sgabeblack@google.com 210612854Sgabeblack@google.com int lhs_index = lhs.m_msw; 210712854Sgabeblack@google.com int rhs_index = rhs.m_msw; 210812854Sgabeblack@google.com 210912854Sgabeblack@google.com int i; 211012854Sgabeblack@google.com 211112854Sgabeblack@google.com for (i = 0; 211212854Sgabeblack@google.com i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index]; 211312854Sgabeblack@google.com i++) { 211412854Sgabeblack@google.com lhs_index--; 211512854Sgabeblack@google.com rhs_index--; 211612854Sgabeblack@google.com } 211712854Sgabeblack@google.com 211812854Sgabeblack@google.com if (i == size) { 211912854Sgabeblack@google.com if (lhs_size == rhs_size) { 212012854Sgabeblack@google.com return 0; 212112854Sgabeblack@google.com } 212212854Sgabeblack@google.com 212312854Sgabeblack@google.com if (lhs_size < rhs_size) { 212412854Sgabeblack@google.com return -1; 212512854Sgabeblack@google.com } else { 212612854Sgabeblack@google.com return 1; 212712854Sgabeblack@google.com } 212812854Sgabeblack@google.com } 212912854Sgabeblack@google.com 213012854Sgabeblack@google.com if (lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index]) { 213112854Sgabeblack@google.com return -1; 213212854Sgabeblack@google.com } else { 213312854Sgabeblack@google.com return 1; 213412854Sgabeblack@google.com } 213512854Sgabeblack@google.com} 213612854Sgabeblack@google.com 213712854Sgabeblack@google.com 213812854Sgabeblack@google.com// ---------------------------------------------------------------------------- 213912854Sgabeblack@google.com// divide the mantissa by ten 214012854Sgabeblack@google.com// ---------------------------------------------------------------------------- 214112854Sgabeblack@google.com 214212854Sgabeblack@google.comunsigned int 214312854Sgabeblack@google.comscfx_rep::divide_by_ten() 214412854Sgabeblack@google.com{ 214512854Sgabeblack@google.com#if defined(SC_BOOST_BIG_ENDIAN) 214612854Sgabeblack@google.com half_word *hw = (half_word *)&m_mant[m_msw]; 214712854Sgabeblack@google.com#elif defined(SC_BOOST_LITTLE_ENDIAN) 214812854Sgabeblack@google.com half_word *hw = ((half_word *)&m_mant[m_msw]) + 1; 214912854Sgabeblack@google.com#endif 215012854Sgabeblack@google.com 215112854Sgabeblack@google.com unsigned int remainder = 0; 215212854Sgabeblack@google.com 215312854Sgabeblack@google.com word_short ls; 215412854Sgabeblack@google.com ls.l = 0; 215512854Sgabeblack@google.com 215612854Sgabeblack@google.com#if defined(SC_BOOST_BIG_ENDIAN) 215712854Sgabeblack@google.com for (int i = 0, end = (m_msw - m_wp + 1) * 2; i < end; i++) { 215812854Sgabeblack@google.com#elif defined(SC_BOOST_LITTLE_ENDIAN) 215912854Sgabeblack@google.com for (int i = 0, end = -(m_msw - m_wp + 1) * 2; i > end; i--) { 216012854Sgabeblack@google.com#endif 216112854Sgabeblack@google.com ls.s.u = static_cast<half_word>(remainder); 216212854Sgabeblack@google.com ls.s.l = hw[i]; 216312854Sgabeblack@google.com remainder = ls.l % 10; 216412854Sgabeblack@google.com ls.l /= 10; 216512854Sgabeblack@google.com hw[i] = ls.s.l; 216612854Sgabeblack@google.com } 216712854Sgabeblack@google.com 216812854Sgabeblack@google.com return remainder; 216912854Sgabeblack@google.com} 217012854Sgabeblack@google.com 217112854Sgabeblack@google.com 217212854Sgabeblack@google.com// ---------------------------------------------------------------------------- 217312854Sgabeblack@google.com// multiply the mantissa by ten 217412854Sgabeblack@google.com// ---------------------------------------------------------------------------- 217512854Sgabeblack@google.com 217612854Sgabeblack@google.comvoid 217712854Sgabeblack@google.comscfx_rep::multiply_by_ten() 217812854Sgabeblack@google.com{ 217912854Sgabeblack@google.com int size = m_mant.size() + 1; 218012854Sgabeblack@google.com 218112854Sgabeblack@google.com scfx_mant mant8(size); 218212854Sgabeblack@google.com scfx_mant mant2(size); 218312854Sgabeblack@google.com 218412854Sgabeblack@google.com size--; 218512854Sgabeblack@google.com 218612854Sgabeblack@google.com mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3)); 218712854Sgabeblack@google.com mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1)); 218812854Sgabeblack@google.com 218912854Sgabeblack@google.com while (--size) { 219012854Sgabeblack@google.com mant8[size] = (m_mant[size] << 3) | 219112854Sgabeblack@google.com (m_mant[size - 1] >> (bits_in_word - 3)); 219212854Sgabeblack@google.com mant2[size] = (m_mant[size] << 1) | 219312854Sgabeblack@google.com (m_mant[size - 1] >> (bits_in_word - 1)); 219412854Sgabeblack@google.com } 219512854Sgabeblack@google.com 219612854Sgabeblack@google.com mant8[0] = (m_mant[0] << 3); 219712854Sgabeblack@google.com mant2[0] = (m_mant[0] << 1); 219812854Sgabeblack@google.com 219912854Sgabeblack@google.com add_mants(m_mant.size(), m_mant, mant8, mant2); 220012854Sgabeblack@google.com} 220112854Sgabeblack@google.com 220212854Sgabeblack@google.com 220312854Sgabeblack@google.com// ---------------------------------------------------------------------------- 220412854Sgabeblack@google.com// normalize 220512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 220612854Sgabeblack@google.com 220712854Sgabeblack@google.comvoid 220812854Sgabeblack@google.comscfx_rep::normalize(int exponent) 220912854Sgabeblack@google.com{ 221012854Sgabeblack@google.com int shift = exponent % bits_in_word; 221112854Sgabeblack@google.com if (shift < 0) { 221212854Sgabeblack@google.com shift += bits_in_word; 221312854Sgabeblack@google.com } 221412854Sgabeblack@google.com 221512854Sgabeblack@google.com if (shift) { 221612854Sgabeblack@google.com shift_left(shift); 221712854Sgabeblack@google.com } 221812854Sgabeblack@google.com 221912854Sgabeblack@google.com find_sw(); 222012854Sgabeblack@google.com 222112854Sgabeblack@google.com m_wp = (shift - exponent) / bits_in_word; 222212854Sgabeblack@google.com} 222312854Sgabeblack@google.com 222412854Sgabeblack@google.com 222512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 222612854Sgabeblack@google.com// return a new mantissa that is aligned and resized 222712854Sgabeblack@google.com// ---------------------------------------------------------------------------- 222812854Sgabeblack@google.com 222912854Sgabeblack@google.comscfx_mant * 223012854Sgabeblack@google.comscfx_rep::resize(int new_size, int new_wp) const 223112854Sgabeblack@google.com{ 223212854Sgabeblack@google.com scfx_mant *result = new scfx_mant(new_size); 223312854Sgabeblack@google.com 223412854Sgabeblack@google.com result->clear(); 223512854Sgabeblack@google.com 223612854Sgabeblack@google.com int shift = new_wp - m_wp; 223712854Sgabeblack@google.com 223812854Sgabeblack@google.com for (int j = m_lsw; j <= m_msw; j++) { 223912854Sgabeblack@google.com (*result)[j + shift] = m_mant[j]; 224012854Sgabeblack@google.com } 224112854Sgabeblack@google.com 224212854Sgabeblack@google.com return result; 224312854Sgabeblack@google.com} 224412854Sgabeblack@google.com 224512854Sgabeblack@google.com 224612854Sgabeblack@google.com// ---------------------------------------------------------------------------- 224712854Sgabeblack@google.com// set a single bit 224812854Sgabeblack@google.com// ---------------------------------------------------------------------------- 224912854Sgabeblack@google.com 225012854Sgabeblack@google.comvoid 225112854Sgabeblack@google.comscfx_rep::set_bin(int i) 225212854Sgabeblack@google.com{ 225312854Sgabeblack@google.com m_mant[i >> 5] |= 1 << (i & 31); 225412854Sgabeblack@google.com} 225512854Sgabeblack@google.com 225612854Sgabeblack@google.com 225712854Sgabeblack@google.com// ---------------------------------------------------------------------------- 225812854Sgabeblack@google.com// set three bits 225912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 226012854Sgabeblack@google.com 226112854Sgabeblack@google.comvoid 226212854Sgabeblack@google.comscfx_rep::set_oct(int i, int n) 226312854Sgabeblack@google.com{ 226412854Sgabeblack@google.com if (n & 1) { 226512854Sgabeblack@google.com m_mant[i >> 5] |= 1 << (i & 31); 226612854Sgabeblack@google.com } 226712854Sgabeblack@google.com i++; 226812854Sgabeblack@google.com if (n & 2) { 226912854Sgabeblack@google.com m_mant[i >> 5] |= 1 << (i & 31); 227012854Sgabeblack@google.com } 227112854Sgabeblack@google.com i++; 227212854Sgabeblack@google.com if (n & 4) { 227312854Sgabeblack@google.com m_mant[i >> 5] |= 1 << (i & 31); 227412854Sgabeblack@google.com } 227512854Sgabeblack@google.com} 227612854Sgabeblack@google.com 227712854Sgabeblack@google.com 227812854Sgabeblack@google.com// ---------------------------------------------------------------------------- 227912854Sgabeblack@google.com// set four bits 228012854Sgabeblack@google.com// ---------------------------------------------------------------------------- 228112854Sgabeblack@google.com 228212854Sgabeblack@google.comvoid 228312854Sgabeblack@google.comscfx_rep::set_hex(int i, int n) 228412854Sgabeblack@google.com{ 228512854Sgabeblack@google.com if (n & 1) { 228612854Sgabeblack@google.com m_mant[i >> 5] |= 1 << (i & 31); 228712854Sgabeblack@google.com } 228812854Sgabeblack@google.com i++; 228912854Sgabeblack@google.com if (n & 2) { 229012854Sgabeblack@google.com m_mant[i >> 5] |= 1 << (i & 31); 229112854Sgabeblack@google.com } 229212854Sgabeblack@google.com i++; 229312854Sgabeblack@google.com if (n & 4) { 229412854Sgabeblack@google.com m_mant[i >> 5] |= 1 << (i & 31); 229512854Sgabeblack@google.com } 229612854Sgabeblack@google.com i++; 229712854Sgabeblack@google.com if (n & 8) { 229812854Sgabeblack@google.com m_mant[i >> 5] |= 1 << (i & 31); 229912854Sgabeblack@google.com } 230012854Sgabeblack@google.com} 230112854Sgabeblack@google.com 230212854Sgabeblack@google.com 230312854Sgabeblack@google.com// ---------------------------------------------------------------------------- 230412854Sgabeblack@google.com// PRIVATE METHOD : shift_left 230512854Sgabeblack@google.com// 230612854Sgabeblack@google.com// Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits. 230712854Sgabeblack@google.com// ---------------------------------------------------------------------------- 230812854Sgabeblack@google.com 230912854Sgabeblack@google.comvoid 231012854Sgabeblack@google.comscfx_rep::shift_left(int n) 231112854Sgabeblack@google.com{ 231212854Sgabeblack@google.com if (n != 0) { 231312854Sgabeblack@google.com int shift_left = n; 231412854Sgabeblack@google.com int shift_right = bits_in_word - n; 231512854Sgabeblack@google.com 231612854Sgabeblack@google.com SC_ASSERT_(!(m_mant[size() - 1] >> shift_right), 231712854Sgabeblack@google.com "shift_left overflow"); 231812854Sgabeblack@google.com 231912854Sgabeblack@google.com for (int i = size() - 1; i > 0; i--) { 232012854Sgabeblack@google.com m_mant[i] = (m_mant[i] << shift_left) | 232112854Sgabeblack@google.com (m_mant[i - 1] >> shift_right); 232212854Sgabeblack@google.com } 232312854Sgabeblack@google.com m_mant[0] <<= shift_left; 232412854Sgabeblack@google.com } 232512854Sgabeblack@google.com} 232612854Sgabeblack@google.com 232712854Sgabeblack@google.com 232812854Sgabeblack@google.com// ---------------------------------------------------------------------------- 232912854Sgabeblack@google.com// PRIVATE METHOD : shift_right 233012854Sgabeblack@google.com// 233112854Sgabeblack@google.com// Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits. 233212854Sgabeblack@google.com// ---------------------------------------------------------------------------- 233312854Sgabeblack@google.com 233412854Sgabeblack@google.comvoid 233512854Sgabeblack@google.comscfx_rep::shift_right(int n) 233612854Sgabeblack@google.com{ 233712854Sgabeblack@google.com if (n != 0) { 233812854Sgabeblack@google.com int shift_left = bits_in_word - n; 233912854Sgabeblack@google.com int shift_right = n; 234012854Sgabeblack@google.com 234112854Sgabeblack@google.com SC_ASSERT_(!(m_mant[0] << shift_left), "shift_right overflow"); 234212854Sgabeblack@google.com 234312854Sgabeblack@google.com for (int i = 0; i < size() - 1; i++) { 234412854Sgabeblack@google.com m_mant[i] = (m_mant[i] >> shift_right) | 234512854Sgabeblack@google.com (m_mant[i + 1] << shift_left); 234612854Sgabeblack@google.com } 234712854Sgabeblack@google.com m_mant[size() - 1] >>= shift_right; 234812854Sgabeblack@google.com } 234912854Sgabeblack@google.com} 235012854Sgabeblack@google.com 235112854Sgabeblack@google.com 235212854Sgabeblack@google.com// ---------------------------------------------------------------------------- 235312854Sgabeblack@google.com// METHOD : get_bit 235412854Sgabeblack@google.com// 235512854Sgabeblack@google.com// Tests a bit, in two's complement. 235612854Sgabeblack@google.com// ---------------------------------------------------------------------------- 235712854Sgabeblack@google.com 235812854Sgabeblack@google.combool 235912854Sgabeblack@google.comscfx_rep::get_bit(int i) const 236012854Sgabeblack@google.com{ 236112854Sgabeblack@google.com if (!is_normal()) 236212854Sgabeblack@google.com return false; 236312854Sgabeblack@google.com 236412854Sgabeblack@google.com scfx_index x = calc_indices(i); 236512854Sgabeblack@google.com 236612854Sgabeblack@google.com if (x.wi() >= size()) 236712854Sgabeblack@google.com return is_neg(); 236812854Sgabeblack@google.com 236912854Sgabeblack@google.com if (x.wi() < 0) 237012854Sgabeblack@google.com return false; 237112854Sgabeblack@google.com 237212854Sgabeblack@google.com const_cast<scfx_rep*>(this)->toggle_tc(); 237312854Sgabeblack@google.com 237412854Sgabeblack@google.com bool result = (m_mant[x.wi()] & (1 << x.bi())) != 0; 237512854Sgabeblack@google.com 237612854Sgabeblack@google.com const_cast<scfx_rep *>(this)->toggle_tc(); 237712854Sgabeblack@google.com 237812854Sgabeblack@google.com return result; 237912854Sgabeblack@google.com} 238012854Sgabeblack@google.com 238112854Sgabeblack@google.com 238212854Sgabeblack@google.com// ---------------------------------------------------------------------------- 238312854Sgabeblack@google.com// METHOD : set 238412854Sgabeblack@google.com// 238512854Sgabeblack@google.com// Sets a bit, in two's complement, between iwl-1 and -fwl. 238612854Sgabeblack@google.com// ---------------------------------------------------------------------------- 238712854Sgabeblack@google.com 238812854Sgabeblack@google.combool 238912854Sgabeblack@google.comscfx_rep::set(int i, const scfx_params ¶ms) 239012854Sgabeblack@google.com{ 239112854Sgabeblack@google.com if (!is_normal()) 239212854Sgabeblack@google.com return false; 239312854Sgabeblack@google.com 239412854Sgabeblack@google.com scfx_index x = calc_indices(i); 239512854Sgabeblack@google.com 239612854Sgabeblack@google.com if (x.wi() >= size()) { 239712854Sgabeblack@google.com if (is_neg()) 239812854Sgabeblack@google.com return true; 239912854Sgabeblack@google.com else 240012854Sgabeblack@google.com resize_to(x.wi() + 1, 1); 240112854Sgabeblack@google.com } else if (x.wi() < 0) { 240212854Sgabeblack@google.com resize_to(size() - x.wi(), -1); 240312854Sgabeblack@google.com x.wi(0); 240412854Sgabeblack@google.com } 240512854Sgabeblack@google.com 240612854Sgabeblack@google.com toggle_tc(); 240712854Sgabeblack@google.com 240812854Sgabeblack@google.com m_mant[x.wi()] |= 1 << x.bi(); 240912854Sgabeblack@google.com 241012854Sgabeblack@google.com if (i == params.iwl() - 1) 241112854Sgabeblack@google.com o_extend(x, params.enc()); // sign extension 241212854Sgabeblack@google.com 241312854Sgabeblack@google.com toggle_tc(); 241412854Sgabeblack@google.com 241512854Sgabeblack@google.com find_sw(); 241612854Sgabeblack@google.com 241712854Sgabeblack@google.com return true; 241812854Sgabeblack@google.com} 241912854Sgabeblack@google.com 242012854Sgabeblack@google.com 242112854Sgabeblack@google.com// ---------------------------------------------------------------------------- 242212854Sgabeblack@google.com// METHOD : clear 242312854Sgabeblack@google.com// 242412854Sgabeblack@google.com// Clears a bit, in two's complement, between iwl-1 and -fwl. 242512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 242612854Sgabeblack@google.com 242712854Sgabeblack@google.combool 242812854Sgabeblack@google.comscfx_rep::clear(int i, const scfx_params ¶ms) 242912854Sgabeblack@google.com{ 243012854Sgabeblack@google.com if (!is_normal()) 243112854Sgabeblack@google.com return false; 243212854Sgabeblack@google.com 243312854Sgabeblack@google.com scfx_index x = calc_indices(i); 243412854Sgabeblack@google.com 243512854Sgabeblack@google.com if (x.wi() >= size()) { 243612854Sgabeblack@google.com if (!is_neg()) 243712854Sgabeblack@google.com return true; 243812854Sgabeblack@google.com else 243912854Sgabeblack@google.com resize_to(x.wi() + 1, 1); 244012854Sgabeblack@google.com } else if (x.wi() < 0) { 244112854Sgabeblack@google.com return true; 244212854Sgabeblack@google.com } 244312854Sgabeblack@google.com 244412854Sgabeblack@google.com toggle_tc(); 244512854Sgabeblack@google.com 244612854Sgabeblack@google.com m_mant[x.wi()] &= ~(1 << x.bi()); 244712854Sgabeblack@google.com 244812854Sgabeblack@google.com if (i == params.iwl() - 1) 244912854Sgabeblack@google.com o_extend(x, params.enc()); // sign extension 245012854Sgabeblack@google.com 245112854Sgabeblack@google.com toggle_tc(); 245212854Sgabeblack@google.com 245312854Sgabeblack@google.com find_sw(); 245412854Sgabeblack@google.com 245512854Sgabeblack@google.com return true; 245612854Sgabeblack@google.com} 245712854Sgabeblack@google.com 245812854Sgabeblack@google.com 245912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 246012854Sgabeblack@google.com// METHOD : get_slice 246112854Sgabeblack@google.com// ---------------------------------------------------------------------------- 246212854Sgabeblack@google.com 246312854Sgabeblack@google.combool 246412854Sgabeblack@google.comscfx_rep::get_slice(int i, int j, const scfx_params &, sc_bv_base &bv) const 246512854Sgabeblack@google.com{ 246612854Sgabeblack@google.com if (is_nan() || is_inf()) 246712854Sgabeblack@google.com return false; 246812854Sgabeblack@google.com 246912854Sgabeblack@google.com // get the bits 247012854Sgabeblack@google.com 247112854Sgabeblack@google.com int l = j; 247212854Sgabeblack@google.com for (int k = 0; k < bv.length(); ++k) { 247312854Sgabeblack@google.com bv[k] = get_bit(l); 247412854Sgabeblack@google.com 247512854Sgabeblack@google.com if (i >= j) 247612854Sgabeblack@google.com ++l; 247712854Sgabeblack@google.com else 247812854Sgabeblack@google.com --l; 247912854Sgabeblack@google.com } 248012854Sgabeblack@google.com 248112854Sgabeblack@google.com return true; 248212854Sgabeblack@google.com} 248312854Sgabeblack@google.com 248412854Sgabeblack@google.combool 248512854Sgabeblack@google.comscfx_rep::set_slice(int i, int j, const scfx_params ¶ms, 248612854Sgabeblack@google.com const sc_bv_base &bv) 248712854Sgabeblack@google.com{ 248812854Sgabeblack@google.com if (is_nan() || is_inf()) 248912854Sgabeblack@google.com return false; 249012854Sgabeblack@google.com 249112854Sgabeblack@google.com // set the bits 249212854Sgabeblack@google.com int l = j; 249312854Sgabeblack@google.com for (int k = 0; k < bv.length(); ++k) { 249412854Sgabeblack@google.com if (bv[k].to_bool()) 249512854Sgabeblack@google.com set(l, params); 249612854Sgabeblack@google.com else 249712854Sgabeblack@google.com clear(l, params); 249812854Sgabeblack@google.com 249912854Sgabeblack@google.com if (i >= j) 250012854Sgabeblack@google.com ++l; 250112854Sgabeblack@google.com else 250212854Sgabeblack@google.com --l; 250312854Sgabeblack@google.com } 250412854Sgabeblack@google.com 250512854Sgabeblack@google.com return true; 250612854Sgabeblack@google.com} 250712854Sgabeblack@google.com 250812854Sgabeblack@google.com 250912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 251012854Sgabeblack@google.com// METHOD : print 251112854Sgabeblack@google.com// ---------------------------------------------------------------------------- 251212854Sgabeblack@google.com 251312854Sgabeblack@google.comvoid 251412854Sgabeblack@google.comscfx_rep::print(::std::ostream &os) const 251512854Sgabeblack@google.com{ 251612854Sgabeblack@google.com os << to_string(SC_DEC, -1, SC_E); 251712854Sgabeblack@google.com} 251812854Sgabeblack@google.com 251912854Sgabeblack@google.com 252012854Sgabeblack@google.com// ---------------------------------------------------------------------------- 252112854Sgabeblack@google.com// METHOD : dump 252212854Sgabeblack@google.com// ---------------------------------------------------------------------------- 252312854Sgabeblack@google.com 252412854Sgabeblack@google.comvoid 252512854Sgabeblack@google.comscfx_rep::dump(::std::ostream &os) const 252612854Sgabeblack@google.com{ 252712854Sgabeblack@google.com os << "scfx_rep" << ::std::endl; 252812854Sgabeblack@google.com os << "(" << ::std::endl; 252912854Sgabeblack@google.com 253012854Sgabeblack@google.com os << "mant =" << ::std::endl; 253112854Sgabeblack@google.com for (int i = size() - 1; i >= 0; i--) { 253212854Sgabeblack@google.com char buf[BUFSIZ]; 253312854Sgabeblack@google.com std::sprintf(buf, " %d: %10u (%8x)", i, 253412854Sgabeblack@google.com (int)m_mant[i], (int)m_mant[i]); 253512854Sgabeblack@google.com os << buf << ::std::endl; 253612854Sgabeblack@google.com } 253712854Sgabeblack@google.com 253812854Sgabeblack@google.com os << "wp = " << m_wp << ::std::endl; 253912854Sgabeblack@google.com os << "sign = " << m_sign << ::std::endl; 254012854Sgabeblack@google.com 254112854Sgabeblack@google.com os << "state = "; 254212854Sgabeblack@google.com switch (m_state) { 254312854Sgabeblack@google.com case normal: 254412854Sgabeblack@google.com os << "normal"; 254512854Sgabeblack@google.com break; 254612854Sgabeblack@google.com case infinity: 254712854Sgabeblack@google.com os << "infinity"; 254812854Sgabeblack@google.com break; 254912854Sgabeblack@google.com case not_a_number: 255012854Sgabeblack@google.com os << "not_a_number"; 255112854Sgabeblack@google.com break; 255212854Sgabeblack@google.com default: 255312854Sgabeblack@google.com os << "unknown"; 255412854Sgabeblack@google.com } 255512854Sgabeblack@google.com os << ::std::endl; 255612854Sgabeblack@google.com 255712854Sgabeblack@google.com os << "msw = " << m_msw << ::std::endl; 255812854Sgabeblack@google.com os << "lsw = " << m_lsw << ::std::endl; 255912854Sgabeblack@google.com 256012854Sgabeblack@google.com os << ")" << ::std::endl; 256112854Sgabeblack@google.com} 256212854Sgabeblack@google.com 256312854Sgabeblack@google.com 256412854Sgabeblack@google.com// ---------------------------------------------------------------------------- 256512854Sgabeblack@google.com// METHOD : get_type 256612854Sgabeblack@google.com// ---------------------------------------------------------------------------- 256712854Sgabeblack@google.com 256812854Sgabeblack@google.comvoid 256912854Sgabeblack@google.comscfx_rep::get_type(int &wl, int &iwl, sc_enc &enc) const 257012854Sgabeblack@google.com{ 257112854Sgabeblack@google.com if (is_nan() || is_inf()) { 257212854Sgabeblack@google.com wl = 0; 257312854Sgabeblack@google.com iwl = 0; 257412854Sgabeblack@google.com enc = SC_TC_; 257512854Sgabeblack@google.com return; 257612854Sgabeblack@google.com } 257712854Sgabeblack@google.com 257812854Sgabeblack@google.com if (is_zero()) { 257912854Sgabeblack@google.com wl = 1; 258012854Sgabeblack@google.com iwl = 1; 258112854Sgabeblack@google.com enc = SC_US_; 258212854Sgabeblack@google.com return; 258312854Sgabeblack@google.com } 258412854Sgabeblack@google.com 258512854Sgabeblack@google.com int msb = (m_msw - m_wp) * bits_in_word + 258612854Sgabeblack@google.com scfx_find_msb(m_mant[ m_msw ]) + 1; 258712854Sgabeblack@google.com while (get_bit(msb) == get_bit(msb - 1)) { 258812854Sgabeblack@google.com --msb; 258912854Sgabeblack@google.com } 259012854Sgabeblack@google.com 259112854Sgabeblack@google.com int lsb = (m_lsw - m_wp) * bits_in_word + 259212854Sgabeblack@google.com scfx_find_lsb(m_mant[m_lsw]); 259312854Sgabeblack@google.com 259412854Sgabeblack@google.com if (is_neg()) { 259512854Sgabeblack@google.com wl = msb - lsb + 1; 259612854Sgabeblack@google.com iwl = msb + 1; 259712854Sgabeblack@google.com enc = SC_TC_; 259812854Sgabeblack@google.com } else { 259912854Sgabeblack@google.com wl = msb - lsb; 260012854Sgabeblack@google.com iwl = msb; 260112854Sgabeblack@google.com enc = SC_US_; 260212854Sgabeblack@google.com } 260312854Sgabeblack@google.com} 260412854Sgabeblack@google.com 260512854Sgabeblack@google.com 260612854Sgabeblack@google.com// ---------------------------------------------------------------------------- 260712854Sgabeblack@google.com// PRIVATE METHOD : round 260812854Sgabeblack@google.com// 260912854Sgabeblack@google.com// Performs convergent rounding (rounding to even) as in floating-point. 261012854Sgabeblack@google.com// ---------------------------------------------------------------------------- 261112854Sgabeblack@google.com 261212854Sgabeblack@google.comvoid 261312854Sgabeblack@google.comscfx_rep::round(int wl) 261412854Sgabeblack@google.com{ 261512854Sgabeblack@google.com // check for special cases 261612854Sgabeblack@google.com 261712854Sgabeblack@google.com if (is_nan() || is_inf() || is_zero()) 261812854Sgabeblack@google.com return; 261912854Sgabeblack@google.com 262012854Sgabeblack@google.com // estimate effective wordlength and compare 262112854Sgabeblack@google.com int wl_effective; 262212854Sgabeblack@google.com wl_effective = (m_msw - m_lsw + 1) * bits_in_word; 262312854Sgabeblack@google.com if (wl_effective <= wl) 262412854Sgabeblack@google.com return; 262512854Sgabeblack@google.com 262612854Sgabeblack@google.com // calculate effective wordlength and compare 262712854Sgabeblack@google.com int msb = scfx_find_msb(m_mant[m_msw]); 262812854Sgabeblack@google.com int lsb = scfx_find_lsb(m_mant[m_lsw]); 262912854Sgabeblack@google.com wl_effective = (m_msw * bits_in_word + msb) - 263012854Sgabeblack@google.com (m_lsw * bits_in_word + lsb) + 1; 263112854Sgabeblack@google.com if (wl_effective <= wl) 263212854Sgabeblack@google.com return; 263312854Sgabeblack@google.com 263412854Sgabeblack@google.com // perform rounding 263512854Sgabeblack@google.com int wi = m_msw - (wl - 1) / bits_in_word; 263612854Sgabeblack@google.com int bi = msb - (wl - 1) % bits_in_word; 263712854Sgabeblack@google.com if (bi < 0) { 263812854Sgabeblack@google.com --wi; 263912854Sgabeblack@google.com bi += bits_in_word; 264012854Sgabeblack@google.com } 264112854Sgabeblack@google.com 264212854Sgabeblack@google.com scfx_index x(wi, bi); 264312854Sgabeblack@google.com 264412854Sgabeblack@google.com if ((q_bit(x) && ! q_zero(x)) || (q_bit(x) && q_zero(x) && q_odd(x))) { 264512854Sgabeblack@google.com q_incr(x); 264612854Sgabeblack@google.com } 264712854Sgabeblack@google.com q_clear(x); 264812854Sgabeblack@google.com 264912854Sgabeblack@google.com find_sw(); 265012854Sgabeblack@google.com 265112854Sgabeblack@google.com m_r_flag = true; 265212854Sgabeblack@google.com} 265312854Sgabeblack@google.com 265412854Sgabeblack@google.com} // namespace sc_dt 2655