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