sc_fxval.cc revision 12854
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 sc_fxval.cpp - 2312854Sgabeblack@google.com 2412854Sgabeblack@google.com Original Author: Martin Janssen, Synopsys, Inc. 2512854Sgabeblack@google.com 2612854Sgabeblack@google.com *****************************************************************************/ 2712854Sgabeblack@google.com 2812854Sgabeblack@google.com/***************************************************************************** 2912854Sgabeblack@google.com 3012854Sgabeblack@google.com MODIFICATION LOG - modifiers, enter your name, affiliation, date and 3112854Sgabeblack@google.com changes you are making here. 3212854Sgabeblack@google.com 3312854Sgabeblack@google.com Name, Affiliation, Date: 3412854Sgabeblack@google.com Description of Modification: 3512854Sgabeblack@google.com 3612854Sgabeblack@google.com *****************************************************************************/ 3712854Sgabeblack@google.com 3812854Sgabeblack@google.com 3912854Sgabeblack@google.com// $Log: sc_fxval.cpp,v $ 4012854Sgabeblack@google.com// Revision 1.1.1.1 2006/12/15 20:20:04 acg 4112854Sgabeblack@google.com// SystemC 2.3 4212854Sgabeblack@google.com// 4312854Sgabeblack@google.com// Revision 1.3 2006/01/13 18:53:58 acg 4412854Sgabeblack@google.com// Andy Goodrich: added $Log command so that CVS comments are reproduced in 4512854Sgabeblack@google.com// the source. 4612854Sgabeblack@google.com// 4712854Sgabeblack@google.com 4812854Sgabeblack@google.com#include <cctype> 4912854Sgabeblack@google.com#include <cfloat> 5012854Sgabeblack@google.com#include <cmath> 5112854Sgabeblack@google.com#include <cstdlib> 5212854Sgabeblack@google.com 5312854Sgabeblack@google.com#include "systemc/ext/dt/fx/sc_fxval.hh" 5412854Sgabeblack@google.com 5512854Sgabeblack@google.comnamespace sc_dt 5612854Sgabeblack@google.com{ 5712854Sgabeblack@google.com 5812854Sgabeblack@google.com// ---------------------------------------------------------------------------- 5912854Sgabeblack@google.com// CLASS : sc_fxval 6012854Sgabeblack@google.com// 6112854Sgabeblack@google.com// Fixed-point value type; arbitrary precision. 6212854Sgabeblack@google.com// ---------------------------------------------------------------------------- 6312854Sgabeblack@google.com 6412854Sgabeblack@google.com// explicit conversion to character string 6512854Sgabeblack@google.com 6612854Sgabeblack@google.comconst std::string 6712854Sgabeblack@google.comsc_fxval::to_string() const 6812854Sgabeblack@google.com{ 6912854Sgabeblack@google.com return std::string(m_rep->to_string(SC_DEC, -1, SC_E)); 7012854Sgabeblack@google.com} 7112854Sgabeblack@google.com 7212854Sgabeblack@google.comconst std::string 7312854Sgabeblack@google.comsc_fxval::to_string(sc_numrep numrep) const 7412854Sgabeblack@google.com{ 7512854Sgabeblack@google.com return std::string(m_rep->to_string(numrep, -1, SC_E)); 7612854Sgabeblack@google.com} 7712854Sgabeblack@google.com 7812854Sgabeblack@google.comconst std::string 7912854Sgabeblack@google.comsc_fxval::to_string(sc_numrep numrep, bool w_prefix) const 8012854Sgabeblack@google.com{ 8112854Sgabeblack@google.com return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0), SC_E)); 8212854Sgabeblack@google.com} 8312854Sgabeblack@google.com 8412854Sgabeblack@google.comconst std::string 8512854Sgabeblack@google.comsc_fxval::to_string(sc_fmt fmt) const 8612854Sgabeblack@google.com{ 8712854Sgabeblack@google.com return std::string(m_rep->to_string(SC_DEC, -1, fmt)); 8812854Sgabeblack@google.com} 8912854Sgabeblack@google.com 9012854Sgabeblack@google.comconst std::string 9112854Sgabeblack@google.comsc_fxval::to_string(sc_numrep numrep, sc_fmt fmt) const 9212854Sgabeblack@google.com{ 9312854Sgabeblack@google.com return std::string(m_rep->to_string(numrep, -1, fmt)); 9412854Sgabeblack@google.com} 9512854Sgabeblack@google.com 9612854Sgabeblack@google.comconst std::string 9712854Sgabeblack@google.comsc_fxval::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const 9812854Sgabeblack@google.com{ 9912854Sgabeblack@google.com return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0), fmt)); 10012854Sgabeblack@google.com} 10112854Sgabeblack@google.com 10212854Sgabeblack@google.com 10312854Sgabeblack@google.comconst std::string 10412854Sgabeblack@google.comsc_fxval::to_dec() const 10512854Sgabeblack@google.com{ 10612854Sgabeblack@google.com return std::string(m_rep->to_string(SC_DEC, -1, SC_E)); 10712854Sgabeblack@google.com} 10812854Sgabeblack@google.com 10912854Sgabeblack@google.comconst std::string 11012854Sgabeblack@google.comsc_fxval::to_bin() const 11112854Sgabeblack@google.com{ 11212854Sgabeblack@google.com return std::string(m_rep->to_string(SC_BIN, -1, SC_E)); 11312854Sgabeblack@google.com} 11412854Sgabeblack@google.com 11512854Sgabeblack@google.comconst std::string 11612854Sgabeblack@google.comsc_fxval::to_oct() const 11712854Sgabeblack@google.com{ 11812854Sgabeblack@google.com return std::string(m_rep->to_string(SC_OCT, -1, SC_E)); 11912854Sgabeblack@google.com} 12012854Sgabeblack@google.com 12112854Sgabeblack@google.comconst std::string 12212854Sgabeblack@google.comsc_fxval::to_hex() const 12312854Sgabeblack@google.com{ 12412854Sgabeblack@google.com return std::string(m_rep->to_string(SC_HEX, -1, SC_E)); 12512854Sgabeblack@google.com} 12612854Sgabeblack@google.com 12712854Sgabeblack@google.com 12812854Sgabeblack@google.com// print or dump content 12912854Sgabeblack@google.com 13012854Sgabeblack@google.comvoid sc_fxval::print(::std::ostream &os) const { m_rep->print(os); } 13112854Sgabeblack@google.com 13212854Sgabeblack@google.comvoid 13312854Sgabeblack@google.comsc_fxval::scan(::std::istream &is) 13412854Sgabeblack@google.com{ 13512854Sgabeblack@google.com std::string s; 13612854Sgabeblack@google.com is >> s; 13712854Sgabeblack@google.com *this = s.c_str(); 13812854Sgabeblack@google.com} 13912854Sgabeblack@google.com 14012854Sgabeblack@google.comvoid 14112854Sgabeblack@google.comsc_fxval::dump(::std::ostream &os) const 14212854Sgabeblack@google.com{ 14312854Sgabeblack@google.com os << "sc_fxval" << ::std::endl; 14412854Sgabeblack@google.com os << "(" << ::std::endl; 14512854Sgabeblack@google.com os << "rep = "; 14612854Sgabeblack@google.com m_rep->dump(os); 14712854Sgabeblack@google.com // TO BE COMPLETED 14812854Sgabeblack@google.com // os << "r_flag = " << m_r_flag << ::std::endl; 14912854Sgabeblack@google.com // os << "observer = "; 15012854Sgabeblack@google.com // if (m_observer != 0) 15112854Sgabeblack@google.com // m_observer->dump(os); 15212854Sgabeblack@google.com // else 15312854Sgabeblack@google.com // os << "0" << ::std::endl; 15412854Sgabeblack@google.com os << ")" << ::std::endl; 15512854Sgabeblack@google.com} 15612854Sgabeblack@google.com 15712854Sgabeblack@google.com// protected methods and friend functions 15812854Sgabeblack@google.comsc_fxval_observer * 15912854Sgabeblack@google.comsc_fxval::lock_observer() const 16012854Sgabeblack@google.com{ 16112854Sgabeblack@google.com SC_ASSERT_(m_observer != 0, "lock observer failed"); 16212854Sgabeblack@google.com sc_fxval_observer *tmp = m_observer; 16312854Sgabeblack@google.com m_observer = 0; 16412854Sgabeblack@google.com return tmp; 16512854Sgabeblack@google.com} 16612854Sgabeblack@google.com 16712854Sgabeblack@google.comvoid 16812854Sgabeblack@google.comsc_fxval::unlock_observer(sc_fxval_observer *observer_) const 16912854Sgabeblack@google.com{ 17012854Sgabeblack@google.com SC_ASSERT_(observer_ != 0, "unlock observer failed"); 17112854Sgabeblack@google.com m_observer = observer_; 17212854Sgabeblack@google.com} 17312854Sgabeblack@google.com 17412854Sgabeblack@google.com 17512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 17612854Sgabeblack@google.com// CLASS : sc_fxval_fast 17712854Sgabeblack@google.com// 17812854Sgabeblack@google.com// Fixed-point value types; limited precision. 17912854Sgabeblack@google.com// ---------------------------------------------------------------------------- 18012854Sgabeblack@google.com 18112854Sgabeblack@google.comstatic void 18212854Sgabeblack@google.comprint_dec(scfx_string &s, scfx_ieee_double id, int w_prefix, sc_fmt fmt) 18312854Sgabeblack@google.com{ 18412854Sgabeblack@google.com if (id.negative() != 0) { 18512854Sgabeblack@google.com id.negative(0); 18612854Sgabeblack@google.com s += '-'; 18712854Sgabeblack@google.com } 18812854Sgabeblack@google.com 18912854Sgabeblack@google.com if (w_prefix == 1) { 19012854Sgabeblack@google.com scfx_print_prefix(s, SC_DEC); 19112854Sgabeblack@google.com } 19212854Sgabeblack@google.com 19312854Sgabeblack@google.com if (id.is_zero()) { 19412854Sgabeblack@google.com s += '0'; 19512854Sgabeblack@google.com return; 19612854Sgabeblack@google.com } 19712854Sgabeblack@google.com 19812854Sgabeblack@google.com // split 'id' into its integer and fractional part 19912854Sgabeblack@google.com double int_part; 20012854Sgabeblack@google.com double frac_part = std::modf(static_cast<double>(id), &int_part); 20112854Sgabeblack@google.com 20212854Sgabeblack@google.com int i; 20312854Sgabeblack@google.com 20412854Sgabeblack@google.com // print integer part 20512854Sgabeblack@google.com int int_digits = 0; 20612854Sgabeblack@google.com int int_zeros = 0; 20712854Sgabeblack@google.com 20812854Sgabeblack@google.com if (int_part != 0.0) { 20912854Sgabeblack@google.com int_digits = (int)std::ceil(std::log10(int_part + 1.0)); 21012854Sgabeblack@google.com 21112854Sgabeblack@google.com int len = s.length(); 21212854Sgabeblack@google.com s.append(int_digits); 21312854Sgabeblack@google.com 21412854Sgabeblack@google.com bool zero_digits = (frac_part == 0.0 && fmt != SC_F); 21512854Sgabeblack@google.com 21612854Sgabeblack@google.com for (i = int_digits + len - 1; i >= len; i--) { 21712854Sgabeblack@google.com unsigned int remainder = (unsigned int)std::fmod(int_part, 10.0); 21812854Sgabeblack@google.com s[i] = static_cast<char>('0' + remainder); 21912854Sgabeblack@google.com 22012854Sgabeblack@google.com if (zero_digits) { 22112854Sgabeblack@google.com if (remainder == 0) 22212854Sgabeblack@google.com int_zeros++; 22312854Sgabeblack@google.com else 22412854Sgabeblack@google.com zero_digits = false; 22512854Sgabeblack@google.com } 22612854Sgabeblack@google.com 22712854Sgabeblack@google.com int_part /= 10.0; 22812854Sgabeblack@google.com } 22912854Sgabeblack@google.com 23012854Sgabeblack@google.com // discard trailing zeros from int_part 23112854Sgabeblack@google.com s.discard(int_zeros); 23212854Sgabeblack@google.com 23312854Sgabeblack@google.com if (s[len] == '0') { 23412854Sgabeblack@google.com // int_digits was overestimated by one 23512854Sgabeblack@google.com s.remove(len); 23612854Sgabeblack@google.com --int_digits; 23712854Sgabeblack@google.com } 23812854Sgabeblack@google.com } 23912854Sgabeblack@google.com 24012854Sgabeblack@google.com // print fractional part 24112854Sgabeblack@google.com int frac_digits = 0; 24212854Sgabeblack@google.com int frac_zeros = 0; 24312854Sgabeblack@google.com 24412854Sgabeblack@google.com if (frac_part != 0.0) { 24512854Sgabeblack@google.com s += '.'; 24612854Sgabeblack@google.com 24712854Sgabeblack@google.com bool zero_digits = (int_digits == 0 && fmt != SC_F); 24812854Sgabeblack@google.com 24912854Sgabeblack@google.com frac_zeros = (int)std::floor(-std::log10(frac_part + DBL_EPSILON)); 25012854Sgabeblack@google.com 25112854Sgabeblack@google.com frac_part *= std::pow(10.0, frac_zeros); 25212854Sgabeblack@google.com 25312854Sgabeblack@google.com frac_digits = frac_zeros; 25412854Sgabeblack@google.com if (!zero_digits) { 25512854Sgabeblack@google.com for (i = 0; i < frac_zeros; i++) 25612854Sgabeblack@google.com s += '0'; 25712854Sgabeblack@google.com frac_zeros = 0; 25812854Sgabeblack@google.com } 25912854Sgabeblack@google.com 26012854Sgabeblack@google.com while (frac_part != 0.0) { 26112854Sgabeblack@google.com frac_part *= 10.0; 26212854Sgabeblack@google.com int n = static_cast<int>(frac_part); 26312854Sgabeblack@google.com 26412854Sgabeblack@google.com if (zero_digits) { 26512854Sgabeblack@google.com if (n == 0) 26612854Sgabeblack@google.com frac_zeros++; 26712854Sgabeblack@google.com else 26812854Sgabeblack@google.com zero_digits = false; 26912854Sgabeblack@google.com } 27012854Sgabeblack@google.com 27112854Sgabeblack@google.com if (!zero_digits) 27212854Sgabeblack@google.com s += static_cast<char>('0' + n); 27312854Sgabeblack@google.com 27412854Sgabeblack@google.com frac_part -= n; 27512854Sgabeblack@google.com frac_digits++; 27612854Sgabeblack@google.com } 27712854Sgabeblack@google.com } 27812854Sgabeblack@google.com 27912854Sgabeblack@google.com // print exponent 28012854Sgabeblack@google.com if (fmt != SC_F) { 28112854Sgabeblack@google.com if (frac_digits == 0) 28212854Sgabeblack@google.com scfx_print_exp(s, int_zeros); 28312854Sgabeblack@google.com else if (int_digits == 0) 28412854Sgabeblack@google.com scfx_print_exp(s, -frac_zeros); 28512854Sgabeblack@google.com } 28612854Sgabeblack@google.com} 28712854Sgabeblack@google.com 28812854Sgabeblack@google.comstatic void 28912854Sgabeblack@google.comprint_other(scfx_string &s, const scfx_ieee_double &id, sc_numrep numrep, 29012854Sgabeblack@google.com int w_prefix, sc_fmt fmt, const scfx_params *params) 29112854Sgabeblack@google.com{ 29212854Sgabeblack@google.com scfx_ieee_double id2 = id; 29312854Sgabeblack@google.com 29412854Sgabeblack@google.com sc_numrep numrep2 = numrep; 29512854Sgabeblack@google.com 29612854Sgabeblack@google.com bool numrep_is_sm = (numrep == SC_BIN_SM || 29712854Sgabeblack@google.com numrep == SC_OCT_SM || 29812854Sgabeblack@google.com numrep == SC_HEX_SM); 29912854Sgabeblack@google.com 30012854Sgabeblack@google.com if (numrep_is_sm) { 30112854Sgabeblack@google.com if (id2.negative() != 0) { 30212854Sgabeblack@google.com s += '-'; 30312854Sgabeblack@google.com id2.negative(0); 30412854Sgabeblack@google.com } 30512854Sgabeblack@google.com switch (numrep) { 30612854Sgabeblack@google.com case SC_BIN_SM: 30712854Sgabeblack@google.com numrep2 = SC_BIN_US; 30812854Sgabeblack@google.com break; 30912854Sgabeblack@google.com case SC_OCT_SM: 31012854Sgabeblack@google.com numrep2 = SC_OCT_US; 31112854Sgabeblack@google.com break; 31212854Sgabeblack@google.com case SC_HEX_SM: 31312854Sgabeblack@google.com numrep2 = SC_HEX_US; 31412854Sgabeblack@google.com break; 31512854Sgabeblack@google.com default: 31612854Sgabeblack@google.com ; 31712854Sgabeblack@google.com } 31812854Sgabeblack@google.com } 31912854Sgabeblack@google.com 32012854Sgabeblack@google.com if (w_prefix != 0) { 32112854Sgabeblack@google.com scfx_print_prefix(s, numrep); 32212854Sgabeblack@google.com } 32312854Sgabeblack@google.com 32412854Sgabeblack@google.com numrep = numrep2; 32512854Sgabeblack@google.com 32612854Sgabeblack@google.com sc_fxval_fast a(id2); 32712854Sgabeblack@google.com 32812854Sgabeblack@google.com int msb, lsb; 32912854Sgabeblack@google.com 33012854Sgabeblack@google.com if (params != 0) { 33112854Sgabeblack@google.com msb = params->iwl() - 1; 33212854Sgabeblack@google.com lsb = params->iwl() - params->wl(); 33312854Sgabeblack@google.com 33412854Sgabeblack@google.com if (params->enc() == SC_TC_ && 33512854Sgabeblack@google.com (numrep == SC_BIN_US || 33612854Sgabeblack@google.com numrep == SC_OCT_US || 33712854Sgabeblack@google.com numrep == SC_HEX_US) && 33812854Sgabeblack@google.com !numrep_is_sm && 33912854Sgabeblack@google.com params->wl() > 1) { 34012854Sgabeblack@google.com --msb; 34112854Sgabeblack@google.com } else if (params->enc() == SC_US_ && 34212854Sgabeblack@google.com (numrep == SC_BIN || 34312854Sgabeblack@google.com numrep == SC_OCT || 34412854Sgabeblack@google.com numrep == SC_HEX || 34512854Sgabeblack@google.com numrep == SC_CSD)) { 34612854Sgabeblack@google.com ++msb; 34712854Sgabeblack@google.com } 34812854Sgabeblack@google.com } else { 34912854Sgabeblack@google.com if (a.is_zero()) { 35012854Sgabeblack@google.com msb = 0; 35112854Sgabeblack@google.com lsb = 0; 35212854Sgabeblack@google.com } else { 35312854Sgabeblack@google.com msb = id2.exponent() + 1; 35412854Sgabeblack@google.com while (a.get_bit(msb) == a.get_bit(msb - 1)) 35512854Sgabeblack@google.com --msb; 35612854Sgabeblack@google.com 35712854Sgabeblack@google.com if (numrep == SC_BIN_US || 35812854Sgabeblack@google.com numrep == SC_OCT_US || 35912854Sgabeblack@google.com numrep == SC_HEX_US) { 36012854Sgabeblack@google.com --msb; 36112854Sgabeblack@google.com } 36212854Sgabeblack@google.com 36312854Sgabeblack@google.com lsb = id2.exponent() - 52; 36412854Sgabeblack@google.com while (!a.get_bit(lsb)) 36512854Sgabeblack@google.com ++lsb; 36612854Sgabeblack@google.com } 36712854Sgabeblack@google.com } 36812854Sgabeblack@google.com 36912854Sgabeblack@google.com int step; 37012854Sgabeblack@google.com 37112854Sgabeblack@google.com switch (numrep) { 37212854Sgabeblack@google.com case SC_BIN: 37312854Sgabeblack@google.com case SC_BIN_US: 37412854Sgabeblack@google.com case SC_CSD: 37512854Sgabeblack@google.com step = 1; 37612854Sgabeblack@google.com break; 37712854Sgabeblack@google.com case SC_OCT: 37812854Sgabeblack@google.com case SC_OCT_US: 37912854Sgabeblack@google.com step = 3; 38012854Sgabeblack@google.com break; 38112854Sgabeblack@google.com case SC_HEX: 38212854Sgabeblack@google.com case SC_HEX_US: 38312854Sgabeblack@google.com step = 4; 38412854Sgabeblack@google.com break; 38512854Sgabeblack@google.com default: 38612854Sgabeblack@google.com SC_REPORT_FATAL("assertion failed", "unexpected sc_numrep"); 38712854Sgabeblack@google.com sc_core::sc_abort(); 38812854Sgabeblack@google.com } 38912854Sgabeblack@google.com 39012854Sgabeblack@google.com msb = (int)std::ceil(double(msb + 1) / step) * step - 1; 39112854Sgabeblack@google.com 39212854Sgabeblack@google.com lsb = (int)std::floor(double(lsb) / step) * step; 39312854Sgabeblack@google.com 39412854Sgabeblack@google.com if (msb < 0) { 39512854Sgabeblack@google.com s += '.'; 39612854Sgabeblack@google.com if (fmt == SC_F) { 39712854Sgabeblack@google.com int sign = (id2.negative() != 0) ? (1 << step) - 1 : 0; 39812854Sgabeblack@google.com for (int i = (msb + 1) / step; i < 0; i++) { 39912854Sgabeblack@google.com if (sign < 10) 40012854Sgabeblack@google.com s += static_cast<char>(sign + '0'); 40112854Sgabeblack@google.com else 40212854Sgabeblack@google.com s += static_cast<char>(sign + 'a' - 10); 40312854Sgabeblack@google.com } 40412854Sgabeblack@google.com } 40512854Sgabeblack@google.com } 40612854Sgabeblack@google.com 40712854Sgabeblack@google.com int i = msb; 40812854Sgabeblack@google.com while (i >= lsb) { 40912854Sgabeblack@google.com int value = 0; 41012854Sgabeblack@google.com for (int j = step - 1; j >= 0; --j) { 41112854Sgabeblack@google.com value += static_cast<int>(a.get_bit(i)) << j; 41212854Sgabeblack@google.com --i; 41312854Sgabeblack@google.com } 41412854Sgabeblack@google.com if (value < 10) 41512854Sgabeblack@google.com s += static_cast<char>(value + '0'); 41612854Sgabeblack@google.com else 41712854Sgabeblack@google.com s += static_cast<char>(value + 'a' - 10); 41812854Sgabeblack@google.com if (i == -1) 41912854Sgabeblack@google.com s += '.'; 42012854Sgabeblack@google.com } 42112854Sgabeblack@google.com 42212854Sgabeblack@google.com if (lsb > 0 && fmt == SC_F) { 42312854Sgabeblack@google.com for (int i = lsb / step; i > 0; i--) 42412854Sgabeblack@google.com s += '0'; 42512854Sgabeblack@google.com } 42612854Sgabeblack@google.com 42712854Sgabeblack@google.com if (s[s.length() - 1] == '.') 42812854Sgabeblack@google.com s.discard(1); 42912854Sgabeblack@google.com 43012854Sgabeblack@google.com if (fmt != SC_F) { 43112854Sgabeblack@google.com if (msb < 0) 43212854Sgabeblack@google.com scfx_print_exp(s, (msb + 1) / step); 43312854Sgabeblack@google.com else if (lsb > 0) 43412854Sgabeblack@google.com scfx_print_exp(s, lsb / step); 43512854Sgabeblack@google.com } 43612854Sgabeblack@google.com 43712854Sgabeblack@google.com if (numrep == SC_CSD) 43812854Sgabeblack@google.com scfx_tc2csd(s, w_prefix); 43912854Sgabeblack@google.com} 44012854Sgabeblack@google.com 44112854Sgabeblack@google.comconst char * 44212854Sgabeblack@google.comto_string(const scfx_ieee_double &id, sc_numrep numrep, int w_prefix, 44312854Sgabeblack@google.com sc_fmt fmt, const scfx_params *params=0) 44412854Sgabeblack@google.com{ 44512854Sgabeblack@google.com static scfx_string s; 44612854Sgabeblack@google.com 44712854Sgabeblack@google.com s.clear(); 44812854Sgabeblack@google.com 44912854Sgabeblack@google.com if (id.is_nan()) { 45012854Sgabeblack@google.com scfx_print_nan(s); 45112854Sgabeblack@google.com } else if (id.is_inf()) { 45212854Sgabeblack@google.com scfx_print_inf(s, static_cast<bool>(id.negative())); 45312854Sgabeblack@google.com } else if (id.negative() && !id.is_zero() && 45412854Sgabeblack@google.com (numrep == SC_BIN_US || 45512854Sgabeblack@google.com numrep == SC_OCT_US || 45612854Sgabeblack@google.com numrep == SC_HEX_US)) { 45712854Sgabeblack@google.com s += "negative"; 45812854Sgabeblack@google.com } else if (numrep == SC_DEC) { 45912854Sgabeblack@google.com sc_dt::print_dec(s, id, w_prefix, fmt); 46012854Sgabeblack@google.com } else { 46112854Sgabeblack@google.com sc_dt::print_other(s, id, numrep, w_prefix, fmt, params); 46212854Sgabeblack@google.com } 46312854Sgabeblack@google.com 46412854Sgabeblack@google.com return s; 46512854Sgabeblack@google.com} 46612854Sgabeblack@google.com 46712854Sgabeblack@google.com 46812854Sgabeblack@google.com// explicit conversion to character string 46912854Sgabeblack@google.comconst std::string 47012854Sgabeblack@google.comsc_fxval_fast::to_string() const 47112854Sgabeblack@google.com{ 47212854Sgabeblack@google.com return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_E)); 47312854Sgabeblack@google.com} 47412854Sgabeblack@google.com 47512854Sgabeblack@google.comconst std::string 47612854Sgabeblack@google.comsc_fxval_fast::to_string(sc_numrep numrep) const 47712854Sgabeblack@google.com{ 47812854Sgabeblack@google.com return std::string(sc_dt::to_string(m_val, numrep, -1, SC_E)); 47912854Sgabeblack@google.com} 48012854Sgabeblack@google.com 48112854Sgabeblack@google.comconst std::string 48212854Sgabeblack@google.comsc_fxval_fast::to_string(sc_numrep numrep, bool w_prefix) const 48312854Sgabeblack@google.com{ 48412854Sgabeblack@google.com return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0), 48512854Sgabeblack@google.com SC_E)); 48612854Sgabeblack@google.com} 48712854Sgabeblack@google.com 48812854Sgabeblack@google.comconst std::string 48912854Sgabeblack@google.comsc_fxval_fast::to_string(sc_fmt fmt) const 49012854Sgabeblack@google.com{ 49112854Sgabeblack@google.com return std::string(sc_dt::to_string(m_val, SC_DEC, -1, fmt)); 49212854Sgabeblack@google.com} 49312854Sgabeblack@google.com 49412854Sgabeblack@google.comconst std::string 49512854Sgabeblack@google.comsc_fxval_fast::to_string(sc_numrep numrep, sc_fmt fmt) const 49612854Sgabeblack@google.com{ 49712854Sgabeblack@google.com return std::string(sc_dt::to_string(m_val, numrep, -1, fmt)); 49812854Sgabeblack@google.com} 49912854Sgabeblack@google.com 50012854Sgabeblack@google.comconst std::string 50112854Sgabeblack@google.comsc_fxval_fast::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const 50212854Sgabeblack@google.com{ 50312854Sgabeblack@google.com return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0), 50412854Sgabeblack@google.com fmt)); 50512854Sgabeblack@google.com} 50612854Sgabeblack@google.com 50712854Sgabeblack@google.comconst std::string 50812854Sgabeblack@google.comsc_fxval_fast::to_dec() const 50912854Sgabeblack@google.com{ 51012854Sgabeblack@google.com return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_E)); 51112854Sgabeblack@google.com} 51212854Sgabeblack@google.com 51312854Sgabeblack@google.comconst std::string 51412854Sgabeblack@google.comsc_fxval_fast::to_bin() const 51512854Sgabeblack@google.com{ 51612854Sgabeblack@google.com return std::string(sc_dt::to_string(m_val, SC_BIN, -1, SC_E)); 51712854Sgabeblack@google.com} 51812854Sgabeblack@google.com 51912854Sgabeblack@google.comconst std::string 52012854Sgabeblack@google.comsc_fxval_fast::to_oct() const 52112854Sgabeblack@google.com{ 52212854Sgabeblack@google.com return std::string(sc_dt::to_string(m_val, SC_OCT, -1, SC_E)); 52312854Sgabeblack@google.com} 52412854Sgabeblack@google.com 52512854Sgabeblack@google.comconst std::string 52612854Sgabeblack@google.comsc_fxval_fast::to_hex() const 52712854Sgabeblack@google.com{ 52812854Sgabeblack@google.com return std::string(sc_dt::to_string(m_val, SC_HEX, -1, SC_E)); 52912854Sgabeblack@google.com} 53012854Sgabeblack@google.com 53112854Sgabeblack@google.com 53212854Sgabeblack@google.com// print or dump content 53312854Sgabeblack@google.com 53412854Sgabeblack@google.comvoid 53512854Sgabeblack@google.comsc_fxval_fast::print(::std::ostream &os) const 53612854Sgabeblack@google.com{ 53712854Sgabeblack@google.com os << sc_dt::to_string(m_val, SC_DEC, -1, SC_E); 53812854Sgabeblack@google.com} 53912854Sgabeblack@google.com 54012854Sgabeblack@google.comvoid 54112854Sgabeblack@google.comsc_fxval_fast::scan(::std::istream &is) 54212854Sgabeblack@google.com{ 54312854Sgabeblack@google.com std::string s; 54412854Sgabeblack@google.com is >> s; 54512854Sgabeblack@google.com *this = s.c_str(); 54612854Sgabeblack@google.com} 54712854Sgabeblack@google.com 54812854Sgabeblack@google.comvoid 54912854Sgabeblack@google.comsc_fxval_fast::dump(::std::ostream &os) const 55012854Sgabeblack@google.com{ 55112854Sgabeblack@google.com os << "sc_fxval_fast" << ::std::endl; 55212854Sgabeblack@google.com os << "(" << ::std::endl; 55312854Sgabeblack@google.com os << "val = " << m_val << ::std::endl; 55412854Sgabeblack@google.com // TO BE COMPLETED 55512854Sgabeblack@google.com // os << "r_flag = " << m_r_flag << ::std::endl; 55612854Sgabeblack@google.com // os << "observer = "; 55712854Sgabeblack@google.com // if (m_observer != 0) 55812854Sgabeblack@google.com // m_observer->dump(os); 55912854Sgabeblack@google.com // else 56012854Sgabeblack@google.com // os << "0" << ::std::endl; 56112854Sgabeblack@google.com os << ")" << ::std::endl; 56212854Sgabeblack@google.com} 56312854Sgabeblack@google.com 56412854Sgabeblack@google.com 56512854Sgabeblack@google.com// internal use only; 56612854Sgabeblack@google.combool 56712854Sgabeblack@google.comsc_fxval_fast::get_bit(int i) const 56812854Sgabeblack@google.com{ 56912854Sgabeblack@google.com scfx_ieee_double id(m_val); 57012854Sgabeblack@google.com if (id.is_zero() || id.is_nan() || id.is_inf()) 57112854Sgabeblack@google.com return false; 57212854Sgabeblack@google.com 57312854Sgabeblack@google.com // convert to two's complement 57412854Sgabeblack@google.com unsigned int m0 = id.mantissa0(); 57512854Sgabeblack@google.com unsigned int m1 = id.mantissa1(); 57612854Sgabeblack@google.com 57712854Sgabeblack@google.com if (id.is_normal()) 57812854Sgabeblack@google.com m0 += 1U << 20; 57912854Sgabeblack@google.com 58012854Sgabeblack@google.com if (id.negative() != 0) { 58112854Sgabeblack@google.com m0 = ~ m0; 58212854Sgabeblack@google.com m1 = ~ m1; 58312854Sgabeblack@google.com unsigned int tmp = m1; 58412854Sgabeblack@google.com m1 += 1U; 58512854Sgabeblack@google.com if (m1 <= tmp) 58612854Sgabeblack@google.com m0 += 1U; 58712854Sgabeblack@google.com } 58812854Sgabeblack@google.com 58912854Sgabeblack@google.com // get the right bit 59012854Sgabeblack@google.com int j = i - id.exponent(); 59112854Sgabeblack@google.com if ((j += 20) >= 32) 59212854Sgabeblack@google.com return ((m0 & 1U << 31) != 0); 59312854Sgabeblack@google.com else if (j >= 0) 59412854Sgabeblack@google.com return ((m0 & 1U << j) != 0); 59512854Sgabeblack@google.com else if ((j += 32) >= 0) 59612854Sgabeblack@google.com return ((m1 & 1U << j) != 0); 59712854Sgabeblack@google.com else 59812854Sgabeblack@google.com return false; 59912854Sgabeblack@google.com} 60012854Sgabeblack@google.com 60112854Sgabeblack@google.com 60212854Sgabeblack@google.com// protected methods and friend functions 60312854Sgabeblack@google.comsc_fxval_fast_observer * 60412854Sgabeblack@google.comsc_fxval_fast::lock_observer() const 60512854Sgabeblack@google.com{ 60612854Sgabeblack@google.com SC_ASSERT_(m_observer != 0, "lock observer failed"); 60712854Sgabeblack@google.com sc_fxval_fast_observer *tmp = m_observer; 60812854Sgabeblack@google.com m_observer = 0; 60912854Sgabeblack@google.com return tmp; 61012854Sgabeblack@google.com} 61112854Sgabeblack@google.com 61212854Sgabeblack@google.comvoid 61312854Sgabeblack@google.comsc_fxval_fast::unlock_observer(sc_fxval_fast_observer *observer_) const 61412854Sgabeblack@google.com{ 61512854Sgabeblack@google.com SC_ASSERT_(observer_ != 0, "unlock observer failed"); 61612854Sgabeblack@google.com m_observer = observer_; 61712854Sgabeblack@google.com} 61812854Sgabeblack@google.com 61912854Sgabeblack@google.com#define SCFX_FAIL_IF_(cnd) \ 62012854Sgabeblack@google.com{ \ 62112854Sgabeblack@google.com if ((cnd)) \ 62212854Sgabeblack@google.com return static_cast<double>(scfx_ieee_double::nan()); \ 62312854Sgabeblack@google.com} 62412854Sgabeblack@google.com 62512854Sgabeblack@google.comdouble 62612854Sgabeblack@google.comsc_fxval_fast::from_string(const char *s) 62712854Sgabeblack@google.com{ 62812854Sgabeblack@google.com SCFX_FAIL_IF_(s == 0 || *s == 0); 62912854Sgabeblack@google.com 63012854Sgabeblack@google.com scfx_string s2; 63112854Sgabeblack@google.com s2 += s; 63212854Sgabeblack@google.com s2 += '\0'; 63312854Sgabeblack@google.com 63412854Sgabeblack@google.com bool sign_char; 63512854Sgabeblack@google.com int sign = scfx_parse_sign(s, sign_char); 63612854Sgabeblack@google.com 63712854Sgabeblack@google.com sc_numrep numrep = scfx_parse_prefix(s); 63812854Sgabeblack@google.com 63912854Sgabeblack@google.com int base = 0; 64012854Sgabeblack@google.com 64112854Sgabeblack@google.com switch (numrep) { 64212854Sgabeblack@google.com case SC_DEC: 64312854Sgabeblack@google.com { 64412854Sgabeblack@google.com base = 10; 64512854Sgabeblack@google.com if (scfx_is_nan(s)) // special case: NaN 64612854Sgabeblack@google.com return static_cast<double>(scfx_ieee_double::nan()); 64712854Sgabeblack@google.com if (scfx_is_inf(s)) // special case: Infinity 64812854Sgabeblack@google.com return static_cast<double>(scfx_ieee_double::inf(sign)); 64912854Sgabeblack@google.com break; 65012854Sgabeblack@google.com } 65112854Sgabeblack@google.com case SC_BIN: 65212854Sgabeblack@google.com case SC_BIN_US: 65312854Sgabeblack@google.com { 65412854Sgabeblack@google.com SCFX_FAIL_IF_(sign_char); 65512854Sgabeblack@google.com base = 2; 65612854Sgabeblack@google.com break; 65712854Sgabeblack@google.com } 65812854Sgabeblack@google.com 65912854Sgabeblack@google.com case SC_BIN_SM: 66012854Sgabeblack@google.com { 66112854Sgabeblack@google.com base = 2; 66212854Sgabeblack@google.com break; 66312854Sgabeblack@google.com } 66412854Sgabeblack@google.com case SC_OCT: 66512854Sgabeblack@google.com case SC_OCT_US: 66612854Sgabeblack@google.com { 66712854Sgabeblack@google.com SCFX_FAIL_IF_(sign_char); 66812854Sgabeblack@google.com base = 8; 66912854Sgabeblack@google.com break; 67012854Sgabeblack@google.com } 67112854Sgabeblack@google.com case SC_OCT_SM: 67212854Sgabeblack@google.com { 67312854Sgabeblack@google.com base = 8; 67412854Sgabeblack@google.com break; 67512854Sgabeblack@google.com } 67612854Sgabeblack@google.com case SC_HEX: 67712854Sgabeblack@google.com case SC_HEX_US: 67812854Sgabeblack@google.com { 67912854Sgabeblack@google.com SCFX_FAIL_IF_(sign_char); 68012854Sgabeblack@google.com base = 16; 68112854Sgabeblack@google.com break; 68212854Sgabeblack@google.com } 68312854Sgabeblack@google.com case SC_HEX_SM: 68412854Sgabeblack@google.com { 68512854Sgabeblack@google.com base = 16; 68612854Sgabeblack@google.com break; 68712854Sgabeblack@google.com } 68812854Sgabeblack@google.com case SC_CSD: 68912854Sgabeblack@google.com { 69012854Sgabeblack@google.com SCFX_FAIL_IF_(sign_char); 69112854Sgabeblack@google.com base = 2; 69212854Sgabeblack@google.com scfx_csd2tc(s2); 69312854Sgabeblack@google.com s = (const char*) s2 + 4; 69412854Sgabeblack@google.com numrep = SC_BIN; 69512854Sgabeblack@google.com break; 69612854Sgabeblack@google.com } 69712854Sgabeblack@google.com default:;// Martin, what is default??? 69812854Sgabeblack@google.com } 69912854Sgabeblack@google.com 70012854Sgabeblack@google.com // 70112854Sgabeblack@google.com // find end of mantissa and count the digits and points 70212854Sgabeblack@google.com // 70312854Sgabeblack@google.com 70412854Sgabeblack@google.com const char *end = s; 70512854Sgabeblack@google.com bool based_point = false; 70612854Sgabeblack@google.com int int_digits = 0; 70712854Sgabeblack@google.com int frac_digits = 0; 70812854Sgabeblack@google.com 70912854Sgabeblack@google.com while (*end) { 71012854Sgabeblack@google.com if (scfx_exp_start(end)) 71112854Sgabeblack@google.com break; 71212854Sgabeblack@google.com 71312854Sgabeblack@google.com if (*end == '.') { 71412854Sgabeblack@google.com SCFX_FAIL_IF_(based_point); 71512854Sgabeblack@google.com based_point = true; 71612854Sgabeblack@google.com } else { 71712854Sgabeblack@google.com SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep)); 71812854Sgabeblack@google.com if (based_point) 71912854Sgabeblack@google.com frac_digits++; 72012854Sgabeblack@google.com else 72112854Sgabeblack@google.com int_digits++; 72212854Sgabeblack@google.com } 72312854Sgabeblack@google.com 72412854Sgabeblack@google.com end++; 72512854Sgabeblack@google.com } 72612854Sgabeblack@google.com 72712854Sgabeblack@google.com SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0); 72812854Sgabeblack@google.com 72912854Sgabeblack@google.com // [ exponent ] 73012854Sgabeblack@google.com int exponent = 0; 73112854Sgabeblack@google.com if (*end) { 73212854Sgabeblack@google.com for (const char *e = end + 2; *e; e++) 73312854Sgabeblack@google.com SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC)); 73412854Sgabeblack@google.com exponent = std::atoi(end + 1); 73512854Sgabeblack@google.com } 73612854Sgabeblack@google.com 73712854Sgabeblack@google.com // 73812854Sgabeblack@google.com // convert the mantissa 73912854Sgabeblack@google.com // 74012854Sgabeblack@google.com double integer = 0.0; 74112854Sgabeblack@google.com if (int_digits != 0) { 74212854Sgabeblack@google.com bool first_digit = true; 74312854Sgabeblack@google.com 74412854Sgabeblack@google.com for (; s < end; s++) { 74512854Sgabeblack@google.com if (*s == '.') 74612854Sgabeblack@google.com break; 74712854Sgabeblack@google.com 74812854Sgabeblack@google.com if (first_digit) { 74912854Sgabeblack@google.com integer = scfx_to_digit(*s, numrep); 75012854Sgabeblack@google.com switch (numrep) { 75112854Sgabeblack@google.com case SC_BIN: 75212854Sgabeblack@google.com case SC_OCT: 75312854Sgabeblack@google.com case SC_HEX: 75412854Sgabeblack@google.com { 75512854Sgabeblack@google.com if (integer >= (base >> 1)) 75612854Sgabeblack@google.com integer -= base; // two's complement 75712854Sgabeblack@google.com break; 75812854Sgabeblack@google.com } 75912854Sgabeblack@google.com default: 76012854Sgabeblack@google.com ; 76112854Sgabeblack@google.com } 76212854Sgabeblack@google.com first_digit = false; 76312854Sgabeblack@google.com } else { 76412854Sgabeblack@google.com integer *= base; 76512854Sgabeblack@google.com integer += scfx_to_digit(*s, numrep); 76612854Sgabeblack@google.com } 76712854Sgabeblack@google.com } 76812854Sgabeblack@google.com } 76912854Sgabeblack@google.com 77012854Sgabeblack@google.com // [ . fraction ] 77112854Sgabeblack@google.com double fraction = 0.0; 77212854Sgabeblack@google.com if (frac_digits != 0) { 77312854Sgabeblack@google.com s++; // skip '.' 77412854Sgabeblack@google.com 77512854Sgabeblack@google.com bool first_digit = (int_digits == 0); 77612854Sgabeblack@google.com double scale = 1.0; 77712854Sgabeblack@google.com for (; s < end; s++) { 77812854Sgabeblack@google.com scale /= base; 77912854Sgabeblack@google.com 78012854Sgabeblack@google.com if (first_digit) { 78112854Sgabeblack@google.com fraction = scfx_to_digit(*s, numrep); 78212854Sgabeblack@google.com switch (numrep) { 78312854Sgabeblack@google.com case SC_BIN: 78412854Sgabeblack@google.com case SC_OCT: 78512854Sgabeblack@google.com case SC_HEX: 78612854Sgabeblack@google.com { 78712854Sgabeblack@google.com if (fraction >= (base >> 1)) 78812854Sgabeblack@google.com fraction -= base; // two's complement 78912854Sgabeblack@google.com break; 79012854Sgabeblack@google.com } 79112854Sgabeblack@google.com default: 79212854Sgabeblack@google.com ; 79312854Sgabeblack@google.com } 79412854Sgabeblack@google.com fraction *= scale; 79512854Sgabeblack@google.com first_digit = false; 79612854Sgabeblack@google.com } else { 79712854Sgabeblack@google.com fraction += scfx_to_digit(*s, numrep) * scale; 79812854Sgabeblack@google.com } 79912854Sgabeblack@google.com } 80012854Sgabeblack@google.com } 80112854Sgabeblack@google.com 80212854Sgabeblack@google.com double exp = 80312854Sgabeblack@google.com (exponent != 0) ? std::pow((double) base, (double) exponent) : 1; 80412854Sgabeblack@google.com 80512854Sgabeblack@google.com return (sign * (integer + fraction) * exp); 80612854Sgabeblack@google.com} 80712854Sgabeblack@google.com 80812854Sgabeblack@google.com#undef SCFX_FAIL_IF_ 80912854Sgabeblack@google.com 81012854Sgabeblack@google.com} // namespace sc_dt 811