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