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