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