sc_fxval.cc revision 13322:7391057615bd
110263Satgutier@umich.edu/*****************************************************************************
212566Snikos.nikoleris@arm.com
310263Satgutier@umich.edu  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
410263Satgutier@umich.edu  more contributor license agreements.  See the NOTICE file distributed
510263Satgutier@umich.edu  with this work for additional information regarding copyright ownership.
610263Satgutier@umich.edu  Accellera licenses this file to you under the Apache License, Version 2.0
710263Satgutier@umich.edu  (the "License"); you may not use this file except in compliance with the
810263Satgutier@umich.edu  License.  You may obtain a copy of the License at
910263Satgutier@umich.edu
1010263Satgutier@umich.edu    http://www.apache.org/licenses/LICENSE-2.0
1110263Satgutier@umich.edu
1210263Satgutier@umich.edu  Unless required by applicable law or agreed to in writing, software
1310263Satgutier@umich.edu  distributed under the License is distributed on an "AS IS" BASIS,
1410263Satgutier@umich.edu  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1510263Satgutier@umich.edu  implied.  See the License for the specific language governing
1610263Satgutier@umich.edu  permissions and limitations under the License.
1710263Satgutier@umich.edu
1810263Satgutier@umich.edu *****************************************************************************/
1910263Satgutier@umich.edu
2010263Satgutier@umich.edu/*****************************************************************************
2110263Satgutier@umich.edu
2210263Satgutier@umich.edu  sc_fxval.cpp -
2310263Satgutier@umich.edu
2410263Satgutier@umich.edu  Original Author: Martin Janssen, Synopsys, Inc.
2510263Satgutier@umich.edu
2610263Satgutier@umich.edu *****************************************************************************/
2710263Satgutier@umich.edu
2810263Satgutier@umich.edu/*****************************************************************************
2910263Satgutier@umich.edu
3010263Satgutier@umich.edu  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
3110263Satgutier@umich.edu  changes you are making here.
3210263Satgutier@umich.edu
3310263Satgutier@umich.edu      Name, Affiliation, Date:
3410263Satgutier@umich.edu  Description of Modification:
3510263Satgutier@umich.edu
3610263Satgutier@umich.edu *****************************************************************************/
3710263Satgutier@umich.edu
3810263Satgutier@umich.edu
3910263Satgutier@umich.edu// $Log: sc_fxval.cpp,v $
4010263Satgutier@umich.edu// Revision 1.1.1.1  2006/12/15 20:20:04  acg
4110263Satgutier@umich.edu// SystemC 2.3
4210263Satgutier@umich.edu//
4310263Satgutier@umich.edu// Revision 1.3  2006/01/13 18:53:58  acg
4410263Satgutier@umich.edu// Andy Goodrich: added $Log command so that CVS comments are reproduced in
4510263Satgutier@umich.edu// the source.
4610263Satgutier@umich.edu//
4710263Satgutier@umich.edu
4812492Sodanrc@yahoo.com.br#include <cctype>
4912492Sodanrc@yahoo.com.br#include <cfloat>
5010263Satgutier@umich.edu#include <cmath>
5110263Satgutier@umich.edu#include <cstdlib>
5210263Satgutier@umich.edu
5312548Sodanrc@yahoo.com.br#include "systemc/ext/dt/fx/sc_fxval.hh"
5412548Sodanrc@yahoo.com.br#include "systemc/ext/utils/messages.hh"
5510263Satgutier@umich.edu
5611486Snikos.nikoleris@arm.comnamespace sc_dt
5711486Snikos.nikoleris@arm.com{
5810263Satgutier@umich.edu
5910263Satgutier@umich.edu// ----------------------------------------------------------------------------
6010263Satgutier@umich.edu//  CLASS : sc_fxval
6110263Satgutier@umich.edu//
6210263Satgutier@umich.edu//  Fixed-point value type; arbitrary precision.
6310263Satgutier@umich.edu// ----------------------------------------------------------------------------
6410263Satgutier@umich.edu
6510263Satgutier@umich.edu// explicit conversion to character string
6610263Satgutier@umich.edu
6710263Satgutier@umich.educonst std::string
6810263Satgutier@umich.edusc_fxval::to_string() const
6910263Satgutier@umich.edu{
7010263Satgutier@umich.edu    return std::string(m_rep->to_string(SC_DEC, -1, SC_E));
7110263Satgutier@umich.edu}
7210263Satgutier@umich.edu
7310263Satgutier@umich.educonst std::string
7410263Satgutier@umich.edusc_fxval::to_string(sc_numrep numrep) const
7510263Satgutier@umich.edu{
7610263Satgutier@umich.edu    return std::string(m_rep->to_string(numrep, -1, SC_E));
7710263Satgutier@umich.edu}
7810263Satgutier@umich.edu
7910263Satgutier@umich.educonst std::string
8010263Satgutier@umich.edusc_fxval::to_string(sc_numrep numrep, bool w_prefix) const
8110263Satgutier@umich.edu{
8210263Satgutier@umich.edu    return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0), SC_E));
8310263Satgutier@umich.edu}
8410263Satgutier@umich.edu
8510263Satgutier@umich.educonst std::string
8610263Satgutier@umich.edusc_fxval::to_string(sc_fmt fmt) const
8710263Satgutier@umich.edu{
8810941Sdavid.guillen@arm.com    return std::string(m_rep->to_string(SC_DEC, -1, fmt));
8910941Sdavid.guillen@arm.com}
9012548Sodanrc@yahoo.com.br
9112548Sodanrc@yahoo.com.brconst std::string
9212548Sodanrc@yahoo.com.brsc_fxval::to_string(sc_numrep numrep, sc_fmt fmt) const
9312548Sodanrc@yahoo.com.br{
9412548Sodanrc@yahoo.com.br    return std::string(m_rep->to_string(numrep, -1, fmt));
9512548Sodanrc@yahoo.com.br}
9610263Satgutier@umich.edu
9710263Satgutier@umich.educonst std::string
9812548Sodanrc@yahoo.com.brsc_fxval::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
9910263Satgutier@umich.edu{
10010263Satgutier@umich.edu    return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0), fmt));
10110263Satgutier@umich.edu}
10210263Satgutier@umich.edu
10312548Sodanrc@yahoo.com.br
10410263Satgutier@umich.educonst std::string
10510263Satgutier@umich.edusc_fxval::to_dec() const
10610263Satgutier@umich.edu{
10710263Satgutier@umich.edu    return std::string(m_rep->to_string(SC_DEC, -1, SC_E));
10810263Satgutier@umich.edu}
10910263Satgutier@umich.edu
11010263Satgutier@umich.educonst std::string
11110263Satgutier@umich.edusc_fxval::to_bin() const
11210263Satgutier@umich.edu{
11310263Satgutier@umich.edu    return std::string(m_rep->to_string(SC_BIN, -1, SC_E));
11410263Satgutier@umich.edu}
11510263Satgutier@umich.edu
11610263Satgutier@umich.educonst std::string
11710263Satgutier@umich.edusc_fxval::to_oct() const
11810263Satgutier@umich.edu{
11910263Satgutier@umich.edu    return std::string(m_rep->to_string(SC_OCT, -1, SC_E));
12010263Satgutier@umich.edu}
12110263Satgutier@umich.edu
12210263Satgutier@umich.educonst std::string
12310263Satgutier@umich.edusc_fxval::to_hex() const
12410263Satgutier@umich.edu{
12512548Sodanrc@yahoo.com.br    return std::string(m_rep->to_string(SC_HEX, -1, SC_E));
12610263Satgutier@umich.edu}
12710263Satgutier@umich.edu
12810941Sdavid.guillen@arm.com
12910941Sdavid.guillen@arm.com// print or dump content
13010941Sdavid.guillen@arm.com
13110941Sdavid.guillen@arm.comvoid sc_fxval::print(::std::ostream &os) const { m_rep->print(os); }
13210941Sdavid.guillen@arm.com
13311169Sandreas.hansson@arm.comvoid
13410941Sdavid.guillen@arm.comsc_fxval::scan(::std::istream &is)
13510941Sdavid.guillen@arm.com{
13610263Satgutier@umich.edu    std::string s;
13711484Snikos.nikoleris@arm.com    is >> s;
13810263Satgutier@umich.edu    *this = s.c_str();
13910263Satgutier@umich.edu}
14010263Satgutier@umich.edu
14110263Satgutier@umich.eduvoid
14210263Satgutier@umich.edusc_fxval::dump(::std::ostream &os) const
14310263Satgutier@umich.edu{
14410263Satgutier@umich.edu    os << "sc_fxval" << ::std::endl;
14511870Snikos.nikoleris@arm.com    os << "(" << ::std::endl;
14610263Satgutier@umich.edu    os << "rep = ";
14712555Sodanrc@yahoo.com.br    m_rep->dump(os);
14810263Satgutier@umich.edu    // TO BE COMPLETED
14910263Satgutier@umich.edu    // os << "r_flag   = " << m_r_flag << ::std::endl;
15010263Satgutier@umich.edu    // os << "observer = ";
15110263Satgutier@umich.edu    // if (m_observer != 0)
15210941Sdavid.guillen@arm.com    //     m_observer->dump(os);
15310263Satgutier@umich.edu    // else
15411484Snikos.nikoleris@arm.com    //     os << "0" << ::std::endl;
15510263Satgutier@umich.edu    os << ")" << ::std::endl;
15610263Satgutier@umich.edu}
15710263Satgutier@umich.edu
15810941Sdavid.guillen@arm.com// protected methods and friend functions
15910263Satgutier@umich.edusc_fxval_observer *
16010263Satgutier@umich.edusc_fxval::lock_observer() const
16111484Snikos.nikoleris@arm.com{
16211722Ssophiane.senni@gmail.com    SC_ASSERT_(m_observer != 0, "lock observer failed");
16311722Ssophiane.senni@gmail.com    sc_fxval_observer *tmp = m_observer;
16411722Ssophiane.senni@gmail.com    m_observer = 0;
16511722Ssophiane.senni@gmail.com    return tmp;
16611722Ssophiane.senni@gmail.com}
16711722Ssophiane.senni@gmail.com
16811722Ssophiane.senni@gmail.comvoid
16911722Ssophiane.senni@gmail.comsc_fxval::unlock_observer(sc_fxval_observer *observer_) const
17011722Ssophiane.senni@gmail.com{
17110263Satgutier@umich.edu    SC_ASSERT_(observer_ != 0, "unlock observer failed");
17210263Satgutier@umich.edu    m_observer = observer_;
17311722Ssophiane.senni@gmail.com}
17411722Ssophiane.senni@gmail.com
17511722Ssophiane.senni@gmail.com
17610263Satgutier@umich.edu// ----------------------------------------------------------------------------
17710263Satgutier@umich.edu//  CLASS : sc_fxval_fast
17810263Satgutier@umich.edu//
17910263Satgutier@umich.edu//  Fixed-point value types; limited precision.
18010263Satgutier@umich.edu// ----------------------------------------------------------------------------
18110263Satgutier@umich.edu
18210263Satgutier@umich.edustatic void
18310263Satgutier@umich.eduprint_dec(scfx_string &s, scfx_ieee_double id, int w_prefix, sc_fmt fmt)
18410263Satgutier@umich.edu{
18510263Satgutier@umich.edu    if (id.negative() != 0) {
18610263Satgutier@umich.edu        id.negative(0);
18710263Satgutier@umich.edu        s += '-';
18810263Satgutier@umich.edu    }
18911169Sandreas.hansson@arm.com
19010263Satgutier@umich.edu    if (w_prefix == 1) {
19110263Satgutier@umich.edu        scfx_print_prefix(s, SC_DEC);
19210263Satgutier@umich.edu    }
19310263Satgutier@umich.edu
19410263Satgutier@umich.edu    if (id.is_zero()) {
19510263Satgutier@umich.edu        s += '0';
19610263Satgutier@umich.edu        return;
19710263Satgutier@umich.edu    }
19811169Sandreas.hansson@arm.com
19910263Satgutier@umich.edu    // split 'id' into its integer and fractional part
20011484Snikos.nikoleris@arm.com    double int_part;
20110263Satgutier@umich.edu    double frac_part = std::modf(static_cast<double>(id), &int_part);
20210263Satgutier@umich.edu
20310263Satgutier@umich.edu    int i;
20410941Sdavid.guillen@arm.com
20510263Satgutier@umich.edu    // print integer part
20610941Sdavid.guillen@arm.com    int int_digits = 0;
20710263Satgutier@umich.edu    int int_zeros  = 0;
20810263Satgutier@umich.edu
20910263Satgutier@umich.edu    if (int_part != 0.0) {
21010263Satgutier@umich.edu        int_digits = (int)std::ceil(std::log10(int_part + 1.0));
21110263Satgutier@umich.edu
21210263Satgutier@umich.edu        int len = s.length();
21310263Satgutier@umich.edu        s.append(int_digits);
21410263Satgutier@umich.edu
21510263Satgutier@umich.edu        bool zero_digits = (frac_part == 0.0 && fmt != SC_F);
21610263Satgutier@umich.edu
21710263Satgutier@umich.edu        for (i = int_digits + len - 1; i >= len; i--) {
21811169Sandreas.hansson@arm.com            unsigned int remainder = (unsigned int)std::fmod(int_part, 10.0);
21910263Satgutier@umich.edu            s[i] = static_cast<char>('0' + remainder);
22010263Satgutier@umich.edu
22110263Satgutier@umich.edu            if (zero_digits) {
22210263Satgutier@umich.edu                if (remainder == 0)
22310274Smitch.hayenga@arm.com                    int_zeros++;
22410263Satgutier@umich.edu                else
22510263Satgutier@umich.edu                    zero_digits = false;
22610263Satgutier@umich.edu            }
22710263Satgutier@umich.edu
22810263Satgutier@umich.edu            int_part /= 10.0;
22910263Satgutier@umich.edu        }
23010263Satgutier@umich.edu
23110263Satgutier@umich.edu        // discard trailing zeros from int_part
23210263Satgutier@umich.edu        s.discard(int_zeros);
23310263Satgutier@umich.edu
23410263Satgutier@umich.edu        if (s[len] == '0') {
23510263Satgutier@umich.edu            // int_digits was overestimated by one
23610263Satgutier@umich.edu            s.remove(len);
23710263Satgutier@umich.edu            --int_digits;
23810263Satgutier@umich.edu        }
23910263Satgutier@umich.edu    }
24012554Snikos.nikoleris@arm.com
24110263Satgutier@umich.edu    // print fractional part
24210263Satgutier@umich.edu    int frac_digits = 0;
24310263Satgutier@umich.edu    int frac_zeros  = 0;
24412557Sodanrc@yahoo.com.br
24512557Sodanrc@yahoo.com.br    if (frac_part != 0.0) {
24612557Sodanrc@yahoo.com.br        s += '.';
24710263Satgutier@umich.edu
24810274Smitch.hayenga@arm.com        bool zero_digits = (int_digits == 0 && fmt != SC_F);
24910263Satgutier@umich.edu
25010263Satgutier@umich.edu        frac_zeros = (int)std::floor(-std::log10(frac_part + DBL_EPSILON));
25110263Satgutier@umich.edu
25210263Satgutier@umich.edu        frac_part *= std::pow(10.0, frac_zeros);
25310263Satgutier@umich.edu
25410263Satgutier@umich.edu        frac_digits = frac_zeros;
25510263Satgutier@umich.edu        if (!zero_digits) {
25610263Satgutier@umich.edu            for (i = 0; i < frac_zeros; i++)
25710263Satgutier@umich.edu                s += '0';
25810263Satgutier@umich.edu            frac_zeros = 0;
25910263Satgutier@umich.edu        }
26010263Satgutier@umich.edu
26110263Satgutier@umich.edu        while (frac_part != 0.0) {
26210263Satgutier@umich.edu            frac_part *= 10.0;
26310263Satgutier@umich.edu            int n = static_cast<int>(frac_part);
26410263Satgutier@umich.edu
26510941Sdavid.guillen@arm.com            if (zero_digits) {
26610941Sdavid.guillen@arm.com                if (n == 0)
26710941Sdavid.guillen@arm.com                    frac_zeros++;
26811169Sandreas.hansson@arm.com                else
26910941Sdavid.guillen@arm.com                    zero_digits = false;
27010941Sdavid.guillen@arm.com            }
27110941Sdavid.guillen@arm.com
27210941Sdavid.guillen@arm.com            if (!zero_digits)
27310941Sdavid.guillen@arm.com                s += static_cast<char>('0' + n);
27410941Sdavid.guillen@arm.com
27510941Sdavid.guillen@arm.com            frac_part -= n;
27610941Sdavid.guillen@arm.com            frac_digits++;
27710941Sdavid.guillen@arm.com        }
27811169Sandreas.hansson@arm.com    }
27910941Sdavid.guillen@arm.com
28010941Sdavid.guillen@arm.com    // print exponent
28110941Sdavid.guillen@arm.com    if (fmt != SC_F) {
28210941Sdavid.guillen@arm.com        if (frac_digits == 0)
28310941Sdavid.guillen@arm.com            scfx_print_exp(s, int_zeros);
28410263Satgutier@umich.edu        else if (int_digits == 0)
28510263Satgutier@umich.edu            scfx_print_exp(s, -frac_zeros);
28610263Satgutier@umich.edu    }
28710263Satgutier@umich.edu}
28811169Sandreas.hansson@arm.com
28910263Satgutier@umich.edustatic void
29010263Satgutier@umich.eduprint_other(scfx_string &s, const scfx_ieee_double &id, sc_numrep numrep,
29110263Satgutier@umich.edu             int w_prefix, sc_fmt fmt, const scfx_params *params)
29210263Satgutier@umich.edu{
29310263Satgutier@umich.edu    scfx_ieee_double id2 = id;
29410263Satgutier@umich.edu
29510263Satgutier@umich.edu    sc_numrep numrep2 = numrep;
29610263Satgutier@umich.edu
29710263Satgutier@umich.edu    bool numrep_is_sm = (numrep == SC_BIN_SM ||
29811169Sandreas.hansson@arm.com                         numrep == SC_OCT_SM ||
29910263Satgutier@umich.edu                         numrep == SC_HEX_SM);
30010263Satgutier@umich.edu
30110263Satgutier@umich.edu    if (numrep_is_sm) {
30210263Satgutier@umich.edu        if (id2.negative() != 0) {
30310263Satgutier@umich.edu            s += '-';
30412574Sodanrc@yahoo.com.br            id2.negative(0);
30512574Sodanrc@yahoo.com.br        }
30612574Sodanrc@yahoo.com.br        switch (numrep) {
30712574Sodanrc@yahoo.com.br          case SC_BIN_SM:
30810263Satgutier@umich.edu            numrep2 = SC_BIN_US;
30912574Sodanrc@yahoo.com.br            break;
31010263Satgutier@umich.edu          case SC_OCT_SM:
31112574Sodanrc@yahoo.com.br            numrep2 = SC_OCT_US;
31210263Satgutier@umich.edu            break;
31310263Satgutier@umich.edu          case SC_HEX_SM:
31410263Satgutier@umich.edu            numrep2 = SC_HEX_US;
31510263Satgutier@umich.edu            break;
31610263Satgutier@umich.edu          default:
31711169Sandreas.hansson@arm.com            ;
31810263Satgutier@umich.edu        }
31910263Satgutier@umich.edu    }
32010263Satgutier@umich.edu
32110263Satgutier@umich.edu    if (w_prefix != 0) {
32211169Sandreas.hansson@arm.com        scfx_print_prefix(s, numrep);
32310263Satgutier@umich.edu    }
32410263Satgutier@umich.edu
32510263Satgutier@umich.edu    numrep = numrep2;
32610263Satgutier@umich.edu
32711169Sandreas.hansson@arm.com    sc_fxval_fast a(id2);
32810263Satgutier@umich.edu
32910263Satgutier@umich.edu    int msb, lsb;
33010263Satgutier@umich.edu
33110263Satgutier@umich.edu    if (params != 0) {
33210263Satgutier@umich.edu        msb = params->iwl() - 1;
33310263Satgutier@umich.edu        lsb = params->iwl() - params->wl();
33410263Satgutier@umich.edu
33510263Satgutier@umich.edu        if (params->enc() == SC_TC_ &&
33610263Satgutier@umich.edu            (numrep == SC_BIN_US ||
33710263Satgutier@umich.edu              numrep == SC_OCT_US ||
33810263Satgutier@umich.edu              numrep == SC_HEX_US) &&
33910263Satgutier@umich.edu            !numrep_is_sm &&
34010263Satgutier@umich.edu            params->wl() > 1) {
34111168Sandreas.hansson@arm.com            --msb;
34210263Satgutier@umich.edu        } else if (params->enc() == SC_US_ &&
34310263Satgutier@umich.edu            (numrep == SC_BIN ||
34410263Satgutier@umich.edu              numrep == SC_OCT ||
34510263Satgutier@umich.edu              numrep == SC_HEX ||
34610263Satgutier@umich.edu              numrep == SC_CSD)) {
34710263Satgutier@umich.edu            ++msb;
34810263Satgutier@umich.edu        }
34912492Sodanrc@yahoo.com.br    } else {
350        if (a.is_zero()) {
351            msb = 0;
352            lsb = 0;
353        } else {
354            msb = id2.exponent() + 1;
355            while (a.get_bit(msb) == a.get_bit(msb - 1))
356                --msb;
357
358            if (numrep == SC_BIN_US ||
359                numrep == SC_OCT_US ||
360                numrep == SC_HEX_US) {
361                --msb;
362            }
363
364            lsb = id2.exponent() - 52;
365            while (!a.get_bit(lsb))
366                ++lsb;
367        }
368    }
369
370    int step;
371
372    switch (numrep) {
373      case SC_BIN:
374      case SC_BIN_US:
375      case SC_CSD:
376        step = 1;
377       break;
378      case SC_OCT:
379      case SC_OCT_US:
380        step = 3;
381        break;
382      case SC_HEX:
383      case SC_HEX_US:
384        step = 4;
385        break;
386      default:
387        SC_REPORT_FATAL(sc_core::SC_ID_ASSERTION_FAILED_,
388                "unexpected sc_numrep");
389        sc_core::sc_abort();
390    }
391
392    msb = (int)std::ceil(double(msb + 1) / step) * step - 1;
393
394    lsb = (int)std::floor(double(lsb) / step) * step;
395
396    if (msb < 0) {
397        s += '.';
398        if (fmt == SC_F) {
399            int sign = (id2.negative() != 0) ? (1 << step) - 1 : 0;
400            for (int i = (msb + 1) / step; i < 0; i++) {
401                if (sign < 10)
402                    s += static_cast<char>(sign + '0');
403                else
404                    s += static_cast<char>(sign + 'a' - 10);
405            }
406        }
407    }
408
409    int i = msb;
410    while (i >= lsb) {
411        int value = 0;
412        for (int j = step - 1; j >= 0; --j) {
413            value += static_cast<int>(a.get_bit(i)) << j;
414            --i;
415        }
416        if (value < 10)
417            s += static_cast<char>(value + '0');
418        else
419            s += static_cast<char>(value + 'a' - 10);
420        if (i == -1)
421            s += '.';
422    }
423
424    if (lsb > 0 && fmt == SC_F) {
425        for (int i = lsb / step; i > 0; i--)
426            s += '0';
427    }
428
429    if (s[s.length() - 1] == '.')
430        s.discard(1);
431
432    if (fmt != SC_F) {
433        if (msb < 0)
434            scfx_print_exp(s, (msb + 1) / step);
435        else if (lsb > 0)
436            scfx_print_exp(s, lsb / step);
437    }
438
439    if (numrep == SC_CSD)
440        scfx_tc2csd(s, w_prefix);
441}
442
443const char *
444to_string(const scfx_ieee_double &id, sc_numrep numrep, int w_prefix,
445          sc_fmt fmt, const scfx_params *params=0)
446{
447    static scfx_string s;
448
449    s.clear();
450
451    if (id.is_nan()) {
452        scfx_print_nan(s);
453    } else if (id.is_inf()) {
454        scfx_print_inf(s, static_cast<bool>(id.negative()));
455    } else if (id.negative() && !id.is_zero() &&
456             (numrep == SC_BIN_US ||
457               numrep == SC_OCT_US ||
458               numrep == SC_HEX_US)) {
459        s += "negative";
460    } else if (numrep == SC_DEC) {
461        sc_dt::print_dec(s, id, w_prefix, fmt);
462    } else {
463        sc_dt::print_other(s, id, numrep, w_prefix, fmt, params);
464    }
465
466    return s;
467}
468
469
470// explicit conversion to character string
471const std::string
472sc_fxval_fast::to_string() const
473{
474    return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_E));
475}
476
477const std::string
478sc_fxval_fast::to_string(sc_numrep numrep) const
479{
480    return std::string(sc_dt::to_string(m_val, numrep, -1, SC_E));
481}
482
483const std::string
484sc_fxval_fast::to_string(sc_numrep numrep, bool w_prefix) const
485{
486    return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
487                       SC_E));
488}
489
490const std::string
491sc_fxval_fast::to_string(sc_fmt fmt) const
492{
493    return std::string(sc_dt::to_string(m_val, SC_DEC, -1, fmt));
494}
495
496const std::string
497sc_fxval_fast::to_string(sc_numrep numrep, sc_fmt fmt) const
498{
499    return std::string(sc_dt::to_string(m_val, numrep, -1, fmt));
500}
501
502const std::string
503sc_fxval_fast::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
504{
505    return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
506                                        fmt));
507}
508
509const std::string
510sc_fxval_fast::to_dec() const
511{
512    return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_E));
513}
514
515const std::string
516sc_fxval_fast::to_bin() const
517{
518    return std::string(sc_dt::to_string(m_val, SC_BIN, -1, SC_E));
519}
520
521const std::string
522sc_fxval_fast::to_oct() const
523{
524    return std::string(sc_dt::to_string(m_val, SC_OCT, -1, SC_E));
525}
526
527const std::string
528sc_fxval_fast::to_hex() const
529{
530    return std::string(sc_dt::to_string(m_val, SC_HEX, -1, SC_E));
531}
532
533
534// print or dump content
535
536void
537sc_fxval_fast::print(::std::ostream &os) const
538{
539    os << sc_dt::to_string(m_val, SC_DEC, -1, SC_E);
540}
541
542void
543sc_fxval_fast::scan(::std::istream &is)
544{
545    std::string s;
546    is >> s;
547    *this = s.c_str();
548}
549
550void
551sc_fxval_fast::dump(::std::ostream &os) const
552{
553    os << "sc_fxval_fast" << ::std::endl;
554    os << "(" << ::std::endl;
555    os << "val = " << m_val << ::std::endl;
556    // TO BE COMPLETED
557    // os << "r_flag   = " << m_r_flag << ::std::endl;
558    // os << "observer = ";
559    // if (m_observer != 0)
560    //     m_observer->dump(os);
561    // else
562    //     os << "0" << ::std::endl;
563    os << ")" << ::std::endl;
564}
565
566
567// internal use only;
568bool
569sc_fxval_fast::get_bit(int i) const
570{
571    scfx_ieee_double id(m_val);
572    if (id.is_zero() || id.is_nan() || id.is_inf())
573        return false;
574
575    // convert to two's complement
576    unsigned int m0 = id.mantissa0();
577    unsigned int m1 = id.mantissa1();
578
579    if (id.is_normal())
580        m0 += 1U << 20;
581
582    if (id.negative() != 0) {
583        m0 = ~ m0;
584        m1 = ~ m1;
585        unsigned int tmp = m1;
586        m1 += 1U;
587        if (m1 <= tmp)
588            m0 += 1U;
589    }
590
591    // get the right bit
592    int j = i - id.exponent();
593    if ((j += 20) >= 32)
594        return ((m0 & 1U << 31) != 0);
595    else if (j >= 0)
596        return ((m0 & 1U << j) != 0);
597    else if ((j += 32) >= 0)
598        return ((m1 & 1U << j) != 0);
599    else
600        return false;
601}
602
603
604// protected methods and friend functions
605sc_fxval_fast_observer *
606sc_fxval_fast::lock_observer() const
607{
608    SC_ASSERT_(m_observer != 0, "lock observer failed");
609    sc_fxval_fast_observer *tmp = m_observer;
610    m_observer = 0;
611    return tmp;
612}
613
614void
615sc_fxval_fast::unlock_observer(sc_fxval_fast_observer *observer_) const
616{
617    SC_ASSERT_(observer_ != 0, "unlock observer failed");
618    m_observer = observer_;
619}
620
621#define SCFX_FAIL_IF_(cnd)                                                    \
622{                                                                             \
623    if ((cnd))                                                             \
624        return static_cast<double>(scfx_ieee_double::nan());                \
625}
626
627double
628sc_fxval_fast::from_string(const char *s)
629{
630    SCFX_FAIL_IF_(s == 0 || *s == 0);
631
632    scfx_string s2;
633    s2 += s;
634    s2 += '\0';
635
636    bool sign_char;
637    int sign = scfx_parse_sign(s, sign_char);
638
639    sc_numrep numrep = scfx_parse_prefix(s);
640
641    int base = 0;
642
643    switch (numrep) {
644      case SC_DEC:
645        {
646            base = 10;
647            if (scfx_is_nan(s)) // special case: NaN
648                return static_cast<double>(scfx_ieee_double::nan());
649            if (scfx_is_inf(s)) // special case: Infinity
650                return static_cast<double>(scfx_ieee_double::inf(sign));
651            break;
652        }
653      case SC_BIN:
654      case SC_BIN_US:
655        {
656            SCFX_FAIL_IF_(sign_char);
657            base = 2;
658            break;
659        }
660
661      case SC_BIN_SM:
662        {
663            base = 2;
664            break;
665        }
666      case SC_OCT:
667      case SC_OCT_US:
668        {
669            SCFX_FAIL_IF_(sign_char);
670            base = 8;
671            break;
672        }
673      case SC_OCT_SM:
674        {
675            base = 8;
676            break;
677        }
678      case SC_HEX:
679      case SC_HEX_US:
680        {
681            SCFX_FAIL_IF_(sign_char);
682            base = 16;
683            break;
684        }
685      case SC_HEX_SM:
686        {
687            base = 16;
688            break;
689        }
690      case SC_CSD:
691        {
692            SCFX_FAIL_IF_(sign_char);
693            base = 2;
694            scfx_csd2tc(s2);
695            s = (const char*) s2 + 4;
696            numrep = SC_BIN;
697            break;
698        }
699      default:;// Martin, what is default???
700    }
701
702    //
703    // find end of mantissa and count the digits and points
704    //
705
706    const char *end = s;
707    bool based_point = false;
708    int int_digits = 0;
709    int frac_digits = 0;
710
711    while (*end) {
712        if (scfx_exp_start(end))
713            break;
714
715        if (*end == '.') {
716            SCFX_FAIL_IF_(based_point);
717            based_point = true;
718        } else {
719            SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep));
720            if (based_point)
721                frac_digits++;
722            else
723                int_digits++;
724        }
725
726        end++;
727    }
728
729    SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0);
730
731    // [ exponent ]
732    int exponent = 0;
733    if (*end) {
734        for (const char *e = end + 2; *e; e++)
735            SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC));
736        exponent = std::atoi(end + 1);
737    }
738
739    //
740    // convert the mantissa
741    //
742    double integer = 0.0;
743    if (int_digits != 0) {
744        bool first_digit = true;
745
746        for (; s < end; s++) {
747            if (*s == '.')
748                break;
749
750            if (first_digit) {
751                integer = scfx_to_digit(*s, numrep);
752                switch (numrep) {
753                  case SC_BIN:
754                  case SC_OCT:
755                  case SC_HEX:
756                    {
757                        if (integer >= (base >> 1))
758                            integer -= base; // two's complement
759                        break;
760                    }
761                  default:
762                    ;
763                }
764                first_digit = false;
765            } else {
766                integer *= base;
767                integer += scfx_to_digit(*s, numrep);
768            }
769        }
770    }
771
772    // [ . fraction ]
773    double fraction = 0.0;
774    if (frac_digits != 0) {
775        s++;  // skip '.'
776
777        bool first_digit = (int_digits == 0);
778        double scale = 1.0;
779        for (; s < end; s++) {
780            scale /= base;
781
782            if (first_digit) {
783                fraction = scfx_to_digit(*s, numrep);
784                switch (numrep) {
785                  case SC_BIN:
786                  case SC_OCT:
787                  case SC_HEX:
788                    {
789                        if (fraction >= (base >> 1))
790                            fraction -= base; // two's complement
791                        break;
792                    }
793                  default:
794                    ;
795                }
796                fraction *= scale;
797                first_digit = false;
798            } else {
799                fraction += scfx_to_digit(*s, numrep) * scale;
800            }
801        }
802    }
803
804    double exp =
805        (exponent != 0) ? std::pow((double) base, (double) exponent) : 1;
806
807    return (sign * (integer + fraction) * exp);
808}
809
810#undef SCFX_FAIL_IF_
811
812} // namespace sc_dt
813