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