--- /dev/null
+# Copyright 2018 Google, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+Import('*')
+
+if env['USE_SYSTEMC']:
+ Source('sc_bit.cc')
+ Source('sc_bv_base.cc')
+ Source('sc_logic.cc')
+ Source('sc_lv_base.cc')
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_bit.cpp -- Bit class.
+
+ Original Author: Gene Bushuyev, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_bit.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.6 2006/04/12 20:17:52 acg
+// Andy Goodrich: enabled deprecation message for sc_bit.
+//
+// Revision 1.5 2006/01/25 00:31:15 acg
+// Andy Goodrich: Changed over to use a standard message id of
+// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages.
+//
+// Revision 1.4 2006/01/24 20:50:55 acg
+// Andy Goodrich: added warnings indicating that sc_bit is deprecated and that
+// the C bool data type should be used in its place.
+//
+// Revision 1.3 2006/01/13 18:53:53 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <sstream>
+
+#include "systemc/ext/dt/bit/sc_bit.hh"
+#include "systemc/ext/dt/bit/sc_logic.hh"
+#include "systemc/ext/utils/sc_report_handler.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_bit
+//
+// Bit class.
+// Note: VSIA compatibility indicated.
+// ----------------------------------------------------------------------------
+
+// support methods
+void
+sc_bit::invalid_value(char c)
+{
+ std::stringstream msg;
+ msg << "sc_bit('" << c << "')";
+ SC_REPORT_ERROR("value is not valid", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+void
+sc_bit::invalid_value(int i)
+{
+ std::stringstream msg;
+ msg << "sc_bit(" << i << ")";
+ SC_REPORT_ERROR("value is not valid", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+// constructors
+sc_bit::sc_bit(const sc_logic &a) : m_val(a.to_bool()) // non-VSIA
+{
+ sc_deprecated_sc_bit();
+}
+
+// assignment operators
+sc_bit &
+sc_bit::operator = (const sc_logic &b) // non-VSIA
+{
+ return (*this = sc_bit(b));
+}
+
+// other methods
+void
+sc_bit::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
+
+void
+sc_deprecated_sc_bit()
+{
+ static bool warn_sc_bit_deprecated = true;
+ if (warn_sc_bit_deprecated) {
+ warn_sc_bit_deprecated = false;
+ SC_REPORT_INFO("/IEEE_Std_1666/deprecated",
+ "sc_bit is deprecated, use bool instead");
+ }
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_bv_base.cpp -- Arbitrary size bit vector class.
+
+ Original Author: Gene Bushuyev, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_bv_base.cpp,v $
+// Revision 1.2 2011/08/24 22:05:40 acg
+// Torsten Maehne: initialization changes to remove warnings.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.4 2006/04/11 23:12:26 acg
+// Andy Goodrich: Fixed bug in parsing of extended string constants like
+// 0bus1110011.
+//
+// Revision 1.3 2006/01/13 18:53:53 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <cstring>
+#include <sstream>
+
+#include "systemc/ext/dt/bit/sc_bv_base.hh"
+#include "systemc/ext/dt/fx/sc_fix.hh"
+#include "systemc/ext/dt/fx/sc_ufix.hh"
+#include "systemc/ext/utils/sc_report.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_bv_base
+//
+// Arbitrary size bit vector base class.
+// ----------------------------------------------------------------------------
+
+void
+sc_bv_base::init(int length_, bool init_value)
+{
+ // check the length
+ if (length_ <= 0) {
+ SC_REPORT_ERROR("zero length", 0);
+ sc_core::sc_abort(); // can't recover from here
+ }
+ // allocate memory for the data and control words
+ m_len = length_;
+ m_size = (m_len - 1) / SC_DIGIT_SIZE + 1;
+ m_data = new sc_digit[m_size];
+ // initialize the bits to 'init_value'
+ sc_digit dw = init_value ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO;
+ int sz = m_size;
+ for (int i = 0; i < sz; ++i) {
+ m_data[i] = dw;
+ }
+ clean_tail();
+}
+
+void
+sc_bv_base::assign_from_string(const std::string &s)
+{
+ // s must have been converted to bin
+ int len = m_len;
+ int s_len = s.length() - 1;
+ int min_len = sc_min(len, s_len);
+ int i = 0;
+ for (; i < min_len; ++i) {
+ char c = s[s_len - i - 1];
+ if (c != '0' && c != '1') {
+ SC_REPORT_ERROR("cannot perform conversion",
+ "string can contain only '0' and '1' characters");
+ // may continue, if suppressed
+ c = '0';
+ }
+ set_bit(i, sc_logic_value_t(c - '0'));
+ }
+ // if formatted, fill the rest with sign(s), otherwise fill with zeros
+ sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t(s[0] - '0')
+ : sc_logic_value_t(0));
+ for (; i < len; ++i) {
+ set_bit(i, fill);
+ }
+}
+
+// constructors
+sc_bv_base::sc_bv_base(const char *a) : m_len(0), m_size(0), m_data(0)
+{
+ std::string s = convert_to_bin(a);
+ init(s.length() - 1);
+ assign_from_string(s);
+}
+
+sc_bv_base::sc_bv_base(const char *a, int length_) :
+ m_len(0), m_size(0), m_data(0)
+{
+ init(length_);
+ assign_from_string(convert_to_bin(a));
+}
+
+sc_bv_base::sc_bv_base(const sc_bv_base &a) :
+ sc_proxy<sc_bv_base>(), m_len(a.m_len), m_size(a.m_size),
+ m_data(new sc_digit[m_size])
+{
+ // copy the bits
+ int sz = m_size;
+ for (int i = 0; i < sz; ++i) {
+ m_data[i] = a.m_data[i];
+ }
+}
+
+// assignment operators
+sc_bv_base &
+sc_bv_base::operator = (const char *a)
+{
+ assign_from_string(convert_to_bin(a));
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// convert formatted string to binary string
+
+const std::string
+convert_to_bin(const char *s)
+{
+ // Beware: logic character strings cannot start with '0x' or '0X',
+ // because this is seen as a hexadecimal encoding prefix!
+
+ if (s == 0) {
+ SC_REPORT_ERROR("cannot perform conversion",
+ "character string is zero");
+ return std::string();
+ }
+ if (*s == 0) {
+ SC_REPORT_ERROR("cannot perform conversion",
+ "character string is empty");
+ return std::string();
+ }
+
+ int n = strlen(s);
+ int i = 0;
+ if (s[0] == '-' || s[0] == '+') {
+ ++i;
+ }
+ if (n > (i + 2) && s[i] == '0') {
+ if (s[i + 1] == 'b' || s[i + 1] == 'B') {
+ if (s[i + 2] == '0' || s[i + 2] == '1') {
+ std::string str(&s[2]);
+ str += "F";
+ return str;
+ }
+ }
+ if (s[i + 1] == 'b' || s[i + 1] == 'B' ||
+ s[i + 1] == 'c' || s[i + 1] == 'C' ||
+ s[i + 1] == 'd' || s[i + 1] == 'D' ||
+ s[i + 1] == 'o' || s[i + 1] == 'O' ||
+ s[i + 1] == 'x' || s[i + 1] == 'X') {
+ try {
+ // worst case length = n * 4
+ sc_fix a(s, n * 4, n * 4, SC_TRN, SC_WRAP, 0, SC_ON);
+ std::string str = a.to_bin();
+ str += "F"; // mark the string as formatted
+ // get rid of prefix (0b) and redundant leading bits
+ const char *p = str.c_str() + 2;
+ while (p[1] && p[0] == p[1]) {
+ ++p;
+ }
+ return std::string(p);
+ } catch (const sc_core::sc_report &) {
+ std::stringstream msg;
+ msg << "character string '" << s << "' is not valid";
+ SC_REPORT_ERROR("cannot perform conversion",
+ msg.str().c_str());
+ return std::string();
+ }
+ }
+ }
+
+ // bin by default
+ std::string str(s);
+ str += "U"; // mark the string as unformatted
+ return str;
+}
+
+// convert binary string to formatted string
+const std::string
+convert_to_fmt(const std::string &s, sc_numrep numrep, bool w_prefix)
+{
+ int n = s.length();
+ std::string str("0bus");
+ // str += "0bus";
+ str += s;
+ sc_ufix a(str.c_str(), n, n, SC_TRN, SC_WRAP, 0, SC_ON);
+ return a.to_string(numrep, w_prefix);
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_logic.cpp -- C++ implementation of logic type. Behaves
+ pretty much the same way as HDLs logic type.
+
+ Original Author: Stan Y. Liao, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_logic.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:53 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <sstream>
+
+#include "systemc/ext/dt/bit/sc_logic.hh"
+#include "systemc/ext/utils/sc_report_handler.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_logic
+//
+// Four-valued logic type.
+// ----------------------------------------------------------------------------
+
+// support methods
+void
+sc_logic::invalid_value(sc_logic_value_t v)
+{
+ invalid_value((int)v);
+}
+
+void
+sc_logic::invalid_value(char c)
+{
+ std::stringstream msg;
+ msg << "sc_logic('" << c << "')";
+ SC_REPORT_ERROR("value is not valid", msg.str().c_str());
+}
+
+void
+sc_logic::invalid_value(int i)
+{
+ std::stringstream msg;
+ msg << "sc_logic(" << i << ")";
+ SC_REPORT_ERROR("value is not valid", msg.str().c_str());
+}
+
+
+void
+sc_logic::invalid_01() const
+{
+ if ((int)m_val == Log_Z) {
+ SC_REPORT_WARNING("sc_logic value 'Z' cannot be converted to bool", 0);
+ } else {
+ SC_REPORT_WARNING("sc_logic value 'X' cannot be converted to bool", 0);
+ }
+}
+
+
+// conversion tables
+const sc_logic_value_t sc_logic::char_to_logic[128] = {
+ Log_0, Log_1, Log_Z, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_0, Log_1, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_Z, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X,
+ Log_X, Log_X, Log_Z, Log_X, Log_X, Log_X, Log_X, Log_X
+};
+
+const char sc_logic::logic_to_char[4] = { '0', '1', 'Z', 'X' };
+
+const sc_logic_value_t sc_logic::and_table[4][4] = {
+ { Log_0, Log_0, Log_0, Log_0 },
+ { Log_0, Log_1, Log_X, Log_X },
+ { Log_0, Log_X, Log_X, Log_X },
+ { Log_0, Log_X, Log_X, Log_X }
+};
+
+const sc_logic_value_t sc_logic::or_table[4][4] = {
+ { Log_0, Log_1, Log_X, Log_X },
+ { Log_1, Log_1, Log_1, Log_1 },
+ { Log_X, Log_1, Log_X, Log_X },
+ { Log_X, Log_1, Log_X, Log_X }
+};
+
+const sc_logic_value_t sc_logic::xor_table[4][4] = {
+ { Log_0, Log_1, Log_X, Log_X },
+ { Log_1, Log_0, Log_X, Log_X },
+ { Log_X, Log_X, Log_X, Log_X },
+ { Log_X, Log_X, Log_X, Log_X }
+};
+
+const sc_logic_value_t sc_logic::not_table[4] = {
+ Log_1, Log_0, Log_X, Log_X
+};
+
+// other methods
+void
+sc_logic::scan(::std::istream &is)
+{
+ char c;
+ is >> c;
+ *this = c;
+}
+
+// #ifdef SC_DT_DEPRECATED
+const sc_logic sc_logic_0(Log_0);
+const sc_logic sc_logic_1(Log_1);
+const sc_logic sc_logic_Z(Log_Z);
+const sc_logic sc_logic_X(Log_X);
+// #endif
+
+const sc_logic SC_LOGIC_0(Log_0);
+const sc_logic SC_LOGIC_1(Log_1);
+const sc_logic SC_LOGIC_Z(Log_Z);
+const sc_logic SC_LOGIC_X(Log_X);
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_lv_base.cpp -- Arbitrary size logic vector class.
+
+ Original Author: Gene Bushuyev, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_lv_base.cpp,v $
+// Revision 1.2 2011/08/24 22:05:40 acg
+// Torsten Maehne: initialization changes to remove warnings.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:53 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <sstream>
+
+#include "systemc/ext/dt/bit/sc_lv_base.hh"
+
+namespace sc_dt
+{
+
+// explicit template instantiations
+template class sc_proxy<sc_lv_base>;
+template class sc_proxy<sc_bv_base>;
+
+void
+sc_proxy_out_of_bounds(const char *msg, int64 val)
+{
+ std::stringstream ss;
+ if (msg != NULL)
+ ss << msg;
+ if (val != 0)
+ ss << val;
+ SC_REPORT_ERROR("out of bounds", ss.str().c_str());
+}
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_lv_base
+//
+// Arbitrary size logic vector base class.
+// ----------------------------------------------------------------------------
+
+static const sc_digit data_array[] = {
+ SC_DIGIT_ZERO, ~SC_DIGIT_ZERO, SC_DIGIT_ZERO, ~SC_DIGIT_ZERO
+};
+
+static const sc_digit ctrl_array[] = {
+ SC_DIGIT_ZERO, SC_DIGIT_ZERO, ~SC_DIGIT_ZERO, ~SC_DIGIT_ZERO
+};
+
+void
+sc_lv_base::init(int length_, const sc_logic& init_value)
+{
+ // check the length
+ if (length_ <= 0) {
+ SC_REPORT_ERROR("zero length", 0);
+ sc_core::sc_abort(); // can't recover from here
+ }
+ // allocate memory for the data and control words
+ m_len = length_;
+ m_size = (m_len - 1) / SC_DIGIT_SIZE + 1;
+ m_data = new sc_digit[m_size * 2];
+ m_ctrl = m_data + m_size;
+ // initialize the bits to 'init_value'
+ sc_digit dw = data_array[init_value.value()];
+ sc_digit cw = ctrl_array[init_value.value()];
+ int sz = m_size;
+ for (int i = 0; i < sz; ++i) {
+ m_data[i] = dw;
+ m_ctrl[i] = cw;
+ }
+ clean_tail();
+}
+
+void
+sc_lv_base::assign_from_string(const std::string &s)
+{
+ // s must have been converted to bin
+ int len = m_len;
+ int s_len = s.length() - 1;
+ int min_len = sc_min(len, s_len);
+ int i = 0;
+ for (; i < min_len; ++i) {
+ char c = s[s_len - i - 1];
+ set_bit(i, sc_logic::char_to_logic[(int)c]);
+ }
+ // if formatted, fill the rest with sign(s), otherwise fill with zeros
+ sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t(s[0] - '0')
+ : sc_logic_value_t(0));
+ for (; i < len; ++i) {
+ set_bit(i, fill);
+ }
+}
+
+// constructors
+sc_lv_base::sc_lv_base(const char *a) :
+ m_len(0), m_size(0), m_data(0), m_ctrl(0)
+{
+ std::string s = convert_to_bin(a);
+ init(s.length() - 1);
+ assign_from_string(s);
+}
+
+sc_lv_base::sc_lv_base(const char *a, int length_) :
+ m_len(0), m_size(0), m_data(0), m_ctrl(0)
+{
+ init(length_);
+ assign_from_string(convert_to_bin(a));
+}
+
+sc_lv_base::sc_lv_base(const sc_lv_base &a) :
+ sc_proxy<sc_lv_base>(), m_len(a.m_len), m_size(a.m_size),
+ m_data(new sc_digit[m_size * 2]), m_ctrl(m_data + m_size)
+{
+ // copy the bits
+ int sz = m_size;
+ for (int i = 0; i < sz; ++i) {
+ m_data[i] = a.m_data[i];
+ m_ctrl[i] = a.m_ctrl[i];
+ }
+}
+
+// assignment operators
+sc_lv_base &
+sc_lv_base::operator = (const char *a)
+{
+ assign_from_string(convert_to_bin(a));
+ return *this;
+}
+
+// returns true if logic vector contains only 0's and 1's
+bool
+sc_lv_base::is_01() const
+{
+ int sz = m_size;
+ for (int i = 0; i < sz; ++i) {
+ if (m_ctrl[i] != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace sc_dt
--- /dev/null
+# Copyright 2018 Google, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+Import('*')
+
+if env['USE_SYSTEMC']:
+ Source('sc_fxcast_switch.cc')
+ Source('sc_fxdefs.cc')
+ Source('scfx_mant.cc')
+ Source('sc_fxnum.cc')
+ Source('sc_fxnum_observer.cc')
+ Source('scfx_pow10.cc')
+ Source('scfx_rep.cc')
+ Source('sc_fxtype_params.cc')
+ Source('scfx_utils.cc')
+ Source('sc_fxval.cc')
+ Source('sc_fxval_observer.cc')
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_fxcast_switch.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date: Gene Bushuyev, Synopsys, Inc.
+ Description of Modification: - fix explicit instantiation syntax.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_fxcast_switch.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:57 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/sc_fxcast_switch.hh"
+
+namespace sc_dt
+{
+
+template class sc_global<sc_fxcast_switch>;
+template class sc_context<sc_fxcast_switch>;
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxcast_switch
+//
+// Fixed-point cast switch class.
+// ----------------------------------------------------------------------------
+
+const std::string
+sc_fxcast_switch::to_string() const
+{
+ return sc_dt::to_string(m_sw);
+}
+
+void
+sc_fxcast_switch::print(::std::ostream &os) const
+{
+ os << sc_dt::to_string(m_sw);
+}
+
+void
+sc_fxcast_switch::dump(::std::ostream &os) const
+{
+ os << "sc_fxcast_switch" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "sw = " << sc_dt::to_string(m_sw) << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_fxdefs.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_fxdefs.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:57 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/sc_fxdefs.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_enc
+//
+// Enumeration of sign encodings.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_enc enc)
+{
+ switch (enc) {
+ case SC_TC_:
+ return std::string("SC_TC_");
+ case SC_US_:
+ return std::string("SC_US_");
+ default:
+ return std::string("unknown");
+ }
+}
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_q_mode
+//
+// Enumeration of quantization modes.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_q_mode q_mode)
+{
+ switch (q_mode) {
+ case SC_RND:
+ return std::string("SC_RND");
+ case SC_RND_ZERO:
+ return std::string("SC_RND_ZERO");
+ case SC_RND_MIN_INF:
+ return std::string("SC_RND_MIN_INF");
+ case SC_RND_INF:
+ return std::string("SC_RND_INF");
+ case SC_RND_CONV:
+ return std::string("SC_RND_CONV");
+ case SC_TRN:
+ return std::string("SC_TRN");
+ case SC_TRN_ZERO:
+ return std::string("SC_TRN_ZERO");
+ default:
+ return std::string("unknown");
+ }
+}
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_o_mode
+//
+// Enumeration of overflow modes.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_o_mode o_mode)
+{
+ switch (o_mode) {
+ case SC_SAT:
+ return std::string("SC_SAT");
+ case SC_SAT_ZERO:
+ return std::string("SC_SAT_ZERO");
+ case SC_SAT_SYM:
+ return std::string("SC_SAT_SYM");
+ case SC_WRAP:
+ return std::string("SC_WRAP");
+ case SC_WRAP_SM:
+ return std::string("SC_WRAP_SM");
+ default:
+ return std::string("unknown");
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_switch
+//
+// Enumeration of switch states.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_switch sw)
+{
+ switch (sw) {
+ case SC_OFF:
+ return std::string("SC_OFF");
+ case SC_ON:
+ return std::string("SC_ON");
+ default:
+ return std::string("unknown");
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_fmt
+//
+// Enumeration of formats for character string conversion.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_fmt fmt)
+{
+ switch (fmt) {
+ case SC_F:
+ return std::string("SC_F");
+ case SC_E:
+ return std::string("SC_E");
+ default:
+ return std::string("unknown");
+ }
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_fxnum.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_fxnum.cpp,v $
+// Revision 1.3 2011/01/19 18:57:40 acg
+// Andy Goodrich: changes for IEEE_1666_2011.
+//
+// Revision 1.2 2010/12/07 20:09:08 acg
+// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix
+//
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:57 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <cmath>
+
+#include "systemc/ext/dt/fx/sc_fxnum.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_bitref
+//
+// Proxy class for bit-selection in class sc_fxnum, behaves like sc_bit.
+// ----------------------------------------------------------------------------
+
+bool sc_fxnum_bitref::get() const { return m_num.get_bit(m_idx); }
+void sc_fxnum_bitref::set(bool high) { m_num.set_bit(m_idx, high); }
+
+// print or dump content
+void sc_fxnum_bitref::print(::std::ostream &os) const { os << get(); }
+
+void
+sc_fxnum_bitref::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
+
+void
+sc_fxnum_bitref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_bitref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "idx = " << m_idx << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast_bitref
+//
+// Proxy class for bit-selection in class sc_fxnum_fast, behaves like sc_bit.
+// ----------------------------------------------------------------------------
+
+bool sc_fxnum_fast_bitref::get() const { return m_num.get_bit(m_idx); }
+void sc_fxnum_fast_bitref::set(bool high) { m_num.set_bit(m_idx, high); }
+
+// print or dump content
+void sc_fxnum_fast_bitref::print(::std::ostream &os) const { os << get(); }
+
+void
+sc_fxnum_fast_bitref::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
+
+void
+sc_fxnum_fast_bitref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_fast_bitref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "idx = " << m_idx << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_subref
+//
+// Proxy class for part-selection in class sc_fxnum,
+// behaves like sc_bv_base.
+// ----------------------------------------------------------------------------
+
+bool
+sc_fxnum_subref::get() const
+{
+ return m_num.get_slice(m_from, m_to, m_bv);
+}
+
+bool
+sc_fxnum_subref::set()
+{
+ return m_num.set_slice(m_from, m_to, m_bv);
+}
+
+// print or dump content
+void
+sc_fxnum_subref::print(::std::ostream &os) const
+{
+ get();
+ m_bv.print(os);
+}
+
+void
+sc_fxnum_subref::scan(::std::istream &is)
+{
+ m_bv.scan(is);
+ set();
+}
+
+void
+sc_fxnum_subref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_subref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "from = " << m_from << ::std::endl;
+ os << "to = " << m_to << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast_subref
+//
+// Proxy class for part-selection in class sc_fxnum_fast,
+// behaves like sc_bv_base.
+// ----------------------------------------------------------------------------
+
+bool
+sc_fxnum_fast_subref::get() const
+{
+ return m_num.get_slice(m_from, m_to, m_bv);
+}
+
+bool
+sc_fxnum_fast_subref::set()
+{
+ return m_num.set_slice(m_from, m_to, m_bv);
+}
+
+// print or dump content
+void
+sc_fxnum_fast_subref::print(::std::ostream &os) const
+{
+ get();
+ m_bv.print(os);
+}
+
+void
+sc_fxnum_fast_subref::scan(::std::istream &is)
+{
+ m_bv.scan(is);
+ set();
+}
+
+void
+sc_fxnum_fast_subref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_fast_subref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "from = " << m_from << ::std::endl;
+ os << "to = " << m_to << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum
+//
+// Base class for the fixed-point types; arbitrary precision.
+// ----------------------------------------------------------------------------
+
+// explicit conversion to character string
+
+const std::string
+sc_fxnum::to_string() const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep) const
+{
+ return std::string(m_rep->to_string(numrep, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0),
+ SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep, sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(numrep, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0),
+ fmt, &m_params));
+}
+
+
+const std::string
+sc_fxnum::to_dec() const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_bin() const
+{
+ return std::string(m_rep->to_string(SC_BIN, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_oct() const
+{
+ return std::string(m_rep->to_string(SC_OCT, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_hex() const
+{
+ return std::string(m_rep->to_string(SC_HEX, -1, SC_F, &m_params));
+}
+
+
+// print or dump content
+void
+sc_fxnum::print(::std::ostream &os) const
+{
+ os << m_rep->to_string(SC_DEC, -1, SC_F, &m_params);
+}
+
+void
+sc_fxnum::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+void
+sc_fxnum::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "rep = ";
+ m_rep->dump(os);
+ os << "params = ";
+ m_params.dump(os);
+ os << "q_flag = " << m_q_flag << ::std::endl;
+ os << "o_flag = " << m_o_flag << ::std::endl;
+ // TO BE COMPLETED
+ // os << "observer = ";
+ // if (m_observer != 0)
+ // m_observer->dump(os);
+ // else
+ // os << "0" << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+sc_fxnum_observer *
+sc_fxnum::lock_observer() const
+{
+ SC_ASSERT_(m_observer != 0, "lock observer failed");
+ sc_fxnum_observer * tmp = m_observer;
+ m_observer = 0;
+ return tmp;
+}
+
+void
+sc_fxnum::unlock_observer(sc_fxnum_observer *observer_) const
+{
+ SC_ASSERT_(observer_ != 0, "unlock observer failed");
+ m_observer = observer_;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast
+//
+// Base class for the fixed-point types; limited precision.
+// ----------------------------------------------------------------------------
+
+static void
+quantization(double &c, const scfx_params ¶ms, bool &q_flag)
+{
+ int fwl = params.wl() - params.iwl();
+ double scale = scfx_pow2(fwl);
+ double val = scale * c;
+ double int_part;
+ double frac_part = modf(val, &int_part);
+
+ q_flag = (frac_part != 0.0);
+
+ if (q_flag) {
+ val = int_part;
+
+ switch (params.q_mode()) {
+ case SC_TRN: // truncation
+ {
+ if (c < 0.0)
+ val -= 1.0;
+ break;
+ }
+ case SC_RND: // rounding to plus infinity
+ {
+ if (frac_part >= 0.5)
+ val += 1.0;
+ else if (frac_part < -0.5)
+ val -= 1.0;
+ break;
+ }
+ case SC_TRN_ZERO: // truncation to zero
+ {
+ break;
+ }
+ case SC_RND_INF: // rounding to infinity
+ {
+ if (frac_part >= 0.5)
+ val += 1.0;
+ else if (frac_part <= -0.5)
+ val -= 1.0;
+ break;
+ }
+ case SC_RND_CONV: // convergent rounding
+ {
+ if (frac_part > 0.5 ||
+ (frac_part == 0.5 && fmod(int_part, 2.0) != 0.0)) {
+ val += 1.0;
+ } else if (frac_part < -0.5 ||
+ (frac_part == -0.5 && fmod(int_part, 2.0) != 0.0)) {
+ val -= 1.0;
+ }
+ break;
+ }
+ case SC_RND_ZERO: // rounding to zero
+ {
+ if (frac_part > 0.5)
+ val += 1.0;
+ else if (frac_part < -0.5)
+ val -= 1.0;
+ break;
+ }
+ case SC_RND_MIN_INF: // rounding to minus infinity
+ {
+ if (frac_part > 0.5)
+ val += 1.0;
+ else if (frac_part <= -0.5)
+ val -= 1.0;
+ break;
+ }
+ default:
+ ;
+ }
+ }
+
+ val /= scale;
+ c = val;
+}
+
+static void
+overflow(double &c, const scfx_params ¶ms, bool &o_flag)
+{
+ int iwl = params.iwl();
+ int fwl = params.wl() - iwl;
+ double full_circle = scfx_pow2(iwl);
+ double resolution = scfx_pow2(-fwl);
+ double low, high;
+ if (params.enc() == SC_TC_) {
+ high = full_circle / 2.0 - resolution;
+ if (params.o_mode() == SC_SAT_SYM)
+ low = - high;
+ else
+ low = - full_circle / 2.0;
+ } else {
+ low = 0.0;
+ high = full_circle - resolution;
+ }
+ double val = c;
+ sc_fxval_fast c2(c);
+
+ bool under = (val < low);
+ bool over = (val > high);
+
+ o_flag = (under || over);
+
+ if (o_flag) {
+ switch (params.o_mode()) {
+ case SC_WRAP: // wrap-around
+ {
+ int n_bits = params.n_bits();
+
+ if (n_bits == 0) {
+ // wrap-around all 'wl' bits
+ val -= floor(val / full_circle) * full_circle;
+ if (val > high)
+ val -= full_circle;
+ } else if (n_bits < params.wl()) {
+ double X = scfx_pow2(iwl - n_bits);
+
+ // wrap-around least significant 'wl - n_bits' bits
+ val -= floor(val / X) * X;
+ if (val > (X - resolution))
+ val -= X;
+
+ // saturate most significant 'n_bits' bits
+ if (under) {
+ val += low;
+ } else {
+ if (params.enc() == SC_TC_)
+ val += full_circle / 2.0 - X;
+ else
+ val += full_circle - X;
+ }
+ } else {
+ // saturate all 'wl' bits
+ if (under)
+ val = low;
+ else
+ val = high;
+ }
+ break;
+ }
+ case SC_SAT: // saturation
+ case SC_SAT_SYM: // symmetrical saturation
+ {
+ if (under)
+ val = low;
+ else
+ val = high;
+ break;
+ }
+ case SC_SAT_ZERO: // saturation to zero
+ {
+ val = 0.0;
+ break;
+ }
+ case SC_WRAP_SM: // sign magnitude wrap-around
+ {
+ SC_ERROR_IF_(params.enc() == SC_US_,
+ "SC_WRAP_SM not defined for unsigned numbers");
+
+ int n_bits = params.n_bits();
+
+ if (n_bits == 0) {
+ // invert conditionally
+ if (c2.get_bit(iwl) != c2.get_bit(iwl - 1))
+ val = -val - resolution;
+
+ // wrap-around all 'wl' bits
+ val -= floor(val / full_circle) * full_circle;
+ if (val > high)
+ val -= full_circle;
+ } else if (n_bits == 1) {
+ // invert conditionally
+ if (c2.is_neg() != c2.get_bit(iwl - 1))
+ val = -val - resolution;
+
+ // wrap-around all 'wl' bits
+ val -= floor(val / full_circle) * full_circle;
+ if (val > high)
+ val -= full_circle;
+ } else if (n_bits < params.wl()) {
+ // invert conditionally
+ if (c2.is_neg() == c2.get_bit(iwl - n_bits))
+ val = -val - resolution;
+
+ double X = scfx_pow2(iwl - n_bits);
+
+ // wrap-around least significant 'wl - n_bits' bits
+ val -= floor(val / X) * X;
+ if (val > (X - resolution))
+ val -= X;
+
+ // saturate most significant 'n_bits' bits
+ if (under)
+ val += low;
+ else
+ val += full_circle / 2.0 - X;
+ } else {
+ // saturate all 'wl' bits
+ if (under)
+ val = low;
+ else
+ val = high;
+ }
+ break;
+ }
+ default:
+ ;
+ }
+
+ c = val;
+ }
+}
+
+
+void
+sc_fxnum_fast::cast()
+{
+ scfx_ieee_double id(m_val);
+ SC_ERROR_IF_(id.is_nan() || id.is_inf(), "invalid fixed-point value");
+
+ if (m_params.cast_switch() == SC_ON) {
+ m_q_flag = false;
+ m_o_flag = false;
+
+ // check for special cases
+
+ if (id.is_zero()) {
+ if (id.negative() != 0)
+ m_val = -m_val;
+ return;
+ }
+
+ // perform casting
+ sc_dt::quantization(m_val, m_params, m_q_flag);
+ sc_dt::overflow(m_val, m_params, m_o_flag);
+
+ // check for special case: -0
+ id = m_val;
+ if (id.is_zero() && id.negative() != 0) {
+ m_val = -m_val;
+ }
+
+ // check for special case: NaN of Inf
+ if (id.is_nan() || id.is_inf()) {
+ m_val = 0.0;
+ }
+ }
+}
+
+
+// defined in sc_fxval.cpp;
+extern const char* to_string(const scfx_ieee_double &, sc_numrep, int, sc_fmt,
+ const scfx_params * =0);
+
+
+// explicit conversion to character string
+
+const std::string
+sc_fxnum_fast::to_string() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
+ SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep, sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
+ fmt, &m_params));
+}
+
+
+const std::string
+sc_fxnum_fast::to_dec() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_bin() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_BIN, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_oct() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_OCT, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_hex() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_HEX, -1, SC_F, &m_params));
+}
+
+// print or dump content
+void
+sc_fxnum_fast::print(::std::ostream &os) const
+{
+ os << sc_dt::to_string(m_val, SC_DEC, -1, SC_F, &m_params);
+}
+
+void
+sc_fxnum_fast::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+void
+sc_fxnum_fast::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_fast" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "val = " << m_val << ::std::endl;
+ os << "params = ";
+ m_params.dump(os);
+ os << "q_flag = " << m_q_flag << ::std::endl;
+ os << "o_flag = " << m_o_flag << ::std::endl;
+ // TO BE COMPLETED
+ // os << "observer = ";
+ // if (m_observer != 0)
+ // m_observer->dump(os);
+ // else
+ // os << "0" << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+// internal use only;
+bool
+sc_fxnum_fast::get_bit(int i) const
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_zero() || id.is_nan() || id.is_inf())
+ return false;
+
+ // convert to two's complement
+ unsigned int m0 = id.mantissa0();
+ unsigned int m1 = id.mantissa1();
+
+ if (id.is_normal())
+ m0 += 1U << 20;
+
+ if (id.negative() != 0) {
+ m0 = ~ m0;
+ m1 = ~ m1;
+ unsigned int tmp = m1;
+ m1 += 1U;
+ if (m1 <= tmp)
+ m0 += 1U;
+ }
+
+ // get the right bit
+ int j = i - id.exponent();
+ if ((j += 20) >= 32)
+ return ((m0 & 1U << 31) != 0);
+ else if (j >= 0)
+ return ((m0 & 1U << j) != 0);
+ else if ((j += 32) >= 0)
+ return ((m1 & 1U << j) != 0);
+ else
+ return false;
+}
+
+
+bool
+sc_fxnum_fast::set_bit(int i, bool high)
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_nan() || id.is_inf())
+ return false;
+
+ if (high) {
+ if (get_bit(i))
+ return true;
+
+ if (m_params.enc() == SC_TC_ && i == m_params.iwl() - 1)
+ m_val -= scfx_pow2(i);
+ else
+ m_val += scfx_pow2(i);
+ } else {
+ if (!get_bit(i))
+ return true;
+
+ if (m_params.enc() == SC_TC_ && i == m_params.iwl() - 1)
+ m_val += scfx_pow2(i);
+ else
+ m_val -= scfx_pow2(i);
+ }
+
+ return true;
+}
+
+
+bool
+sc_fxnum_fast::get_slice(int i, int j, sc_bv_base &bv) const
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_nan() || id.is_inf())
+ return false;
+
+ // convert to two's complement
+ unsigned int m0 = id.mantissa0();
+ unsigned int m1 = id.mantissa1();
+
+ if (id.is_normal())
+ m0 += 1U << 20;
+
+ if (id.negative() != 0) {
+ m0 = ~ m0;
+ m1 = ~ m1;
+ unsigned int tmp = m1;
+ m1 += 1U;
+ if (m1 <= tmp)
+ m0 += 1U;
+ }
+
+ // get the bits
+ int l = j;
+ for (int k = 0; k < bv.length(); ++ k) {
+ bool b = false;
+
+ int n = l - id.exponent();
+ if ((n += 20) >= 32)
+ b = ((m0 & 1U << 31) != 0);
+ else if (n >= 0)
+ b = ((m0 & 1U << n) != 0);
+ else if ((n += 32) >= 0)
+ b = ((m1 & 1U << n) != 0);
+
+ bv[k] = b;
+
+ if (i >= j)
+ ++l;
+ else
+ --l;
+ }
+
+ return true;
+}
+
+bool
+sc_fxnum_fast::set_slice(int i, int j, const sc_bv_base &bv)
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_nan() || id.is_inf())
+ return false;
+
+ // set the bits
+ int l = j;
+ for (int k = 0; k < bv.length(); ++k) {
+ if (bv[k].to_bool()) {
+ if (!get_bit(l)) {
+ if (m_params.enc() == SC_TC_ && l == m_params.iwl() - 1)
+ m_val -= scfx_pow2(l);
+ else
+ m_val += scfx_pow2(l);
+ }
+ } else {
+ if (get_bit(l)) {
+ if (m_params.enc() == SC_TC_ && l == m_params.iwl() - 1)
+ m_val += scfx_pow2(l);
+ else
+ m_val -= scfx_pow2(l);
+ }
+ }
+
+ if (i >= j)
+ ++l;
+ else
+ --l;
+ }
+
+ return true;
+}
+
+sc_fxnum_fast_observer *
+sc_fxnum_fast::lock_observer() const
+{
+ SC_ASSERT_(m_observer != 0, "lock observer failed");
+ sc_fxnum_fast_observer *tmp = m_observer;
+ m_observer = 0;
+ return tmp;
+}
+
+void
+sc_fxnum_fast::unlock_observer(sc_fxnum_fast_observer *observer_) const
+{
+ SC_ASSERT_(observer_ != 0, "unlock observer failed");
+ m_observer = observer_;
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_fxnum_observer.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_fxnum_observer.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/sc_fxnum_observer.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_observer
+//
+// Abstract base class for fixed-point types observers; arbitrary precision.
+// ----------------------------------------------------------------------------
+
+sc_fxnum_observer *(* sc_fxnum_observer::default_observer) () = 0;
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast_observer
+//
+// Abstract base class for fixed-point types observers; limited precision.
+// ----------------------------------------------------------------------------
+
+sc_fxnum_fast_observer *(* sc_fxnum_fast_observer::default_observer) () = 0;
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_fxtype_params.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_fxtype_params.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <sstream>
+
+#include "systemc/ext/dt/fx/sc_fxtype_params.hh"
+
+namespace sc_dt
+{
+
+template class sc_global<sc_fxtype_params>;
+template class sc_context<sc_fxtype_params>;
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxtype_params
+//
+// Fixed-point type parameters class.
+// ----------------------------------------------------------------------------
+
+const std::string
+sc_fxtype_params::to_string() const
+{
+ std::stringstream ss;
+ print(ss);
+ return ss.str();
+}
+
+void
+sc_fxtype_params::print(::std::ostream &os) const
+{
+ os << "("
+ << m_wl << ","
+ << m_iwl << ","
+ << m_q_mode << ","
+ << m_o_mode << ","
+ << m_n_bits
+ << ")";
+}
+
+void
+sc_fxtype_params::dump(::std::ostream &os) const
+{
+ os << "sc_fxtype_params" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "wl = " << m_wl << ::std::endl;
+ os << "iwl = " << m_iwl << ::std::endl;
+ os << "q_mode = " << m_q_mode << ::std::endl;
+ os << "o_mode = " << m_o_mode << ::std::endl;
+ os << "n_bits = " << m_n_bits << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_fxval.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_fxval.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <cctype>
+#include <cfloat>
+#include <cmath>
+#include <cstdlib>
+
+#include "systemc/ext/dt/fx/sc_fxval.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxval
+//
+// Fixed-point value type; arbitrary precision.
+// ----------------------------------------------------------------------------
+
+// explicit conversion to character string
+
+const std::string
+sc_fxval::to_string() const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, SC_E));
+}
+
+const std::string
+sc_fxval::to_string(sc_numrep numrep) const
+{
+ return std::string(m_rep->to_string(numrep, -1, SC_E));
+}
+
+const std::string
+sc_fxval::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0), SC_E));
+}
+
+const std::string
+sc_fxval::to_string(sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, fmt));
+}
+
+const std::string
+sc_fxval::to_string(sc_numrep numrep, sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(numrep, -1, fmt));
+}
+
+const std::string
+sc_fxval::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0), fmt));
+}
+
+
+const std::string
+sc_fxval::to_dec() const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, SC_E));
+}
+
+const std::string
+sc_fxval::to_bin() const
+{
+ return std::string(m_rep->to_string(SC_BIN, -1, SC_E));
+}
+
+const std::string
+sc_fxval::to_oct() const
+{
+ return std::string(m_rep->to_string(SC_OCT, -1, SC_E));
+}
+
+const std::string
+sc_fxval::to_hex() const
+{
+ return std::string(m_rep->to_string(SC_HEX, -1, SC_E));
+}
+
+
+// print or dump content
+
+void sc_fxval::print(::std::ostream &os) const { m_rep->print(os); }
+
+void
+sc_fxval::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+void
+sc_fxval::dump(::std::ostream &os) const
+{
+ os << "sc_fxval" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "rep = ";
+ m_rep->dump(os);
+ // TO BE COMPLETED
+ // os << "r_flag = " << m_r_flag << ::std::endl;
+ // os << "observer = ";
+ // if (m_observer != 0)
+ // m_observer->dump(os);
+ // else
+ // os << "0" << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+// protected methods and friend functions
+sc_fxval_observer *
+sc_fxval::lock_observer() const
+{
+ SC_ASSERT_(m_observer != 0, "lock observer failed");
+ sc_fxval_observer *tmp = m_observer;
+ m_observer = 0;
+ return tmp;
+}
+
+void
+sc_fxval::unlock_observer(sc_fxval_observer *observer_) const
+{
+ SC_ASSERT_(observer_ != 0, "unlock observer failed");
+ m_observer = observer_;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxval_fast
+//
+// Fixed-point value types; limited precision.
+// ----------------------------------------------------------------------------
+
+static void
+print_dec(scfx_string &s, scfx_ieee_double id, int w_prefix, sc_fmt fmt)
+{
+ if (id.negative() != 0) {
+ id.negative(0);
+ s += '-';
+ }
+
+ if (w_prefix == 1) {
+ scfx_print_prefix(s, SC_DEC);
+ }
+
+ if (id.is_zero()) {
+ s += '0';
+ return;
+ }
+
+ // split 'id' into its integer and fractional part
+ double int_part;
+ double frac_part = std::modf(static_cast<double>(id), &int_part);
+
+ int i;
+
+ // print integer part
+ int int_digits = 0;
+ int int_zeros = 0;
+
+ if (int_part != 0.0) {
+ int_digits = (int)std::ceil(std::log10(int_part + 1.0));
+
+ int len = s.length();
+ s.append(int_digits);
+
+ bool zero_digits = (frac_part == 0.0 && fmt != SC_F);
+
+ for (i = int_digits + len - 1; i >= len; i--) {
+ unsigned int remainder = (unsigned int)std::fmod(int_part, 10.0);
+ s[i] = static_cast<char>('0' + remainder);
+
+ if (zero_digits) {
+ if (remainder == 0)
+ int_zeros++;
+ else
+ zero_digits = false;
+ }
+
+ int_part /= 10.0;
+ }
+
+ // discard trailing zeros from int_part
+ s.discard(int_zeros);
+
+ if (s[len] == '0') {
+ // int_digits was overestimated by one
+ s.remove(len);
+ --int_digits;
+ }
+ }
+
+ // print fractional part
+ int frac_digits = 0;
+ int frac_zeros = 0;
+
+ if (frac_part != 0.0) {
+ s += '.';
+
+ bool zero_digits = (int_digits == 0 && fmt != SC_F);
+
+ frac_zeros = (int)std::floor(-std::log10(frac_part + DBL_EPSILON));
+
+ frac_part *= std::pow(10.0, frac_zeros);
+
+ frac_digits = frac_zeros;
+ if (!zero_digits) {
+ for (i = 0; i < frac_zeros; i++)
+ s += '0';
+ frac_zeros = 0;
+ }
+
+ while (frac_part != 0.0) {
+ frac_part *= 10.0;
+ int n = static_cast<int>(frac_part);
+
+ if (zero_digits) {
+ if (n == 0)
+ frac_zeros++;
+ else
+ zero_digits = false;
+ }
+
+ if (!zero_digits)
+ s += static_cast<char>('0' + n);
+
+ frac_part -= n;
+ frac_digits++;
+ }
+ }
+
+ // print exponent
+ if (fmt != SC_F) {
+ if (frac_digits == 0)
+ scfx_print_exp(s, int_zeros);
+ else if (int_digits == 0)
+ scfx_print_exp(s, -frac_zeros);
+ }
+}
+
+static void
+print_other(scfx_string &s, const scfx_ieee_double &id, sc_numrep numrep,
+ int w_prefix, sc_fmt fmt, const scfx_params *params)
+{
+ scfx_ieee_double id2 = id;
+
+ sc_numrep numrep2 = numrep;
+
+ bool numrep_is_sm = (numrep == SC_BIN_SM ||
+ numrep == SC_OCT_SM ||
+ numrep == SC_HEX_SM);
+
+ if (numrep_is_sm) {
+ if (id2.negative() != 0) {
+ s += '-';
+ id2.negative(0);
+ }
+ switch (numrep) {
+ case SC_BIN_SM:
+ numrep2 = SC_BIN_US;
+ break;
+ case SC_OCT_SM:
+ numrep2 = SC_OCT_US;
+ break;
+ case SC_HEX_SM:
+ numrep2 = SC_HEX_US;
+ break;
+ default:
+ ;
+ }
+ }
+
+ if (w_prefix != 0) {
+ scfx_print_prefix(s, numrep);
+ }
+
+ numrep = numrep2;
+
+ sc_fxval_fast a(id2);
+
+ int msb, lsb;
+
+ if (params != 0) {
+ msb = params->iwl() - 1;
+ lsb = params->iwl() - params->wl();
+
+ if (params->enc() == SC_TC_ &&
+ (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US) &&
+ !numrep_is_sm &&
+ params->wl() > 1) {
+ --msb;
+ } else if (params->enc() == SC_US_ &&
+ (numrep == SC_BIN ||
+ numrep == SC_OCT ||
+ numrep == SC_HEX ||
+ numrep == SC_CSD)) {
+ ++msb;
+ }
+ } else {
+ if (a.is_zero()) {
+ msb = 0;
+ lsb = 0;
+ } else {
+ msb = id2.exponent() + 1;
+ while (a.get_bit(msb) == a.get_bit(msb - 1))
+ --msb;
+
+ if (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US) {
+ --msb;
+ }
+
+ lsb = id2.exponent() - 52;
+ while (!a.get_bit(lsb))
+ ++lsb;
+ }
+ }
+
+ int step;
+
+ switch (numrep) {
+ case SC_BIN:
+ case SC_BIN_US:
+ case SC_CSD:
+ step = 1;
+ break;
+ case SC_OCT:
+ case SC_OCT_US:
+ step = 3;
+ break;
+ case SC_HEX:
+ case SC_HEX_US:
+ step = 4;
+ break;
+ default:
+ SC_REPORT_FATAL("assertion failed", "unexpected sc_numrep");
+ sc_core::sc_abort();
+ }
+
+ msb = (int)std::ceil(double(msb + 1) / step) * step - 1;
+
+ lsb = (int)std::floor(double(lsb) / step) * step;
+
+ if (msb < 0) {
+ s += '.';
+ if (fmt == SC_F) {
+ int sign = (id2.negative() != 0) ? (1 << step) - 1 : 0;
+ for (int i = (msb + 1) / step; i < 0; i++) {
+ if (sign < 10)
+ s += static_cast<char>(sign + '0');
+ else
+ s += static_cast<char>(sign + 'a' - 10);
+ }
+ }
+ }
+
+ int i = msb;
+ while (i >= lsb) {
+ int value = 0;
+ for (int j = step - 1; j >= 0; --j) {
+ value += static_cast<int>(a.get_bit(i)) << j;
+ --i;
+ }
+ if (value < 10)
+ s += static_cast<char>(value + '0');
+ else
+ s += static_cast<char>(value + 'a' - 10);
+ if (i == -1)
+ s += '.';
+ }
+
+ if (lsb > 0 && fmt == SC_F) {
+ for (int i = lsb / step; i > 0; i--)
+ s += '0';
+ }
+
+ if (s[s.length() - 1] == '.')
+ s.discard(1);
+
+ if (fmt != SC_F) {
+ if (msb < 0)
+ scfx_print_exp(s, (msb + 1) / step);
+ else if (lsb > 0)
+ scfx_print_exp(s, lsb / step);
+ }
+
+ if (numrep == SC_CSD)
+ scfx_tc2csd(s, w_prefix);
+}
+
+const char *
+to_string(const scfx_ieee_double &id, sc_numrep numrep, int w_prefix,
+ sc_fmt fmt, const scfx_params *params=0)
+{
+ static scfx_string s;
+
+ s.clear();
+
+ if (id.is_nan()) {
+ scfx_print_nan(s);
+ } else if (id.is_inf()) {
+ scfx_print_inf(s, static_cast<bool>(id.negative()));
+ } else if (id.negative() && !id.is_zero() &&
+ (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US)) {
+ s += "negative";
+ } else if (numrep == SC_DEC) {
+ sc_dt::print_dec(s, id, w_prefix, fmt);
+ } else {
+ sc_dt::print_other(s, id, numrep, w_prefix, fmt, params);
+ }
+
+ return s;
+}
+
+
+// explicit conversion to character string
+const std::string
+sc_fxval_fast::to_string() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_E));
+}
+
+const std::string
+sc_fxval_fast::to_string(sc_numrep numrep) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, -1, SC_E));
+}
+
+const std::string
+sc_fxval_fast::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
+ SC_E));
+}
+
+const std::string
+sc_fxval_fast::to_string(sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, fmt));
+}
+
+const std::string
+sc_fxval_fast::to_string(sc_numrep numrep, sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, -1, fmt));
+}
+
+const std::string
+sc_fxval_fast::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
+ fmt));
+}
+
+const std::string
+sc_fxval_fast::to_dec() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_E));
+}
+
+const std::string
+sc_fxval_fast::to_bin() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_BIN, -1, SC_E));
+}
+
+const std::string
+sc_fxval_fast::to_oct() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_OCT, -1, SC_E));
+}
+
+const std::string
+sc_fxval_fast::to_hex() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_HEX, -1, SC_E));
+}
+
+
+// print or dump content
+
+void
+sc_fxval_fast::print(::std::ostream &os) const
+{
+ os << sc_dt::to_string(m_val, SC_DEC, -1, SC_E);
+}
+
+void
+sc_fxval_fast::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+void
+sc_fxval_fast::dump(::std::ostream &os) const
+{
+ os << "sc_fxval_fast" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "val = " << m_val << ::std::endl;
+ // TO BE COMPLETED
+ // os << "r_flag = " << m_r_flag << ::std::endl;
+ // os << "observer = ";
+ // if (m_observer != 0)
+ // m_observer->dump(os);
+ // else
+ // os << "0" << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// internal use only;
+bool
+sc_fxval_fast::get_bit(int i) const
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_zero() || id.is_nan() || id.is_inf())
+ return false;
+
+ // convert to two's complement
+ unsigned int m0 = id.mantissa0();
+ unsigned int m1 = id.mantissa1();
+
+ if (id.is_normal())
+ m0 += 1U << 20;
+
+ if (id.negative() != 0) {
+ m0 = ~ m0;
+ m1 = ~ m1;
+ unsigned int tmp = m1;
+ m1 += 1U;
+ if (m1 <= tmp)
+ m0 += 1U;
+ }
+
+ // get the right bit
+ int j = i - id.exponent();
+ if ((j += 20) >= 32)
+ return ((m0 & 1U << 31) != 0);
+ else if (j >= 0)
+ return ((m0 & 1U << j) != 0);
+ else if ((j += 32) >= 0)
+ return ((m1 & 1U << j) != 0);
+ else
+ return false;
+}
+
+
+// protected methods and friend functions
+sc_fxval_fast_observer *
+sc_fxval_fast::lock_observer() const
+{
+ SC_ASSERT_(m_observer != 0, "lock observer failed");
+ sc_fxval_fast_observer *tmp = m_observer;
+ m_observer = 0;
+ return tmp;
+}
+
+void
+sc_fxval_fast::unlock_observer(sc_fxval_fast_observer *observer_) const
+{
+ SC_ASSERT_(observer_ != 0, "unlock observer failed");
+ m_observer = observer_;
+}
+
+#define SCFX_FAIL_IF_(cnd) \
+{ \
+ if ((cnd)) \
+ return static_cast<double>(scfx_ieee_double::nan()); \
+}
+
+double
+sc_fxval_fast::from_string(const char *s)
+{
+ SCFX_FAIL_IF_(s == 0 || *s == 0);
+
+ scfx_string s2;
+ s2 += s;
+ s2 += '\0';
+
+ bool sign_char;
+ int sign = scfx_parse_sign(s, sign_char);
+
+ sc_numrep numrep = scfx_parse_prefix(s);
+
+ int base = 0;
+
+ switch (numrep) {
+ case SC_DEC:
+ {
+ base = 10;
+ if (scfx_is_nan(s)) // special case: NaN
+ return static_cast<double>(scfx_ieee_double::nan());
+ if (scfx_is_inf(s)) // special case: Infinity
+ return static_cast<double>(scfx_ieee_double::inf(sign));
+ break;
+ }
+ case SC_BIN:
+ case SC_BIN_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 2;
+ break;
+ }
+
+ case SC_BIN_SM:
+ {
+ base = 2;
+ break;
+ }
+ case SC_OCT:
+ case SC_OCT_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 8;
+ break;
+ }
+ case SC_OCT_SM:
+ {
+ base = 8;
+ break;
+ }
+ case SC_HEX:
+ case SC_HEX_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 16;
+ break;
+ }
+ case SC_HEX_SM:
+ {
+ base = 16;
+ break;
+ }
+ case SC_CSD:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 2;
+ scfx_csd2tc(s2);
+ s = (const char*) s2 + 4;
+ numrep = SC_BIN;
+ break;
+ }
+ default:;// Martin, what is default???
+ }
+
+ //
+ // find end of mantissa and count the digits and points
+ //
+
+ const char *end = s;
+ bool based_point = false;
+ int int_digits = 0;
+ int frac_digits = 0;
+
+ while (*end) {
+ if (scfx_exp_start(end))
+ break;
+
+ if (*end == '.') {
+ SCFX_FAIL_IF_(based_point);
+ based_point = true;
+ } else {
+ SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep));
+ if (based_point)
+ frac_digits++;
+ else
+ int_digits++;
+ }
+
+ end++;
+ }
+
+ SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0);
+
+ // [ exponent ]
+ int exponent = 0;
+ if (*end) {
+ for (const char *e = end + 2; *e; e++)
+ SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC));
+ exponent = std::atoi(end + 1);
+ }
+
+ //
+ // convert the mantissa
+ //
+ double integer = 0.0;
+ if (int_digits != 0) {
+ bool first_digit = true;
+
+ for (; s < end; s++) {
+ if (*s == '.')
+ break;
+
+ if (first_digit) {
+ integer = scfx_to_digit(*s, numrep);
+ switch (numrep) {
+ case SC_BIN:
+ case SC_OCT:
+ case SC_HEX:
+ {
+ if (integer >= (base >> 1))
+ integer -= base; // two's complement
+ break;
+ }
+ default:
+ ;
+ }
+ first_digit = false;
+ } else {
+ integer *= base;
+ integer += scfx_to_digit(*s, numrep);
+ }
+ }
+ }
+
+ // [ . fraction ]
+ double fraction = 0.0;
+ if (frac_digits != 0) {
+ s++; // skip '.'
+
+ bool first_digit = (int_digits == 0);
+ double scale = 1.0;
+ for (; s < end; s++) {
+ scale /= base;
+
+ if (first_digit) {
+ fraction = scfx_to_digit(*s, numrep);
+ switch (numrep) {
+ case SC_BIN:
+ case SC_OCT:
+ case SC_HEX:
+ {
+ if (fraction >= (base >> 1))
+ fraction -= base; // two's complement
+ break;
+ }
+ default:
+ ;
+ }
+ fraction *= scale;
+ first_digit = false;
+ } else {
+ fraction += scfx_to_digit(*s, numrep) * scale;
+ }
+ }
+ }
+
+ double exp =
+ (exponent != 0) ? std::pow((double) base, (double) exponent) : 1;
+
+ return (sign * (integer + fraction) * exp);
+}
+
+#undef SCFX_FAIL_IF_
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_fxval_observer.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_fxval_observer.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/sc_fxval_observer.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxval_observer
+//
+// Abstract base class for fixed-point value type observers;
+// arbitrary precision.
+// ----------------------------------------------------------------------------
+
+sc_fxval_observer *(* sc_fxval_observer::default_observer)() = 0;
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxval_fast_observer
+//
+// Abstract base class for fixed-point value type observers;
+// limited precision.
+// ----------------------------------------------------------------------------
+
+sc_fxval_fast_observer *(* sc_fxval_fast_observer::default_observer)() = 0;
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ scfx_mant.cpp -
+
+ Original Author: Robert Graulich, Synopsys, Inc.
+ Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: scfx_mant.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/scfx_mant.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// word memory management
+// ----------------------------------------------------------------------------
+
+class word_list // Entry in free_words bucket.
+{
+ public:
+ word_list *m_next_p;
+};
+
+static inline unsigned
+next_pow2_index(std::size_t size)
+{
+ unsigned index = scfx_find_msb(size);
+ // If this was a power of 2 we are one bucket too low.
+ if (~(UINT64_ONE << index) & size)
+ index++;
+ // If this is a 64-bit machine and we are using 32-bit words go down
+ // one slot size, as all the slots are 2x in size.
+ if (index != 0 && (sizeof(word_list) != sizeof(word))) {
+ index -= 1;
+ }
+ return index;
+}
+
+static word_list *free_words[32] = { 0 };
+
+word *
+scfx_mant::alloc_word(std::size_t size)
+{
+ const int ALLOC_SIZE = 128;
+
+ unsigned slot_index = next_pow2_index(size);
+ unsigned alloc_size = (UINT64_ONE << slot_index);
+
+ word_list*& slot = free_words[slot_index];
+
+ if (!slot) {
+ slot = new word_list[ALLOC_SIZE * alloc_size];
+ unsigned i;
+ for (i = 0; i < alloc_size * (ALLOC_SIZE - 1) ; i += alloc_size) {
+ slot[i].m_next_p = &slot[i + alloc_size];
+ }
+ slot[i].m_next_p = 0;
+ }
+
+ word *result = (word *)slot;
+ free_words[slot_index] = slot[0].m_next_p;
+ return result;
+}
+
+void
+scfx_mant::free_word(word *array, std::size_t size)
+{
+ if (array && size) {
+ int slot_index = next_pow2_index(size);
+ word_list *wl_p = (word_list *)array;
+
+ wl_p->m_next_p = free_words[slot_index];
+ free_words[slot_index] = wl_p;
+ }
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ scfx_pow10.cpp -
+
+ Original Author: Robert Graulich, Synopsys, Inc.
+ Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: scfx_pow10.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/scfx_pow10.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : scfx_pow10
+//
+// Class to compute (and cache) powers of 10 in arbitrary precision.
+// ----------------------------------------------------------------------------
+
+scfx_pow10::scfx_pow10()
+{
+ m_pos[0] = scfx_rep(10.0);
+ m_neg[0] = scfx_rep(0.1);
+
+ for (int i = 1; i < SCFX_POW10_TABLE_SIZE; i++) {
+ m_pos[i].set_nan();
+ m_neg[i].set_nan();
+ }
+}
+
+scfx_pow10::~scfx_pow10() {}
+
+const scfx_rep
+scfx_pow10::operator() (int i)
+{
+ if (i == 0) {
+ return scfx_rep(1.0);
+ }
+
+ if (i > 0) {
+ int bit = scfx_find_msb(i);
+ scfx_rep result = *pos(bit);
+ if (bit) {
+ while (--bit >= 0) {
+ if ((1 << bit) & i) {
+ scfx_rep *tmp = mult_scfx_rep(result, *pos(bit));
+ result = *tmp;
+ delete tmp;
+ }
+ }
+ }
+ return result;
+ } else {
+ i = -i;
+ int bit = scfx_find_msb(i);
+ scfx_rep result = *neg(bit);
+ if (bit) {
+ while (--bit >= 0) {
+ if ((1 << bit) & i) {
+ scfx_rep *tmp = mult_scfx_rep(result, *neg(bit));
+ result = *tmp;
+ delete tmp;
+ }
+ }
+ }
+ return result;
+ }
+}
+
+
+scfx_rep *
+scfx_pow10::pos(int i)
+{
+ if (!m_pos[i].is_normal()) {
+ multiply(m_pos[i], *pos(i - 1), *pos(i - 1));
+ }
+ return &m_pos[i];
+}
+
+scfx_rep *
+scfx_pow10::neg(int i)
+{
+ if (!m_neg[i].is_normal()) {
+ multiply(m_neg[i], *neg(i - 1), *neg(i - 1));
+ }
+ return &m_neg[i];
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ scfx_rep.cpp -
+
+ Original Author: Robert Graulich, Synopsys, Inc.
+ Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: scfx_rep.cpp,v $
+// Revision 1.4 2011/08/24 22:05:43 acg
+// Torsten Maehne: initialization changes to remove warnings.
+//
+// Revision 1.3 2011/08/15 16:43:24 acg
+// Torsten Maehne: changes to remove unused argument warnings.
+//
+// Revision 1.2 2009/02/28 00:26:20 acg
+// Andy Goodrich: bug fixes.
+//
+// Revision 1.2 2008/11/06 17:22:47 acg
+// Andy Goodrich: bug fixes for 2.2.1.
+//
+// Revision 1.1.1.1 2006/12/15 20:31:36 acg
+// SystemC 2.2
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <cctype>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+
+#include "base/compiler.hh"
+#include "systemc/ext/dt/bit/sc_bv_base.hh"
+#include "systemc/ext/dt/bit/sc_lv_base.hh"
+#include "systemc/ext/dt/fx/scfx_ieee.hh"
+#include "systemc/ext/dt/fx/scfx_pow10.hh"
+#include "systemc/ext/dt/fx/scfx_rep.hh"
+#include "systemc/ext/dt/fx/scfx_utils.hh"
+#include "systemc/ext/utils/endian.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// some utilities
+// ----------------------------------------------------------------------------
+
+static scfx_pow10 pow10_fx;
+
+static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int;
+
+static inline int
+n_word(int x)
+{
+ return (x + bits_in_word - 1) / bits_in_word;
+}
+
+
+// ----------------------------------------------------------------------------
+// CONSTRUCTORS
+// ----------------------------------------------------------------------------
+
+scfx_rep::scfx_rep() :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ set_zero();
+}
+
+scfx_rep::scfx_rep(int a) : m_mant(min_mant), m_wp(), m_sign(), m_state(),
+ m_msw(), m_lsw(), m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_wp = m_msw = m_lsw = 2;
+ m_state = normal;
+ if (a > 0) {
+ m_mant[2] = a;
+ m_sign = 1;
+ } else {
+ m_mant[2] = -a;
+ m_sign = -1;
+ }
+ } else {
+ set_zero();
+ }
+}
+
+scfx_rep::scfx_rep(unsigned int a) : m_mant(min_mant), m_wp(), m_sign(),
+ m_state(), m_msw(), m_lsw(), m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_wp = m_msw = m_lsw = 2;
+ m_state = normal;
+ m_mant[2] = a;
+ m_sign = 1;
+ } else {
+ set_zero();
+ }
+}
+
+scfx_rep::scfx_rep(long a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_state = normal;
+ if (a > 0) {
+ m_sign = 1;
+ } else {
+ a = -a;
+ m_sign = -1;
+ }
+# if defined(SC_LONG_64)
+ m_wp = 1;
+ m_mant[1] = static_cast<word>(a);
+ m_mant[2] = static_cast<word>(a >> bits_in_word);
+ find_sw();
+# else
+ m_wp = 2;
+ m_msw = 2;
+ m_lsw = 2;
+ m_mant[2] = a;
+# endif
+ } else {
+ set_zero();
+ }
+}
+
+scfx_rep::scfx_rep(unsigned long a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_wp = m_msw = m_lsw = 2;
+ m_state = normal;
+# if defined(SC_LONG_64)
+ m_wp = 1;
+ m_mant[1] = static_cast<word>(a);
+ m_mant[2] = static_cast<word>(a >> bits_in_word);
+ find_sw();
+# else
+ m_wp = 2;
+ m_msw = 2;
+ m_lsw = 2;
+ m_mant[2] = a;
+# endif
+ m_sign = 1;
+ }
+ else
+ set_zero();
+}
+
+scfx_rep::scfx_rep(double a) :
+ m_mant(min_mant), m_wp(0), m_sign(), m_state(normal), m_msw(0),
+ m_lsw(0), m_r_flag(false)
+{
+ m_mant.clear();
+
+ scfx_ieee_double id(a);
+
+ m_sign = id.negative() ? -1 : 1;
+
+ if (id.is_nan()) {
+ m_state = not_a_number;
+ } else if (id.is_inf()) {
+ m_state = infinity;
+ } else if (id.is_subnormal()) {
+ m_mant[0] = id.mantissa1();
+ m_mant[1] = id.mantissa0();
+ normalize(id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE);
+ } else if (id.is_normal()) {
+ m_mant[0] = id.mantissa1();
+ m_mant[1] = id.mantissa0() | (1 << mantissa0_size);
+ normalize(id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE);
+ }
+}
+
+scfx_rep::scfx_rep(int64 a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_wp = 1;
+ m_state = normal;
+ if (a > 0) {
+ m_mant[1] = static_cast<word>(a);
+ m_mant[2] = static_cast<word>(a >> bits_in_word);
+ m_sign = 1;
+ } else {
+ m_mant[1] = static_cast<word>(-a);
+ m_mant[2] = static_cast<word>((-a) >> bits_in_word);
+ m_sign = -1;
+ }
+ find_sw();
+ } else {
+ set_zero();
+ }
+}
+
+scfx_rep::scfx_rep(uint64 a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_wp = 1;
+ m_state = normal;
+ m_mant[1] = static_cast<word>(a);
+ m_mant[2] = static_cast<word>(a >> bits_in_word);
+ m_sign = 1;
+ find_sw();
+ } else {
+ set_zero();
+ }
+}
+
+scfx_rep::scfx_rep(const sc_signed &a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a.iszero()) {
+ set_zero();
+ } else {
+ int words = n_word(a.length());
+ if (words > size())
+ resize_to(words);
+ m_mant.clear();
+ m_wp = 0;
+ m_state = normal;
+ if (a.sign()) {
+ sc_signed a2 = -a;
+ for (int i = 0; i < a2.length(); ++i) {
+ if (a2[i]) {
+ scfx_index x = calc_indices(i);
+ m_mant[x.wi()] |= 1 << x.bi();
+ }
+ }
+ m_sign = -1;
+ } else {
+ for (int i = 0; i < a.length(); ++i) {
+ if (a[i]) {
+ scfx_index x = calc_indices(i);
+ m_mant[x.wi()] |= 1 << x.bi();
+ }
+ }
+ m_sign = 1;
+ }
+ find_sw();
+ }
+}
+
+scfx_rep::scfx_rep(const sc_unsigned &a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a.iszero()) {
+ set_zero();
+ } else {
+ int words = n_word(a.length());
+ if (words > size())
+ resize_to(words);
+ m_mant.clear();
+ m_wp = 0;
+ m_state = normal;
+ for (int i = 0; i < a.length(); ++i) {
+ if (a[i]) {
+ scfx_index x = calc_indices(i);
+ m_mant[x.wi()] |= 1 << x.bi();
+ }
+ }
+ m_sign = 1;
+ find_sw();
+ }
+}
+
+// copy constructor
+scfx_rep::scfx_rep(const scfx_rep &a) :
+ m_mant(a.m_mant), m_wp(a.m_wp), m_sign(a.m_sign), m_state(a.m_state),
+ m_msw(a.m_msw), m_lsw(a.m_lsw), m_r_flag(false)
+{}
+
+
+// ----------------------------------------------------------------------------
+// OPERATORS : new, delete
+//
+// Memory management for class scfx_rep.
+// ----------------------------------------------------------------------------
+
+union scfx_rep_node
+{
+ char data[sizeof(scfx_rep)];
+ scfx_rep_node *next;
+};
+
+static scfx_rep_node *list = 0;
+
+void *
+scfx_rep::operator new(std::size_t size)
+{
+ const int ALLOC_SIZE = 1024;
+
+ if (size != sizeof(scfx_rep))
+ return ::operator new(size);
+
+ if (!list) {
+ list = new scfx_rep_node[ALLOC_SIZE];
+ for (int i = 0; i < ALLOC_SIZE - 1; i++)
+ list[i].next = list + i + 1;
+ list[ALLOC_SIZE - 1].next = 0;
+ }
+
+ scfx_rep *ptr = reinterpret_cast<scfx_rep *>(list->data);
+ list = list->next;
+
+ return ptr;
+}
+
+void
+scfx_rep::operator delete(void *ptr, std::size_t size)
+{
+ if (size != sizeof(scfx_rep)) {
+ ::operator delete(ptr);
+ return;
+ }
+
+ scfx_rep_node *node = static_cast<scfx_rep_node *>(ptr);
+ node->next = list;
+ list = node;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : from_string
+//
+// Convert from character string to sc_fxrep.
+// ----------------------------------------------------------------------------
+
+#define SCFX_FAIL_IF_(cnd) \
+{ \
+ if ((cnd)) { \
+ m_state = not_a_number; \
+ m_mant.clear(); /* to avoid Purify UMRs during assignment */ \
+ return; \
+ } \
+}
+
+void
+scfx_rep::from_string(const char *s, int cte_wl)
+{
+ SCFX_FAIL_IF_(s == 0 || *s == 0);
+
+ scfx_string s2;
+ s2 += s;
+ s2 += '\0';
+
+ bool sign_char;
+ m_sign = scfx_parse_sign(s, sign_char);
+
+ sc_numrep numrep = scfx_parse_prefix(s);
+
+ int base = 0;
+
+ switch (numrep) {
+ case SC_DEC:
+ {
+ base = 10;
+ if (scfx_is_nan(s)) { // special case: NaN
+ m_state = not_a_number;
+ m_mant.clear(); /* to avoid Purify UMRs during assignment */
+ return;
+ }
+ if (scfx_is_inf(s)) { // special case: Infinity
+ m_state = infinity;
+ m_mant.clear(); /* to avoid Purify UMRs during assignment */
+ return;
+ }
+ break;
+ }
+ case SC_BIN:
+ case SC_BIN_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 2;
+ break;
+ }
+
+ case SC_BIN_SM:
+ {
+ base = 2;
+ break;
+ }
+ case SC_OCT:
+ case SC_OCT_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 8;
+ break;
+ }
+ case SC_OCT_SM:
+ {
+ base = 8;
+ break;
+ }
+ case SC_HEX:
+ case SC_HEX_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 16;
+ break;
+ }
+ case SC_HEX_SM:
+ {
+ base = 16;
+ break;
+ }
+ case SC_CSD:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 2;
+ scfx_csd2tc(s2);
+ s = (const char *)s2 + 4;
+ numrep = SC_BIN;
+ break;
+ }
+ default:
+ ;
+ }
+
+ //
+ // find end of mantissa and count the digits and points
+ //
+
+ const char *end = s;
+ bool based_point = false;
+ int int_digits = 0;
+ int frac_digits = 0;
+
+ while (*end) {
+ if (scfx_exp_start(end))
+ break;
+
+ if (*end == '.') {
+ SCFX_FAIL_IF_(based_point);
+ based_point = true;
+ } else {
+ SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep));
+ if (based_point)
+ frac_digits++;
+ else
+ int_digits++;
+ }
+
+ ++end;
+ }
+
+ SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0);
+
+ // [ exponent ]
+ int exponent = 0;
+
+ if (*end) {
+ for (const char *e = end + 2; *e; ++e)
+ SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC));
+ exponent = std::atoi(end + 1);
+ }
+
+ //
+ // check if the mantissa is negative
+ //
+ bool mant_is_neg = false;
+ switch (numrep) {
+ case SC_BIN:
+ case SC_OCT:
+ case SC_HEX:
+ {
+ const char *p = s;
+ if (*p == '.')
+ ++p;
+
+ mant_is_neg = (scfx_to_digit(* p, numrep) >= (base >> 1));
+ break;
+ }
+ default:
+ ;
+ }
+
+ //
+ // convert the mantissa
+ //
+
+ switch (base) {
+ case 2:
+ {
+ int bit_offset = exponent % bits_in_word;
+ int word_offset = exponent / bits_in_word;
+
+ int_digits += bit_offset;
+ frac_digits -= bit_offset;
+
+ int words = n_word(int_digits) + n_word(frac_digits);
+ if (words > size())
+ resize_to(words);
+ m_mant.clear();
+
+ int j = n_word(frac_digits) * bits_in_word + int_digits - 1;
+
+ for (; s < end; s++) {
+ switch (*s) {
+ case '1':
+ set_bin(j);
+ M5_FALLTHROUGH;
+ case '0':
+ j--;
+ M5_FALLTHROUGH;
+ case '.':
+ break;
+ default:
+ SCFX_FAIL_IF_(true); // should not happen
+ }
+ }
+
+ m_wp = n_word(frac_digits) - word_offset;
+ break;
+ }
+ case 8:
+ {
+ exponent *= 3;
+ int_digits *= 3;
+ frac_digits *= 3;
+
+ int bit_offset = exponent % bits_in_word;
+ int word_offset = exponent / bits_in_word;
+
+ int_digits += bit_offset;
+ frac_digits -= bit_offset;
+
+ int words = n_word(int_digits) + n_word(frac_digits);
+ if (words > size())
+ resize_to(words);
+ m_mant.clear();
+
+ int j = n_word(frac_digits) * bits_in_word + int_digits - 3;
+
+ for (; s < end; s++) {
+ switch (*s) {
+ case '7': case '6': case '5': case '4':
+ case '3': case '2': case '1':
+ set_oct(j, *s - '0');
+ M5_FALLTHROUGH;
+ case '0':
+ j -= 3;
+ M5_FALLTHROUGH;
+ case '.':
+ break;
+ default:
+ SCFX_FAIL_IF_(true); // should not happen
+ }
+ }
+
+ m_wp = n_word(frac_digits) - word_offset;
+ break;
+ }
+ case 10:
+ {
+ word carry, temp;
+ int length = int_digits + frac_digits;
+ resize_to(sc_max(min_mant, n_word(4 * length)));
+
+ m_mant.clear();
+ m_msw = m_lsw = 0;
+
+ for (; s < end; s++) {
+ switch (*s) {
+ case '9': case '8': case '7': case '6': case '5':
+ case '4': case '3': case '2': case '1': case '0':
+ multiply_by_ten();
+ carry = *s - '0';
+ for (int i = 0; carry && i < m_mant.size(); i++) {
+ temp = m_mant[i];
+ temp += carry;
+ carry = temp < m_mant[i];
+ m_mant[i] = temp;
+ }
+ case '.':
+ break;
+ default:
+ SCFX_FAIL_IF_(true); // should not happen
+ }
+ }
+
+ m_wp = 0;
+ find_sw();
+
+ int denominator = frac_digits - exponent;
+
+ if (denominator) {
+ scfx_rep frac_num = pow10_fx(denominator);
+ scfx_rep *temp_num =
+ div_scfx_rep(const_cast<const scfx_rep &>(*this),
+ frac_num, cte_wl);
+ *this = *temp_num;
+ delete temp_num;
+ }
+
+ break;
+ }
+ case 16:
+ {
+ exponent *= 4;
+ int_digits *= 4;
+ frac_digits *= 4;
+
+ int bit_offset = exponent % bits_in_word;
+ int word_offset = exponent / bits_in_word;
+
+ int_digits += bit_offset;
+ frac_digits -= bit_offset;
+
+ int words = n_word(int_digits) + n_word(frac_digits);
+ if (words > size())
+ resize_to(words);
+ m_mant.clear();
+
+ int j = n_word(frac_digits) * bits_in_word + int_digits - 4;
+
+ for (; s < end; s ++) {
+ switch (*s) {
+ case 'f': case 'e': case 'd': case 'c': case 'b': case 'a':
+ set_hex(j, *s - 'a' + 10);
+ j -= 4;
+ break;
+ case 'F': case 'E': case 'D': case 'C': case 'B': case 'A':
+ set_hex(j, *s - 'A' + 10);
+ j -= 4;
+ break;
+ case '9': case '8': case '7': case '6': case '5':
+ case '4': case '3': case '2': case '1':
+ set_hex(j, *s - '0');
+ M5_FALLTHROUGH;
+ case '0':
+ j -= 4;
+ M5_FALLTHROUGH;
+ case '.':
+ break;
+ default:
+ SCFX_FAIL_IF_(true); // should not happen
+ }
+ }
+
+ m_wp = n_word(frac_digits) - word_offset;
+ break;
+ }
+ }
+
+ m_state = normal;
+ find_sw();
+
+ //
+ // two's complement of mantissa if it is negative
+ //
+ if (mant_is_neg) {
+ m_mant[m_msw] |= ~0U << scfx_find_msb(m_mant[m_msw]);
+ for (int i = m_msw + 1; i < m_mant.size(); ++i)
+ m_mant[i] = static_cast<word>(-1);
+ complement(m_mant, m_mant, m_mant.size());
+ inc(m_mant);
+ m_sign *= -1;
+ find_sw();
+ }
+}
+
+#undef SCFX_FAIL_IF_
+
+// ----------------------------------------------------------------------------
+// METHOD : to_double
+//
+// Convert from scfx_rep to double.
+// ----------------------------------------------------------------------------
+
+double
+scfx_rep::to_double() const
+{
+ scfx_ieee_double id;
+
+ // handle special cases
+ if (is_nan()) {
+ id.set_nan();
+ return id;
+ }
+
+ if (is_inf()) {
+ id.set_inf();
+ id.negative(m_sign < 0);
+ return id;
+ }
+
+ if (is_zero()) {
+ id = 0.;
+ id.negative(m_sign < 0);
+ return id;
+ }
+
+ int msb = scfx_find_msb(m_mant[m_msw]);
+
+ int exp = (m_msw - m_wp) * bits_in_word + msb;
+
+ if (exp > SCFX_IEEE_DOUBLE_E_MAX) {
+ id.set_inf();
+ id.negative(m_sign < 0);
+ return id;
+ }
+
+ if (exp < SCFX_IEEE_DOUBLE_E_MIN -
+ static_cast<int>(SCFX_IEEE_DOUBLE_M_SIZE))
+ {
+ id = 0.;
+ return id;
+ }
+
+ int shift = mantissa0_size - msb;
+
+ unsigned int m0;
+ unsigned int m1 = 0;
+ unsigned int guard = 0;
+
+ if (shift == 0) {
+ m0 = m_mant[m_msw] & ~(1 << mantissa0_size);
+ if (m_msw > m_lsw) {
+ m1 = m_mant[m_msw - 1];
+ if (m_msw - 1 > m_lsw)
+ guard = m_mant[m_msw - 2] >> (bits_in_word - 1);
+ }
+ } else if (shift < 0) {
+ m0 = (m_mant[m_msw] >> -shift) & ~(1 << mantissa0_size);
+ m1 = m_mant[m_msw] << (bits_in_word + shift);
+ if (m_msw > m_lsw) {
+ m1 |= m_mant[m_msw - 1] >> -shift;
+ guard = (m_mant[m_msw - 1] >> (-shift - 1)) & 1;
+ }
+ } else {
+ m0 = (m_mant[m_msw] << shift) & ~(1 << mantissa0_size);
+ if (m_msw > m_lsw) {
+ m0 |= m_mant[m_msw - 1] >> (bits_in_word - shift);
+ m1 = m_mant[m_msw - 1] << shift;
+ if (m_msw - 1 > m_lsw) {
+ m1 |= m_mant[m_msw - 2] >> (bits_in_word - shift);
+ guard = (m_mant[m_msw - 2] >> (bits_in_word - shift - 1)) & 1;
+ }
+ }
+ }
+
+ if (exp < SCFX_IEEE_DOUBLE_E_MIN) {
+ m0 |= (1 << mantissa0_size);
+
+ int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp;
+
+ if (subnormal_shift < bits_in_word) {
+ m1 = m1 >> subnormal_shift |
+ m0 << (bits_in_word - subnormal_shift);
+ m0 = m0 >> subnormal_shift;
+ } else {
+ m1 = m0 >> (subnormal_shift - bits_in_word);
+ m0 = 0;
+ }
+
+ guard = 0;
+
+ exp = SCFX_IEEE_DOUBLE_E_MIN - 1;
+ }
+
+ id.mantissa0(m0);
+ id.mantissa1(m1);
+ id.exponent(exp);
+ id.negative(m_sign < 0);
+
+ double result = id;
+
+ if (guard != 0)
+ result += m_sign * scfx_pow2(exp - SCFX_IEEE_DOUBLE_M_SIZE);
+
+ return result;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : to_uint64
+//
+// Convert from scfx_rep to uint64.
+// Truncates towards 0 _then_ wraps; infinities and NaN go to zero.
+// ----------------------------------------------------------------------------
+
+uint64
+scfx_rep::to_uint64() const
+{
+ if (!is_normal() || is_zero()) {
+ return 0;
+ }
+
+ uint64 result = 0;
+ int shift = 0;
+ int idx = m_wp;
+
+ // Ignore bits off the top; they modulo out.
+ // Ignore bits off the bottom; we're truncating.
+ while (shift < 64 && m_msw >= idx && idx >= m_lsw) {
+ result += static_cast<uint64>(m_mant[idx]) << shift;
+ shift += bits_in_word;
+ idx += 1;
+ }
+
+ return m_sign > 0 ? result : -result;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : to_string
+//
+// Convert from scfx_rep to character string.
+// ----------------------------------------------------------------------------
+
+void
+print_dec(scfx_string &s, const scfx_rep &num, int w_prefix, sc_fmt fmt)
+{
+ if (num.is_neg())
+ s += '-';
+
+ if (w_prefix == 1) {
+ scfx_print_prefix(s, SC_DEC);
+ }
+
+ if (num.is_zero()) {
+ s += '0';
+ return;
+ }
+
+ // split 'num' into its integer and fractional part
+ scfx_rep int_part = num;
+ scfx_rep frac_part = num;
+
+ int i;
+
+ for (i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i++)
+ int_part.m_mant[i] = 0;
+ int_part.find_sw();
+ if (int_part.m_wp < int_part.m_lsw)
+ int_part.resize_to(int_part.size() - int_part.m_wp, -1);
+
+ for (i = frac_part.m_msw;
+ i >= frac_part.m_lsw && i >= frac_part.m_wp; i--)
+ frac_part.m_mant[i] = 0;
+ frac_part.find_sw();
+ if (frac_part.m_msw == frac_part.size() - 1)
+ frac_part.resize_to(frac_part.size() + 1, 1);
+
+ // print integer part
+ int int_digits = 0;
+ int int_zeros = 0;
+
+ if (!int_part.is_zero()) {
+ double int_wl = (int_part.m_msw - int_part.m_wp) * bits_in_word +
+ scfx_find_msb(int_part.m_mant[int_part.m_msw]) + 1;
+ int_digits = (int)std::ceil(int_wl * std::log10(2.));
+
+ int len = s.length();
+ s.append(int_digits);
+
+ bool zero_digits = (frac_part.is_zero() && fmt != SC_F);
+
+ for (i = int_digits + len - 1; i >= len; i--) {
+ unsigned int remainder = int_part.divide_by_ten();
+ s[i] = static_cast<char>('0' + remainder);
+
+ if (zero_digits) {
+ if (remainder == 0)
+ int_zeros++;
+ else
+ zero_digits = false;
+ }
+ }
+
+ // discard trailing zeros from int_part
+ s.discard(int_zeros);
+
+ if (s[len] == '0') {
+ // int_digits was overestimated by one
+ s.remove(len);
+ --int_digits;
+ }
+ }
+
+ // print fractional part
+ int frac_digits = 0;
+ int frac_zeros = 0;
+
+ if (!frac_part.is_zero()) {
+ s += '.';
+
+ bool zero_digits = (int_digits == 0 && fmt != SC_F);
+
+ double frac_wl = (frac_part.m_wp - frac_part.m_msw) * bits_in_word -
+ scfx_find_msb(frac_part.m_mant[frac_part.m_msw]) - 1;
+ frac_zeros = (int)std::floor(frac_wl * std::log10(2.));
+
+ scfx_rep temp;
+ sc_dt::multiply(temp, frac_part, pow10_fx(frac_zeros));
+ frac_part = temp;
+ if (frac_part.m_msw == frac_part.size() - 1)
+ frac_part.resize_to(frac_part.size() + 1, 1);
+
+ frac_digits = frac_zeros;
+ if (!zero_digits) {
+ for (i = 0; i < frac_zeros; i++)
+ s += '0';
+ frac_zeros = 0;
+ }
+
+ while (!frac_part.is_zero()) {
+ frac_part.multiply_by_ten();
+ int n = frac_part.m_mant[frac_part.m_msw + 1];
+
+ if (zero_digits) {
+ if (n == 0)
+ frac_zeros++;
+ else
+ zero_digits = false;
+ }
+
+ if (! zero_digits)
+ s += static_cast<char>('0' + n);
+
+ frac_part.m_mant[frac_part.m_msw + 1] = 0;
+ frac_digits++;
+ }
+ }
+
+ // print exponent
+ if (fmt != SC_F) {
+ if (frac_digits == 0)
+ scfx_print_exp(s, int_zeros);
+ else if (int_digits == 0)
+ scfx_print_exp(s, -frac_zeros);
+ }
+}
+
+void
+print_other(scfx_string &s, const scfx_rep &a, sc_numrep numrep, int w_prefix,
+ sc_fmt fmt, const scfx_params *params)
+{
+ scfx_rep b = a;
+
+ sc_numrep numrep2 = numrep;
+
+ bool numrep_is_sm = (numrep == SC_BIN_SM ||
+ numrep == SC_OCT_SM ||
+ numrep == SC_HEX_SM);
+
+ if (numrep_is_sm) {
+ if (b.is_neg()) {
+ s += '-';
+ b = *neg_scfx_rep(a);
+ }
+ switch (numrep) {
+ case SC_BIN_SM:
+ numrep2 = SC_BIN_US;
+ break;
+ case SC_OCT_SM:
+ numrep2 = SC_OCT_US;
+ break;
+ case SC_HEX_SM:
+ numrep2 = SC_HEX_US;
+ break;
+ default:
+ ;
+ }
+ }
+
+ if (w_prefix != 0) {
+ scfx_print_prefix(s, numrep);
+ }
+
+ numrep = numrep2;
+
+ int msb, lsb;
+
+ if (params != 0) {
+ msb = params->iwl() - 1;
+ lsb = params->iwl() - params->wl();
+
+ if (params->enc() == SC_TC_ &&
+ (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US) &&
+ !numrep_is_sm &&
+ params->wl() > 1) {
+ --msb;
+ } else if (params->enc() == SC_US_ &&
+ (numrep == SC_BIN ||
+ numrep == SC_OCT ||
+ numrep == SC_HEX ||
+ numrep == SC_CSD)) {
+ ++msb;
+ }
+ } else {
+ if (b.is_zero()) {
+ msb = 0;
+ lsb = 0;
+ } else {
+ msb = (b.m_msw - b.m_wp) * bits_in_word
+ + scfx_find_msb(b.m_mant[ b.m_msw ]) + 1;
+ while (b.get_bit(msb) == b.get_bit(msb - 1))
+ --msb;
+
+ if (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US) {
+ --msb;
+ }
+
+ lsb = (b.m_lsw - b.m_wp) * bits_in_word +
+ scfx_find_lsb(b.m_mant[b.m_lsw]);
+ }
+ }
+
+ int step;
+
+ switch (numrep) {
+ case SC_BIN:
+ case SC_BIN_US:
+ case SC_CSD:
+ step = 1;
+ break;
+ case SC_OCT:
+ case SC_OCT_US:
+ step = 3;
+ break;
+ case SC_HEX:
+ case SC_HEX_US:
+ step = 4;
+ break;
+ default:
+ SC_REPORT_FATAL("assertion failed", "unexpected sc_numrep");
+ sc_core::sc_abort();
+ }
+
+ msb = (int)std::ceil(double(msb + 1) / step) * step - 1;
+
+ lsb = (int)std::floor(double(lsb) / step) * step;
+
+ if (msb < 0) {
+ s += '.';
+ if (fmt == SC_F) {
+ int sign = (b.is_neg()) ? (1 << step) - 1 : 0;
+ for (int i = (msb + 1) / step; i < 0; i++) {
+ if (sign < 10)
+ s += static_cast<char>(sign + '0');
+ else
+ s += static_cast<char>(sign + 'a' - 10);
+ }
+ }
+ }
+
+ int i = msb;
+ while (i >= lsb) {
+ int value = 0;
+ for (int j = step - 1; j >= 0; --j) {
+ value += static_cast<int>(b.get_bit(i)) << j;
+ --i;
+ }
+ if (value < 10)
+ s += static_cast<char>(value + '0');
+ else
+ s += static_cast<char>(value + 'a' - 10);
+ if (i == -1)
+ s += '.';
+ }
+
+ if (lsb > 0 && fmt == SC_F) {
+ for (int i = lsb / step; i > 0; i--)
+ s += '0';
+ }
+
+ if (s[s.length() - 1] == '.')
+ s.discard(1);
+
+ if (fmt != SC_F) {
+ if (msb < 0)
+ scfx_print_exp(s, (msb + 1) / step);
+ else if (lsb > 0)
+ scfx_print_exp(s, lsb / step);
+ }
+
+ if (numrep == SC_CSD)
+ scfx_tc2csd(s, w_prefix);
+}
+
+const char *
+scfx_rep::to_string(sc_numrep numrep, int w_prefix,
+ sc_fmt fmt, const scfx_params *params) const
+{
+ static scfx_string s;
+
+ s.clear();
+
+ if (is_nan()) {
+ scfx_print_nan(s);
+ } else if (is_inf()) {
+ scfx_print_inf(s, is_neg());
+ } else if (is_neg() && !is_zero() &&
+ (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US)) {
+ s += "negative";
+ } else if (numrep == SC_DEC || numrep == SC_NOBASE) {
+ sc_dt::print_dec(s, *this, w_prefix, fmt);
+ } else {
+ sc_dt::print_other(s, *this, numrep, w_prefix, fmt, params);
+ }
+
+ return s;
+}
+
+
+// ----------------------------------------------------------------------------
+// ADD
+//
+// add two mantissas of the same size
+// result has the same size
+// returns carry of operation
+// ----------------------------------------------------------------------------
+
+static inline int
+add_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b)
+{
+ unsigned int carry = 0;
+
+ int index = 0;
+
+ do {
+ word x = a[index];
+ word y = b[index];
+
+ y += carry;
+ carry = y < carry;
+ y += x;
+ carry += y < x;
+ result[index] = y;
+ } while (++index < size);
+
+ return (carry ? 1 : 0);
+}
+
+static inline int
+sub_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b)
+{
+ unsigned carry = 0;
+
+ int index = 0;
+
+ do {
+ word x = a[index];
+ word y = b[index];
+
+ y += carry;
+ carry = y < carry;
+ y = x - y;
+ carry += y > x;
+ result[index] = y;
+ } while (++index < size);
+
+ return (carry ? 1 : 0);
+}
+
+scfx_rep *
+add_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl)
+{
+ scfx_rep &result = *new scfx_rep;
+
+ //
+ // check for special cases
+ //
+ if (lhs.is_nan() || rhs.is_nan() ||
+ (lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign)) {
+ result.set_nan();
+ return &result;
+ }
+
+ if (lhs.is_inf()) {
+ result.set_inf(lhs.m_sign);
+ return &result;
+ }
+
+ if (rhs.is_inf()) {
+ result.set_inf(rhs.m_sign);
+ return &result;
+ }
+
+ //
+ // align operands if needed
+ //
+ scfx_mant_ref lhs_mant;
+ scfx_mant_ref rhs_mant;
+
+ int len_mant = lhs.size();
+ int new_wp = lhs.m_wp;
+
+ align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant);
+
+ //
+ // size the result mantissa
+ //
+ result.resize_to(len_mant);
+ result.m_wp = new_wp;
+
+ //
+ // do it
+ //
+ if (lhs.m_sign == rhs.m_sign) {
+ add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
+ result.m_sign = lhs.m_sign;
+ } else {
+ int cmp = compare_abs(lhs, rhs);
+
+ if (cmp == 1) {
+ sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
+ result.m_sign = lhs.m_sign;
+ } else if (cmp == -1) {
+ sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant);
+ result.m_sign = rhs.m_sign;
+ } else {
+ result.m_mant.clear();
+ result.m_sign = 1;
+ }
+ }
+
+ result.find_sw();
+ result.round(max_wl);
+
+ return &result;
+}
+
+
+// ----------------------------------------------------------------------------
+// SUB
+//
+// sub two word's of the same size
+// result has the same size
+// returns carry of operation
+// ----------------------------------------------------------------------------
+
+static inline int
+sub_with_index(scfx_mant &a, int a_msw, int /*a_lsw*/,
+ const scfx_mant &b, int b_msw, int b_lsw)
+{
+ unsigned carry = 0;
+
+ int size = b_msw - b_lsw;
+ int a_index = a_msw - size;
+ int b_index = b_msw - size;
+
+ do {
+ word x = a[a_index];
+ word y = b[b_index];
+
+ y += carry;
+ carry = y < carry;
+ y = x - y;
+ carry += y > x;
+ a[a_index] = y;
+
+ a_index++;
+ b_index++;
+ } while (size--);
+
+ if (carry) {
+ // special case: a[a_msw + 1] == 1
+ a[a_msw + 1] = 0;
+ }
+
+ return (carry ? 1 : 0);
+}
+
+scfx_rep *
+sub_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl)
+{
+ scfx_rep &result = *new scfx_rep;
+
+ //
+ // check for special cases
+ //
+ if (lhs.is_nan() || rhs.is_nan() ||
+ (lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign)) {
+ result.set_nan();
+ return &result;
+ }
+
+ if (lhs.is_inf()) {
+ result.set_inf(lhs.m_sign);
+ return &result;
+ }
+
+ if (rhs.is_inf()) {
+ result.set_inf(-1 * rhs.m_sign);
+ return &result;
+ }
+
+ //
+ // align operands if needed
+ //
+ scfx_mant_ref lhs_mant;
+ scfx_mant_ref rhs_mant;
+
+ int len_mant = lhs.size();
+ int new_wp = lhs.m_wp;
+
+ align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant);
+
+ //
+ // size the result mantissa
+ //
+ result.resize_to(len_mant);
+ result.m_wp = new_wp;
+
+ //
+ // do it
+ //
+ if (lhs.m_sign != rhs.m_sign) {
+ add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
+ result.m_sign = lhs.m_sign;
+ } else {
+ int cmp = compare_abs(lhs, rhs);
+
+ if (cmp == 1) {
+ sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
+ result.m_sign = lhs.m_sign;
+ } else if (cmp == -1) {
+ sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant);
+ result.m_sign = -rhs.m_sign;
+ } else {
+ result.m_mant.clear();
+ result.m_sign = 1;
+ }
+ }
+
+ result.find_sw();
+ result.round(max_wl);
+
+ return &result;
+}
+
+
+// ----------------------------------------------------------------------------
+// MUL
+// ----------------------------------------------------------------------------
+
+union word_short
+{
+ word l;
+ struct
+ {
+#if defined(SC_BOOST_BIG_ENDIAN)
+ half_word u;
+ half_word l;
+#elif defined(SC_BOOST_LITTLE_ENDIAN)
+ half_word l;
+ half_word u;
+#endif
+ } s;
+};
+
+#if defined(SC_BOOST_BIG_ENDIAN)
+static const int half_word_incr = -1;
+#elif defined(SC_BOOST_LITTLE_ENDIAN)
+static const int half_word_incr = 1;
+#endif
+
+void
+multiply(scfx_rep &result, const scfx_rep &lhs, const scfx_rep &rhs,
+ int max_wl)
+{
+ //
+ // check for special cases
+ //
+ if (lhs.is_nan() || rhs.is_nan() ||
+ (lhs.is_inf() && rhs.is_zero()) ||
+ (lhs.is_zero() && rhs.is_inf())) {
+ result.set_nan();
+ return;
+ }
+
+ if (lhs.is_inf() || rhs.is_inf()) {
+ result.set_inf(lhs.m_sign * rhs.m_sign);
+ return;
+ }
+
+ if (lhs.is_zero() || rhs.is_zero()) {
+ result.set_zero(lhs.m_sign * rhs.m_sign);
+ return;
+ }
+
+ //
+ // do it
+ //
+ int len_lhs = lhs.m_msw - lhs.m_lsw + 1;
+ int len_rhs = rhs.m_msw - rhs.m_lsw + 1;
+
+ int new_size = sc_max(min_mant, len_lhs + len_rhs);
+ int new_wp = (lhs.m_wp - lhs.m_lsw) + (rhs.m_wp - rhs.m_lsw);
+ int new_sign = lhs.m_sign * rhs.m_sign;
+
+ result.resize_to(new_size);
+ result.m_mant.clear();
+ result.m_wp = new_wp;
+ result.m_sign = new_sign;
+ result.m_state = scfx_rep::normal;
+
+ half_word *s1 = lhs.m_mant.half_addr(lhs.m_lsw);
+ half_word *s2 = rhs.m_mant.half_addr(rhs.m_lsw);
+
+ half_word *t = result.m_mant.half_addr();
+
+ len_lhs <<= 1;
+ len_rhs <<= 1;
+
+ int i1, i2;
+
+ for (i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr) {
+ word_short ls;
+ ls.l = 0;
+
+ half_word v1 = s1[i1];
+
+ for (i2 = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr) {
+ ls.l += v1 * s2[i2];
+ ls.s.l = ls.s.u + ((t[i2] += ls.s.l) < ls.s.l);
+ ls.s.u = 0;
+ }
+
+ t[i2] = ls.s.l;
+ t += half_word_incr;
+ }
+
+ result.find_sw();
+ result.round(max_wl);
+}
+
+
+// ----------------------------------------------------------------------------
+// DIV
+// ----------------------------------------------------------------------------
+
+scfx_rep *
+div_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int div_wl)
+{
+ scfx_rep &result = *new scfx_rep;
+
+ //
+ // check for special cases
+ //
+ if (lhs.is_nan() || rhs.is_nan() || (lhs.is_inf() && rhs.is_inf()) ||
+ (lhs.is_zero() && rhs.is_zero())) {
+ result.set_nan();
+ return &result;
+ }
+
+ if (lhs.is_inf() || rhs.is_zero()) {
+ result.set_inf(lhs.m_sign * rhs.m_sign);
+ return &result;
+ }
+
+ if (lhs.is_zero() || rhs.is_inf()) {
+ result.set_zero(lhs.m_sign * rhs.m_sign);
+ return &result;
+ }
+
+ //
+ // do it
+ //
+
+ // compute one bit more for rounding
+ div_wl++;
+
+ result.resize_to(sc_max(n_word(div_wl) + 1, min_mant));
+ result.m_mant.clear();
+ result.m_sign = lhs.m_sign * rhs.m_sign;
+
+ int msb_lhs = scfx_find_msb(lhs.m_mant[lhs.m_msw]) +
+ (lhs.m_msw - lhs.m_wp) * bits_in_word;
+ int msb_rhs = scfx_find_msb(rhs.m_mant[rhs.m_msw]) +
+ (rhs.m_msw - rhs.m_wp) * bits_in_word;
+
+ int msb_res = msb_lhs - msb_rhs;
+ int to_shift = -msb_res % bits_in_word;
+ int result_index;
+
+ int c = (msb_res % bits_in_word >= 0) ? 1 : 0;
+
+ result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word;
+ result.m_wp = (result.size() - c) - msb_res / bits_in_word;
+
+ scfx_rep remainder = lhs;
+
+ // align msb from remainder to msb from rhs
+ remainder.lshift(to_shift);
+
+ // make sure msw(remainder) < size - 1
+ if (remainder.m_msw == remainder.size() - 1)
+ remainder.resize_to(remainder.size() + 1, 1);
+
+ // make sure msw(remainder) >= msw(rhs)!
+ int msw_diff = rhs.m_msw - remainder.m_msw;
+ if (msw_diff > 0)
+ remainder.resize_to(remainder.size() + msw_diff, -1);
+
+ int counter;
+
+ for (counter = div_wl; counter && !remainder.is_zero(); counter--) {
+ if (compare_msw_ff(rhs, remainder) <= 0) {
+ result.set_bin(result_index);
+ sub_with_index(remainder.m_mant, remainder.m_msw, remainder.m_lsw,
+ rhs.m_mant, rhs.m_msw, rhs.m_lsw);
+ }
+ result_index--;
+ remainder.shift_left(1);
+ remainder.m_lsw = remainder.find_lsw();
+ }
+
+ // perform convergent rounding, if needed
+ if (counter == 0) {
+ int index = result_index + 1 - result.m_wp * bits_in_word;
+
+ scfx_index x = result.calc_indices(index);
+ scfx_index x1 = result.calc_indices(index + 1);
+
+ if (result.o_bit_at(x) && result.o_bit_at(x1))
+ result.q_incr(x);
+
+ result.m_r_flag = true;
+ }
+
+ result.find_sw();
+
+ return &result;
+}
+
+// ----------------------------------------------------------------------------
+// destructive shift mantissa to the left
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::lshift(int n)
+{
+ if (n == 0)
+ return;
+
+ if (n < 0) {
+ rshift(-n);
+ return;
+ }
+
+ if (is_normal()) {
+ int shift_bits = n % bits_in_word;
+ int shift_words = n / bits_in_word;
+
+ // resize if needed
+ if (m_msw == size() - 1 &&
+ scfx_find_msb(m_mant[m_msw]) >= bits_in_word - shift_bits)
+ resize_to(size() + 1, 1);
+
+ // do it
+ m_wp -= shift_words;
+ shift_left(shift_bits);
+ find_sw();
+ }
+}
+
+// ----------------------------------------------------------------------------
+// destructive shift mantissa to the right
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::rshift(int n)
+{
+ if (n == 0)
+ return;
+
+ if (n < 0) {
+ lshift(-n);
+ return;
+ }
+
+ if (is_normal()) {
+ int shift_bits = n % bits_in_word;
+ int shift_words = n / bits_in_word;
+
+ // resize if needed
+ if (m_lsw == 0 && scfx_find_lsb(m_mant[m_lsw]) < shift_bits)
+ resize_to(size() + 1, -1);
+
+ // do it
+ m_wp += shift_words;
+ shift_right(shift_bits);
+ find_sw();
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// FRIEND FUNCTION : compare_abs
+//
+// Compares the absolute values of two scfx_reps, excluding the special cases.
+// ----------------------------------------------------------------------------
+
+int
+compare_abs(const scfx_rep &a, const scfx_rep &b)
+{
+ // check for zero
+ word a_word = a.m_mant[a.m_msw];
+ word b_word = b.m_mant[b.m_msw];
+
+ if (a_word == 0 || b_word == 0) {
+ if (a_word != 0)
+ return 1;
+ if (b_word != 0)
+ return -1;
+ return 0;
+ }
+
+ // compare msw index
+ int a_msw = a.m_msw - a.m_wp;
+ int b_msw = b.m_msw - b.m_wp;
+
+ if (a_msw > b_msw)
+ return 1;
+
+ if (a_msw < b_msw)
+ return -1;
+
+ // compare content
+ int a_i = a.m_msw;
+ int b_i = b.m_msw;
+
+ while (a_i >= a.m_lsw && b_i >= b.m_lsw) {
+ a_word = a.m_mant[a_i];
+ b_word = b.m_mant[b_i];
+ if (a_word > b_word)
+ return 1;
+ if (a_word < b_word)
+ return -1;
+ --a_i;
+ --b_i;
+ }
+
+ bool a_zero = true;
+ while (a_i >= a.m_lsw) {
+ a_zero = a_zero && (a.m_mant[a_i] == 0);
+ --a_i;
+ }
+
+ bool b_zero = true;
+ while (b_i >= b.m_lsw) {
+ b_zero = b_zero && (b.m_mant[b_i] == 0);
+ --b_i;
+ }
+
+ // assertion: a_zero || b_zero
+
+ if (!a_zero && b_zero)
+ return 1;
+
+ if (a_zero && !b_zero)
+ return -1;
+
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+// FRIEND FUNCTION : cmp_scfx_rep
+//
+// Compares the values of two scfx_reps, including the special cases.
+// ----------------------------------------------------------------------------
+
+int
+cmp_scfx_rep(const scfx_rep &a, const scfx_rep &b)
+{
+ // handle special cases
+
+ if (a.is_nan() || b.is_nan()) {
+ return 2;
+ }
+
+ if (a.is_inf() || b.is_inf()) {
+ if (a.is_inf()) {
+ if (!a.is_neg()) {
+ if (b.is_inf() && !b.is_neg()) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ if (b.is_inf() && b.is_neg()) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+ }
+ if (b.is_inf()) {
+ if (!b.is_neg()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ }
+
+ if (a.is_zero() && b.is_zero()) {
+ return 0;
+ }
+
+ // compare sign
+ if (a.m_sign != b.m_sign) {
+ return a.m_sign;
+ }
+
+ return (a.m_sign * compare_abs(a, b));
+}
+
+
+// ----------------------------------------------------------------------------
+// PRIVATE METHOD : quantization
+//
+// Performs destructive quantization.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::quantization(const scfx_params ¶ms, bool &q_flag)
+{
+ scfx_index x = calc_indices(params.iwl() - params.wl());
+
+ if (x.wi() < 0)
+ return;
+
+ if (x.wi() >= size())
+ resize_to(x.wi() + 1, 1);
+
+ bool qb = q_bit(x);
+ bool qz = q_zero(x);
+
+ q_flag = (qb || ! qz);
+
+ if (q_flag) {
+ switch (params.q_mode()) {
+ case SC_TRN: // truncation
+ {
+ if (is_neg())
+ q_incr(x);
+ break;
+ }
+ case SC_RND: // rounding to plus infinity
+ {
+ if (!is_neg()) {
+ if (qb)
+ q_incr(x);
+ } else {
+ if (qb && !qz)
+ q_incr(x);
+ }
+ break;
+ }
+ case SC_TRN_ZERO: // truncation to zero
+ {
+ break;
+ }
+ case SC_RND_INF: // rounding to infinity
+ {
+ if (qb)
+ q_incr(x);
+ break;
+ }
+ case SC_RND_CONV: // convergent rounding
+ {
+ if ((qb && !qz) || (qb && qz && q_odd(x)))
+ q_incr(x);
+ break;
+ }
+ case SC_RND_ZERO: // rounding to zero
+ {
+ if (qb && !qz)
+ q_incr(x);
+ break;
+ }
+ case SC_RND_MIN_INF: // rounding to minus infinity
+ {
+ if (!is_neg()) {
+ if (qb && !qz)
+ q_incr(x);
+ } else {
+ if (qb)
+ q_incr(x);
+ }
+ break;
+ }
+ default:
+ ;
+ }
+ q_clear(x);
+
+ find_sw();
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// PRIVATE METHOD : overflow
+//
+// Performs destructive overflow handling.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::overflow(const scfx_params ¶ms, bool &o_flag)
+{
+ scfx_index x = calc_indices(params.iwl() - 1);
+
+ if (x.wi() >= size())
+ resize_to(x.wi() + 1, 1);
+
+ if (x.wi() < 0) {
+ resize_to(size() - x.wi(), -1);
+ x.wi(0);
+ }
+
+ bool zero_left = o_zero_left(x);
+ bool bit_at = o_bit_at(x);
+ bool zero_right = o_zero_right(x);
+
+ bool under = false;
+ bool over = false;
+
+ sc_enc enc = params.enc();
+
+ if (enc == SC_TC_) {
+ if (is_neg()) {
+ if (params.o_mode() == SC_SAT_SYM)
+ under = (!zero_left || bit_at);
+ else
+ under = (!zero_left || (zero_left && bit_at && ! zero_right));
+ } else {
+ over = (! zero_left || bit_at);
+ }
+ } else {
+ if (is_neg())
+ under = (!is_zero());
+ else
+ over = (!zero_left);
+ }
+
+ o_flag = (under || over);
+
+ if (o_flag) {
+ scfx_index x2 = calc_indices(params.iwl() - params.wl());
+
+ if (x2.wi() < 0) {
+ resize_to(size() - x2.wi(), -1);
+ x.wi(x.wi() - x2.wi());
+ x2.wi(0);
+ }
+
+ switch (params.o_mode()) {
+ case SC_WRAP: // wrap-around
+ {
+ int n_bits = params.n_bits();
+
+ if (n_bits == 0) {
+ // wrap-around all 'wl' bits
+ toggle_tc();
+ o_extend(x, enc);
+ toggle_tc();
+ } else if (n_bits < params.wl()) {
+ scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits);
+
+ // wrap-around least significant 'wl - n_bits' bits;
+ // saturate most significant 'n_bits' bits
+ toggle_tc();
+ o_set(x, x3, enc, under);
+ o_extend(x, enc);
+ toggle_tc();
+ } else {
+ // saturate all 'wl' bits
+ if (under)
+ o_set_low(x, enc);
+ else
+ o_set_high(x, x2, enc);
+ }
+ break;
+ }
+ case SC_SAT: // saturation
+ {
+ if (under)
+ o_set_low(x, enc);
+ else
+ o_set_high(x, x2, enc);
+ break;
+ }
+ case SC_SAT_SYM: // symmetrical saturation
+ {
+ if (under) {
+ if (enc == SC_TC_)
+ o_set_high(x, x2, SC_TC_, -1);
+ else
+ o_set_low(x, SC_US_);
+ } else {
+ o_set_high(x, x2, enc);
+ }
+ break;
+ }
+ case SC_SAT_ZERO: // saturation to zero
+ {
+ set_zero();
+ break;
+ }
+ case SC_WRAP_SM: // sign magnitude wrap-around
+ {
+ SC_ERROR_IF_(enc == SC_US_,
+ "SC_WRAP_SM not defined for unsigned numbers");
+
+ int n_bits = params.n_bits();
+
+ if (n_bits == 0) {
+ scfx_index x4 = calc_indices(params.iwl());
+
+ if (x4.wi() >= size())
+ resize_to(x4.wi() + 1, 1);
+
+ toggle_tc();
+ if (o_bit_at(x4) != o_bit_at(x))
+ o_invert(x2);
+ o_extend(x, SC_TC_);
+ toggle_tc();
+ } else if (n_bits == 1) {
+ toggle_tc();
+ if (is_neg() != o_bit_at(x))
+ o_invert(x2);
+ o_extend(x, SC_TC_);
+ toggle_tc();
+ } else if (n_bits < params.wl()) {
+ scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits);
+ scfx_index x4 = calc_indices(params.iwl() - n_bits);
+
+ // wrap-around least significant 'wl - n_bits' bits;
+ // saturate most significant 'n_bits' bits
+ toggle_tc();
+ if (is_neg() == o_bit_at(x4))
+ o_invert(x2);
+ o_set(x, x3, SC_TC_, under);
+ o_extend(x, SC_TC_);
+ toggle_tc();
+ } else {
+ if (under)
+ o_set_low(x, SC_TC_);
+ else
+ o_set_high(x, x2, SC_TC_);
+ }
+ break;
+ }
+ default:
+ ;
+ }
+
+ find_sw();
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// PUBLIC METHOD : cast
+//
+// Performs a destructive cast operation on a scfx_rep.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::cast(const scfx_params ¶ms, bool &q_flag, bool &o_flag)
+{
+ q_flag = false;
+ o_flag = false;
+
+ // check for special cases
+ if (is_zero()) {
+ if (is_neg())
+ m_sign = 1;
+ return;
+ }
+
+ // perform casting
+ quantization(params, q_flag);
+ overflow(params, o_flag);
+
+ // check for special case: -0
+ if (is_zero() && is_neg())
+ m_sign = 1;
+}
+
+
+// ----------------------------------------------------------------------------
+// make sure, the two mantissas are aligned
+// ----------------------------------------------------------------------------
+
+void
+align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp,
+ int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant)
+{
+ bool need_lhs = true;
+ bool need_rhs = true;
+
+ if (lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size()) {
+ int lower_bound_lhs = lhs.m_lsw - lhs.m_wp;
+ int upper_bound_lhs = lhs.m_msw - lhs.m_wp;
+ int lower_bound_rhs = rhs.m_lsw - rhs.m_wp;
+ int upper_bound_rhs = rhs.m_msw - rhs.m_wp;
+
+ int lower_bound = sc_min(lower_bound_lhs, lower_bound_rhs);
+ int upper_bound = sc_max(upper_bound_lhs, upper_bound_rhs);
+
+ new_wp = -lower_bound;
+ len_mant = sc_max(min_mant, upper_bound - lower_bound + 1);
+
+ if (new_wp != lhs.m_wp || len_mant != lhs.size()) {
+ lhs_mant = lhs.resize(len_mant, new_wp);
+ need_lhs = false;
+ }
+
+ if (new_wp != rhs.m_wp || len_mant != rhs.size()) {
+ rhs_mant = rhs.resize(len_mant, new_wp);
+ need_rhs = false;
+ }
+ }
+
+ if (need_lhs) {
+ lhs_mant = lhs.m_mant;
+ }
+
+ if (need_rhs) {
+ rhs_mant = rhs.m_mant;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// compare two mantissas
+// ----------------------------------------------------------------------------
+
+int
+compare_msw_ff(const scfx_rep &lhs, const scfx_rep &rhs)
+{
+ // special case: rhs.m_mant[rhs.m_msw + 1] == 1
+ if (rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0) {
+ return -1;
+ }
+
+ int lhs_size = lhs.m_msw - lhs.m_lsw + 1;
+ int rhs_size = rhs.m_msw - rhs.m_lsw + 1;
+
+ int size = sc_min(lhs_size, rhs_size);
+
+ int lhs_index = lhs.m_msw;
+ int rhs_index = rhs.m_msw;
+
+ int i;
+
+ for (i = 0;
+ i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index];
+ i++) {
+ lhs_index--;
+ rhs_index--;
+ }
+
+ if (i == size) {
+ if (lhs_size == rhs_size) {
+ return 0;
+ }
+
+ if (lhs_size < rhs_size) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ if (lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index]) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// divide the mantissa by ten
+// ----------------------------------------------------------------------------
+
+unsigned int
+scfx_rep::divide_by_ten()
+{
+#if defined(SC_BOOST_BIG_ENDIAN)
+ half_word *hw = (half_word *)&m_mant[m_msw];
+#elif defined(SC_BOOST_LITTLE_ENDIAN)
+ half_word *hw = ((half_word *)&m_mant[m_msw]) + 1;
+#endif
+
+ unsigned int remainder = 0;
+
+ word_short ls;
+ ls.l = 0;
+
+#if defined(SC_BOOST_BIG_ENDIAN)
+ for (int i = 0, end = (m_msw - m_wp + 1) * 2; i < end; i++) {
+#elif defined(SC_BOOST_LITTLE_ENDIAN)
+ for (int i = 0, end = -(m_msw - m_wp + 1) * 2; i > end; i--) {
+#endif
+ ls.s.u = static_cast<half_word>(remainder);
+ ls.s.l = hw[i];
+ remainder = ls.l % 10;
+ ls.l /= 10;
+ hw[i] = ls.s.l;
+ }
+
+ return remainder;
+}
+
+
+// ----------------------------------------------------------------------------
+// multiply the mantissa by ten
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::multiply_by_ten()
+{
+ int size = m_mant.size() + 1;
+
+ scfx_mant mant8(size);
+ scfx_mant mant2(size);
+
+ size--;
+
+ mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3));
+ mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1));
+
+ while (--size) {
+ mant8[size] = (m_mant[size] << 3) |
+ (m_mant[size - 1] >> (bits_in_word - 3));
+ mant2[size] = (m_mant[size] << 1) |
+ (m_mant[size - 1] >> (bits_in_word - 1));
+ }
+
+ mant8[0] = (m_mant[0] << 3);
+ mant2[0] = (m_mant[0] << 1);
+
+ add_mants(m_mant.size(), m_mant, mant8, mant2);
+}
+
+
+// ----------------------------------------------------------------------------
+// normalize
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::normalize(int exponent)
+{
+ int shift = exponent % bits_in_word;
+ if (shift < 0) {
+ shift += bits_in_word;
+ }
+
+ if (shift) {
+ shift_left(shift);
+ }
+
+ find_sw();
+
+ m_wp = (shift - exponent) / bits_in_word;
+}
+
+
+// ----------------------------------------------------------------------------
+// return a new mantissa that is aligned and resized
+// ----------------------------------------------------------------------------
+
+scfx_mant *
+scfx_rep::resize(int new_size, int new_wp) const
+{
+ scfx_mant *result = new scfx_mant(new_size);
+
+ result->clear();
+
+ int shift = new_wp - m_wp;
+
+ for (int j = m_lsw; j <= m_msw; j++) {
+ (*result)[j + shift] = m_mant[j];
+ }
+
+ return result;
+}
+
+
+// ----------------------------------------------------------------------------
+// set a single bit
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::set_bin(int i)
+{
+ m_mant[i >> 5] |= 1 << (i & 31);
+}
+
+
+// ----------------------------------------------------------------------------
+// set three bits
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::set_oct(int i, int n)
+{
+ if (n & 1) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+ i++;
+ if (n & 2) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+ i++;
+ if (n & 4) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// set four bits
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::set_hex(int i, int n)
+{
+ if (n & 1) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+ i++;
+ if (n & 2) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+ i++;
+ if (n & 4) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+ i++;
+ if (n & 8) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// PRIVATE METHOD : shift_left
+//
+// Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::shift_left(int n)
+{
+ if (n != 0) {
+ int shift_left = n;
+ int shift_right = bits_in_word - n;
+
+ SC_ASSERT_(!(m_mant[size() - 1] >> shift_right),
+ "shift_left overflow");
+
+ for (int i = size() - 1; i > 0; i--) {
+ m_mant[i] = (m_mant[i] << shift_left) |
+ (m_mant[i - 1] >> shift_right);
+ }
+ m_mant[0] <<= shift_left;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// PRIVATE METHOD : shift_right
+//
+// Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::shift_right(int n)
+{
+ if (n != 0) {
+ int shift_left = bits_in_word - n;
+ int shift_right = n;
+
+ SC_ASSERT_(!(m_mant[0] << shift_left), "shift_right overflow");
+
+ for (int i = 0; i < size() - 1; i++) {
+ m_mant[i] = (m_mant[i] >> shift_right) |
+ (m_mant[i + 1] << shift_left);
+ }
+ m_mant[size() - 1] >>= shift_right;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : get_bit
+//
+// Tests a bit, in two's complement.
+// ----------------------------------------------------------------------------
+
+bool
+scfx_rep::get_bit(int i) const
+{
+ if (!is_normal())
+ return false;
+
+ scfx_index x = calc_indices(i);
+
+ if (x.wi() >= size())
+ return is_neg();
+
+ if (x.wi() < 0)
+ return false;
+
+ const_cast<scfx_rep*>(this)->toggle_tc();
+
+ bool result = (m_mant[x.wi()] & (1 << x.bi())) != 0;
+
+ const_cast<scfx_rep *>(this)->toggle_tc();
+
+ return result;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : set
+//
+// Sets a bit, in two's complement, between iwl-1 and -fwl.
+// ----------------------------------------------------------------------------
+
+bool
+scfx_rep::set(int i, const scfx_params ¶ms)
+{
+ if (!is_normal())
+ return false;
+
+ scfx_index x = calc_indices(i);
+
+ if (x.wi() >= size()) {
+ if (is_neg())
+ return true;
+ else
+ resize_to(x.wi() + 1, 1);
+ } else if (x.wi() < 0) {
+ resize_to(size() - x.wi(), -1);
+ x.wi(0);
+ }
+
+ toggle_tc();
+
+ m_mant[x.wi()] |= 1 << x.bi();
+
+ if (i == params.iwl() - 1)
+ o_extend(x, params.enc()); // sign extension
+
+ toggle_tc();
+
+ find_sw();
+
+ return true;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : clear
+//
+// Clears a bit, in two's complement, between iwl-1 and -fwl.
+// ----------------------------------------------------------------------------
+
+bool
+scfx_rep::clear(int i, const scfx_params ¶ms)
+{
+ if (!is_normal())
+ return false;
+
+ scfx_index x = calc_indices(i);
+
+ if (x.wi() >= size()) {
+ if (!is_neg())
+ return true;
+ else
+ resize_to(x.wi() + 1, 1);
+ } else if (x.wi() < 0) {
+ return true;
+ }
+
+ toggle_tc();
+
+ m_mant[x.wi()] &= ~(1 << x.bi());
+
+ if (i == params.iwl() - 1)
+ o_extend(x, params.enc()); // sign extension
+
+ toggle_tc();
+
+ find_sw();
+
+ return true;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : get_slice
+// ----------------------------------------------------------------------------
+
+bool
+scfx_rep::get_slice(int i, int j, const scfx_params &, sc_bv_base &bv) const
+{
+ if (is_nan() || is_inf())
+ return false;
+
+ // get the bits
+
+ int l = j;
+ for (int k = 0; k < bv.length(); ++k) {
+ bv[k] = get_bit(l);
+
+ if (i >= j)
+ ++l;
+ else
+ --l;
+ }
+
+ return true;
+}
+
+bool
+scfx_rep::set_slice(int i, int j, const scfx_params ¶ms,
+ const sc_bv_base &bv)
+{
+ if (is_nan() || is_inf())
+ return false;
+
+ // set the bits
+ int l = j;
+ for (int k = 0; k < bv.length(); ++k) {
+ if (bv[k].to_bool())
+ set(l, params);
+ else
+ clear(l, params);
+
+ if (i >= j)
+ ++l;
+ else
+ --l;
+ }
+
+ return true;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : print
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::print(::std::ostream &os) const
+{
+ os << to_string(SC_DEC, -1, SC_E);
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : dump
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::dump(::std::ostream &os) const
+{
+ os << "scfx_rep" << ::std::endl;
+ os << "(" << ::std::endl;
+
+ os << "mant =" << ::std::endl;
+ for (int i = size() - 1; i >= 0; i--) {
+ char buf[BUFSIZ];
+ std::sprintf(buf, " %d: %10u (%8x)", i,
+ (int)m_mant[i], (int)m_mant[i]);
+ os << buf << ::std::endl;
+ }
+
+ os << "wp = " << m_wp << ::std::endl;
+ os << "sign = " << m_sign << ::std::endl;
+
+ os << "state = ";
+ switch (m_state) {
+ case normal:
+ os << "normal";
+ break;
+ case infinity:
+ os << "infinity";
+ break;
+ case not_a_number:
+ os << "not_a_number";
+ break;
+ default:
+ os << "unknown";
+ }
+ os << ::std::endl;
+
+ os << "msw = " << m_msw << ::std::endl;
+ os << "lsw = " << m_lsw << ::std::endl;
+
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : get_type
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::get_type(int &wl, int &iwl, sc_enc &enc) const
+{
+ if (is_nan() || is_inf()) {
+ wl = 0;
+ iwl = 0;
+ enc = SC_TC_;
+ return;
+ }
+
+ if (is_zero()) {
+ wl = 1;
+ iwl = 1;
+ enc = SC_US_;
+ return;
+ }
+
+ int msb = (m_msw - m_wp) * bits_in_word +
+ scfx_find_msb(m_mant[ m_msw ]) + 1;
+ while (get_bit(msb) == get_bit(msb - 1)) {
+ --msb;
+ }
+
+ int lsb = (m_lsw - m_wp) * bits_in_word +
+ scfx_find_lsb(m_mant[m_lsw]);
+
+ if (is_neg()) {
+ wl = msb - lsb + 1;
+ iwl = msb + 1;
+ enc = SC_TC_;
+ } else {
+ wl = msb - lsb;
+ iwl = msb;
+ enc = SC_US_;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// PRIVATE METHOD : round
+//
+// Performs convergent rounding (rounding to even) as in floating-point.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::round(int wl)
+{
+ // check for special cases
+
+ if (is_nan() || is_inf() || is_zero())
+ return;
+
+ // estimate effective wordlength and compare
+ int wl_effective;
+ wl_effective = (m_msw - m_lsw + 1) * bits_in_word;
+ if (wl_effective <= wl)
+ return;
+
+ // calculate effective wordlength and compare
+ int msb = scfx_find_msb(m_mant[m_msw]);
+ int lsb = scfx_find_lsb(m_mant[m_lsw]);
+ wl_effective = (m_msw * bits_in_word + msb) -
+ (m_lsw * bits_in_word + lsb) + 1;
+ if (wl_effective <= wl)
+ return;
+
+ // perform rounding
+ int wi = m_msw - (wl - 1) / bits_in_word;
+ int bi = msb - (wl - 1) % bits_in_word;
+ if (bi < 0) {
+ --wi;
+ bi += bits_in_word;
+ }
+
+ scfx_index x(wi, bi);
+
+ if ((q_bit(x) && ! q_zero(x)) || (q_bit(x) && q_zero(x) && q_odd(x))) {
+ q_incr(x);
+ }
+ q_clear(x);
+
+ find_sw();
+
+ m_r_flag = true;
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ scfx_utils.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: scfx_utils.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/scfx_utils.hh"
+
+namespace sc_dt
+{
+
+void
+scfx_tc2csd(scfx_string &s, int w_prefix)
+{
+ if (w_prefix != 0) {
+ SC_ASSERT_(s[0] == '0' && s[1] == 'c' &&
+ s[2] == 's' && s[3] == 'd', "invalid prefix");
+ }
+
+ scfx_string csd;
+
+ // copy bits from 's' into 'csd'; skip prefix, point, and exponent
+ int i = 0;
+ int j = (w_prefix != 0 ? 4 : 0);
+ while (s[j]) {
+ if (s[j] == '0' || s[j] == '1')
+ csd[i ++] = s[j];
+ else if (s[j] != '.')
+ break;
+ ++j;
+ }
+ csd[i] = '\0';
+
+ // convert 'csd' from two's complement to csd
+ --i;
+ while (i >= 0) {
+ if (csd[i] == '0') {
+ --i;
+ } else {
+ if (i > 0 && csd[i - 1] == '0') {
+ --i;
+ } else if (i == 0) {
+ csd[i--] = '-';
+ } else {
+ csd[i--] = '-';
+ while (i >= 0 && csd[i] == '1')
+ csd[i--] = '0';
+ if (i > 0)
+ csd[i] = '1';
+ else if (i == 0)
+ csd[i--] = '1';
+ }
+ }
+ }
+
+ // copy bits from 'csd' back into 's'
+ i = 0;
+ j = (w_prefix != 0 ? 4 : 0);
+ while (csd[i]) {
+ if (s[j] == '.')
+ ++j;
+ s[j++] = csd[i++];
+ }
+}
+
+
+void
+scfx_csd2tc(scfx_string &csd)
+{
+ SC_ASSERT_(csd[0] == '0' && csd[1] == 'c' &&
+ csd[2] == 's' && csd[3] == 'd', "invalid prefix");
+
+ scfx_string s;
+
+ // copy bits from 'csd' into 's'; skip prefix, point, and exponent
+ int i = 0;
+ s[i++] = '0';
+ int j = 4;
+ while (csd[j]) {
+ if (csd[j] == '-' || csd[j] == '0' || csd[j] == '1')
+ s[i++] = csd[j];
+ else if (csd[j] != '.')
+ break;
+ ++j;
+ }
+ s[i] = '\0';
+
+ // convert 's' from csd to two's complement
+ int len = i;
+ i = 1;
+ while (i < len) {
+ while (i < len && s[i] != '-')
+ i++;
+ if (i < len) {
+ j = i++;
+ s[j--] = '1';
+ while (j >= 0 && s[j] == '0')
+ s[j--] = '1';
+ if (j >= 0)
+ s[j] = '0';
+ }
+ }
+
+ // copy bits from 's' back into 'csd'
+ j = csd.length();
+ csd[j + 1] = '\0';
+ while (j > 4) {
+ csd[j] = csd[j - 1];
+ --j;
+ }
+
+ i = 0;
+ j = 4;
+ while (s[i]) {
+ if (csd[j] == '.')
+ ++j;
+ csd[j++] = s[i++];
+ }
+}
+
+} // namespace sc_dt
--- /dev/null
+# Copyright 2018 Google, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+Import('*')
+
+if env['USE_SYSTEMC']:
+ Source('sc_int_base.cc')
+ Source('sc_int_mask.cc')
+ Source('sc_length_param.cc')
+ Source('sc_nbexterns.cc')
+ Source('sc_nbutils.cc')
+ Source('sc_signed.cc')
+ Source('sc_uint_base.cc')
+ Source('sc_unsigned.cc')
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_int_base.cpp -- contains interface definitions between sc_int and
+ sc_signed, sc_unsigned, and definitions for sc_int_subref.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_int_base.cpp,v $
+// Revision 1.5 2011/02/18 20:19:14 acg
+// Andy Goodrich: updating Copyright notice.
+//
+// Revision 1.4 2010/02/04 22:23:29 acg
+// Andy Goodrich: fixed bug in concatenation reads for part selections,
+// the mask being used was 32 bits and should have been 64 bits.
+//
+// Revision 1.3 2008/06/19 17:47:56 acg
+// Andy Goodrich: fixes for bugs. See 2.2.1 RELEASENOTES.
+//
+// Revision 1.2 2007/11/04 21:27:00 acg
+// Andy Goodrich: changes to make sure the proper value is returned from
+// concat_get_data().
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:49:31 acg
+// Added $Log command so that CVS check in comments are reproduced in the
+// source.
+//
+
+#include <sstream>
+
+#include "systemc/ext/dt/bit/sc_bv_base.hh"
+#include "systemc/ext/dt/bit/sc_lv_base.hh"
+#include "systemc/ext/dt/fx/sc_fix.hh"
+#include "systemc/ext/dt/fx/scfx_other_defs.hh"
+#include "systemc/ext/dt/int/sc_int_base.hh"
+#include "systemc/ext/dt/int/sc_signed.hh"
+#include "systemc/ext/dt/int/sc_uint_base.hh"
+#include "systemc/ext/dt/int/sc_unsigned.hh"
+#include "systemc/ext/dt/misc/sc_concatref.hh"
+
+// explicit template instantiations
+namespace sc_core
+{
+
+template class sc_vpool<sc_dt::sc_int_bitref>;
+template class sc_vpool<sc_dt::sc_int_subref>;
+
+} // namespace sc_core
+
+namespace sc_dt
+{
+
+// to avoid code bloat in sc_int_concref<T1,T2>
+
+void
+sc_int_concref_invalid_length(int length)
+{
+ std::stringstream msg;
+ msg << "sc_int_concref<T1,T2> initialization: length = " << length <<
+ "violates 1 <= length <= " << SC_INTWIDTH;
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_int_bitref
+//
+// Proxy class for sc_int bit selection (r-value and l-value).
+// ----------------------------------------------------------------------------
+
+sc_core::sc_vpool<sc_int_bitref> sc_int_bitref::m_pool(9);
+
+// concatenation methods:
+
+// #### OPTIMIZE
+void sc_int_bitref::concat_set(int64 src, int low_i)
+{
+ sc_int_base aa(1);
+ *this = aa = (low_i < 64) ? src >> low_i : src >> 63;
+}
+
+void sc_int_bitref::concat_set(const sc_signed &src, int low_i)
+{
+ sc_int_base aa(1);
+ if (low_i < src.length())
+ *this = aa = 1 & (src >> low_i);
+ else
+ *this = aa = (src < 0) ? (int_type)-1 : 0;
+}
+
+void sc_int_bitref::concat_set(const sc_unsigned &src, int low_i)
+{
+ sc_int_base aa(1);
+ if (low_i < src.length())
+ *this = aa = 1 & (src >> low_i);
+ else
+ *this = aa = 0;
+}
+
+void sc_int_bitref::concat_set(uint64 src, int low_i)
+{
+ sc_int_base aa(1);
+ *this = aa = (low_i < 64) ? src >> low_i : 0;
+}
+
+
+// other methods
+void
+sc_int_bitref::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_int_subref_r
+//
+// Proxy class for sc_int part selection (l-value).
+// ----------------------------------------------------------------------------
+
+bool
+sc_int_subref_r::concat_get_ctrl(sc_digit *dst_p, int low_i) const
+{
+ int dst_i; // Word in dst_p now processing.
+ int end_i; // Highest order word in dst_p to process.
+ int high_i; // Index of high order bit in dst_p to set.
+ uint_type mask; // Mask for bits to extract or keep.
+
+ dst_i = low_i / BITS_PER_DIGIT;
+ high_i = low_i + (m_left - m_right);
+ end_i = high_i / BITS_PER_DIGIT;
+ mask = ~mask_int[m_left][m_right];
+
+ // PROCESS THE FIRST WORD:
+ dst_p[dst_i] = (sc_digit)(dst_p[dst_i] & mask);
+ switch (end_i - dst_i) {
+ // BITS ARE ACROSS TWO WORDS:
+ case 1:
+ dst_i++;
+ dst_p[dst_i] = 0;
+ break;
+
+ // BITS ARE ACROSS THREE WORDS:
+ case 2:
+ dst_i++;
+ dst_p[dst_i++] = 0;
+ dst_p[dst_i] = 0;
+ break;
+
+ // BITS ARE ACROSS FOUR WORDS:
+ case 3:
+ dst_i++;
+ dst_p[dst_i++] = 0;
+ dst_p[dst_i++] = 0;
+ dst_p[dst_i] = 0;
+ break;
+ }
+ return false;
+}
+
+bool
+sc_int_subref_r::concat_get_data(sc_digit *dst_p, int low_i) const
+{
+ int dst_i; // Word in dst_p now processing.
+ int end_i; // Highest order word in dst_p to process.
+ int high_i; // Index of high order bit in dst_p to set.
+ int left_shift; // Left shift for val.
+ uint_type mask; // Mask for bits to extract or keep.
+ bool non_zero; // True if value inserted is non-zero.
+ uint_type val; // Selection value extracted from m_obj_p.
+
+ dst_i = low_i / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+ high_i = low_i + (m_left-m_right);
+ end_i = high_i / BITS_PER_DIGIT;
+ mask = ~mask_int[m_left][m_right];
+ val = (m_obj_p->m_val & mask) >> m_right;
+ non_zero = val != 0;
+
+ // PROCESS THE FIRST WORD:
+ mask = ~(~UINT_ZERO << left_shift);
+ dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask) |
+ ((val << left_shift) & DIGIT_MASK));
+
+ switch (end_i - dst_i) {
+ // BITS ARE ACROSS TWO WORDS:
+ case 1:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT - left_shift);
+ dst_p[dst_i] = (sc_digit)(val & DIGIT_MASK);
+ break;
+
+ // BITS ARE ACROSS THREE WORDS:
+ case 2:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT - left_shift);
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+
+ // BITS ARE ACROSS FOUR WORDS:
+ case 3:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT - left_shift);
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+ }
+ return non_zero;
+}
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_int_subref
+//
+// Proxy class for sc_int part selection (r-value and l-value).
+// ----------------------------------------------------------------------------
+
+sc_core::sc_vpool<sc_int_subref> sc_int_subref::m_pool(9);
+
+// assignment operators
+
+sc_int_subref &
+sc_int_subref::operator = (int_type v)
+{
+ int_type val = m_obj_p->m_val;
+ uint_type mask = mask_int[m_left][m_right];
+ val &= mask;
+ val |= (v << m_right) & ~mask;
+ m_obj_p->m_val = val;
+ m_obj_p->extend_sign();
+ return *this;
+}
+
+sc_int_subref &
+sc_int_subref::operator = (const sc_signed &a)
+{
+ sc_int_base aa(length());
+ return (*this = aa = a);
+}
+
+sc_int_subref &
+sc_int_subref::operator = (const sc_unsigned &a)
+{
+ sc_int_base aa(length());
+ return (*this = aa = a);
+}
+
+sc_int_subref &
+sc_int_subref::operator = (const sc_bv_base &a)
+{
+ sc_int_base aa(length());
+ return (*this = aa = a);
+}
+
+sc_int_subref &
+sc_int_subref::operator = (const sc_lv_base &a)
+{
+ sc_int_base aa(length());
+ return (*this = aa = a);
+}
+
+
+// concatenation methods:
+// #### OPTIMIZE
+void
+sc_int_subref::concat_set(int64 src, int low_i)
+{
+ sc_int_base aa(length());
+ *this = aa = (low_i < 64) ? src >> low_i : src >> 63;
+}
+
+void
+sc_int_subref::concat_set(const sc_signed &src, int low_i)
+{
+ sc_int_base aa(length());
+ if (low_i < src.length())
+ *this = aa = src >> low_i;
+ else
+ *this = (src < 0) ? (int_type)-1 : 0;
+}
+
+void
+sc_int_subref::concat_set(const sc_unsigned &src, int low_i)
+{
+ sc_int_base aa(length());
+ if (low_i < src.length())
+ *this = aa = src >> low_i;
+ else
+ *this = 0;
+}
+
+void
+sc_int_subref::concat_set(uint64 src, int low_i)
+{
+ sc_int_base aa (length());
+ *this = aa = (low_i < 64) ? src >> low_i : 0;
+}
+
+
+// other methods
+void
+sc_int_subref::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_int_base
+//
+// Base class for sc_int.
+// ----------------------------------------------------------------------------
+
+// support methods
+void
+sc_int_base::invalid_length() const
+{
+ std::stringstream msg;
+ msg << "sc_int[_base] initialization: length = " << m_len <<
+ " violates 1 <= length <= " << SC_INTWIDTH;
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+void
+sc_int_base::invalid_index(int i) const
+{
+ std::stringstream msg;
+ msg << "sc_int[_base] bit selection: index = " << i <<
+ " violates 0 <= index <= " << (m_len - 1);
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+void
+sc_int_base::invalid_range(int l, int r) const
+{
+ std::stringstream msg;
+ msg << "sc_int[_base] part selection: " <<
+ "left = " << l << ", right = " << r << " violates " <<
+ (m_len-1) << " >= left >= right >= 0";
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+void
+sc_int_base::check_value() const
+{
+ int_type limit = (int_type)1 << (m_len - 1);
+ if (m_val < -limit || m_val >= limit) {
+ std::stringstream msg;
+ msg << "sc_int[_base]: value does not fit into a length of " << m_len;
+ SC_REPORT_WARNING("out of bounds", msg.str().c_str());
+ }
+}
+
+
+// constructors
+sc_int_base::sc_int_base(const sc_bv_base &v) :
+ m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = v;
+}
+sc_int_base::sc_int_base(const sc_lv_base &v) :
+ m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = v;
+}
+sc_int_base::sc_int_base(const sc_uint_subref_r &v) :
+ m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = v.to_uint64();
+}
+sc_int_base::sc_int_base(const sc_signed_subref_r &v) :
+ m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = v.to_uint64();
+}
+sc_int_base::sc_int_base(const sc_unsigned_subref_r &v) :
+ m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = v.to_uint64();
+}
+
+sc_int_base::sc_int_base(const sc_signed &a) :
+ m_val(0), m_len(a.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = a.to_int64();
+}
+
+sc_int_base::sc_int_base(const sc_unsigned &a) :
+ m_val(0), m_len(a.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = a.to_int64();
+}
+
+
+// assignment operators
+sc_int_base &
+sc_int_base::operator = (const sc_signed &a)
+{
+ int minlen = sc_min(m_len, a.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ set(i, a.test(i));
+ }
+ bool sgn = a.sign();
+ for (; i < m_len; ++i) {
+ // sign extension
+ set(i, sgn);
+ }
+ extend_sign();
+ return *this;
+}
+
+sc_int_base &
+sc_int_base::operator = (const sc_unsigned &a)
+{
+ int minlen = sc_min(m_len, a.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ set(i, a.test(i));
+ }
+ for (; i < m_len; ++i) {
+ // zero extension
+ set(i, 0);
+ }
+ extend_sign();
+ return *this;
+}
+
+
+sc_int_base &
+sc_int_base::operator = (const sc_bv_base &a)
+{
+ int minlen = sc_min(m_len, a.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ set(i, a.get_bit(i));
+ }
+ for (; i < m_len; ++i) {
+ // zero extension
+ set(i, 0);
+ }
+ extend_sign();
+ return *this;
+}
+
+sc_int_base &
+sc_int_base::operator = (const sc_lv_base &a)
+{
+ int minlen = sc_min(m_len, a.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ set(i, sc_logic(a.get_bit(i)).to_bool());
+ }
+ for (; i < m_len; ++i) {
+ // zero extension
+ set(i, 0);
+ }
+ extend_sign();
+ return *this;
+}
+
+sc_int_base &
+sc_int_base::operator = (const char *a)
+{
+ if (a == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is zero");
+ } else if (*a == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is empty");
+ } else try {
+ int len = m_len;
+ sc_fix aa(a, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return this->operator = (aa);
+ } catch(const sc_core::sc_report &) {
+ std::stringstream msg;
+ msg << "character string '" << a << "' is not valid";
+ SC_REPORT_ERROR("conversion failed", msg.str().c_str());
+ }
+ return *this;
+}
+
+// explicit conversion to character string
+const std::string
+sc_int_base::to_string(sc_numrep numrep) const
+{
+ int len = m_len;
+ sc_fix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return aa.to_string(numrep);
+}
+
+const std::string
+sc_int_base::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ int len = m_len;
+ sc_fix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return aa.to_string(numrep, w_prefix);
+}
+
+
+// reduce methods
+bool sc_int_base::and_reduce() const { return (m_val == int_type(-1)); }
+bool sc_int_base::or_reduce() const { return (m_val != int_type(0)); }
+
+bool
+sc_int_base::xor_reduce() const
+{
+ uint_type mask = ~UINT_ZERO;
+ uint_type val = m_val & (mask >> m_ulen);
+ int n = SC_INTWIDTH;
+ do {
+ n >>= 1;
+ mask >>= n;
+ val = ((val & (mask << n)) >> n) ^ (val & mask);
+ } while (n != 1);
+ return (val != uint_type(0));
+}
+
+bool
+sc_int_base::concat_get_ctrl(sc_digit *dst_p, int low_i) const
+{
+ int dst_i; // Word in dst_p now processing.
+ int end_i; // Highest order word in dst_p to process.
+ int left_shift; // Left shift for val.
+ uint_type mask; // Mask for bits to extract or keep.
+
+ dst_i = low_i / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+ end_i = (low_i + (m_len - 1)) / BITS_PER_DIGIT;
+
+ mask = ~(~UINT_ZERO << left_shift);
+ dst_p[dst_i] = (sc_digit)(dst_p[dst_i] & mask);
+ dst_i++;
+ for (; dst_i <= end_i; dst_i++)
+ dst_p[dst_i] = 0;
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+//"sc_int_base::concat_get_data"
+//
+// This method transfers the value of this object instance to the supplied
+// array of sc_unsigned digits starting with the bit specified by low_i within
+// the array of digits.
+//
+// Notes:
+// (1) we don't worry about masking the high order data we transfer since
+// concat_get_data() is called from low order bit to high order bit. So
+// the bits above where we place ours will be filled in by someone else.
+//
+// dst_p -> array of sc_unsigned digits to be filled in.
+// low_i = first bit within dst_p to be set.
+//-----------------------------------------------------------------------------
+bool
+sc_int_base::concat_get_data(sc_digit *dst_p, int low_i) const
+{
+ int dst_i; // Word in dst_p now processing.
+ int end_i; // Highest order word in dst_p to process.
+ int high_i; // Index of high order bit in dst_p to set.
+ int left_shift; // Left shift for val.
+ uint_type mask; // Mask for bits to extract or keep.
+ bool non_zero; // True if value inserted is non-zero.
+ uint_type val; // Value for this object.
+
+ dst_i = low_i / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+ high_i = low_i + (m_len - 1);
+ end_i = high_i / BITS_PER_DIGIT;
+ val = m_val;
+ non_zero = val != 0;
+
+ // MASK OFF DATA TO BE TRANSFERRED BASED ON WIDTH:
+ if (m_len < 64) {
+ mask = ~(~UINT_ZERO << m_len);
+ val &= mask;
+ }
+
+ // PROCESS THE FIRST WORD:
+ mask = (~UINT_ZERO << left_shift);
+ dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & ~mask) |
+ ((val <<left_shift) & DIGIT_MASK));
+ switch (end_i - dst_i) {
+ // BITS ARE ACROSS TWO WORDS:
+ case 1:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT - left_shift);
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+
+ // BITS ARE ACROSS THREE WORDS:
+ case 2:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT - left_shift);
+ dst_p[dst_i++] = ((sc_digit)val) & DIGIT_MASK;
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+
+ // BITS ARE ACROSS FOUR WORDS:
+ case 3:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT - left_shift);
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+ }
+ return non_zero;
+}
+
+// #### OPTIMIZE
+void
+sc_int_base::concat_set(int64 src, int low_i)
+{
+ *this = (low_i < 64) ? src >> low_i : src >> 63;
+}
+
+void
+sc_int_base::concat_set(const sc_signed &src, int low_i)
+{
+ if (low_i < src.length())
+ *this = src >> low_i;
+ else
+ *this = (src < 0) ? (int_type)-1 : 0;
+}
+
+void
+sc_int_base::concat_set(const sc_unsigned &src, int low_i)
+{
+ if (low_i < src.length())
+ *this = src >> low_i;
+ else
+ *this = 0;
+}
+
+void
+sc_int_base::concat_set(uint64 src, int low_i)
+{
+ *this = (low_i < 64) ? src >> low_i : 0;
+}
+
+// other methods
+void
+sc_int_base::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+} // namespace sc_dt;
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_int_mask.cpp -- Fills the mask_int lookup table to enable efficient
+ part-selection on sc_ints and sc_uints.
+
+ Original Author: Amit Rao, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc.
+ Description of Modification: - Resolved ambiguity with sc_(un)signed.
+ - Merged the code for 64- and 32-bit versions
+ via the constants in sc_nbdefs.h.
+ - Eliminated redundant file inclusions.
+
+ Name, Affiliation, Date: Philipp A Hartmann, Intel
+ Description of Modification: - drop specializations for Windows, 32-bit only
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+#include "systemc/ext/dt/int/sc_int_base.hh"
+#include "systemc/ext/dt/int/sc_uint_base.hh"
+
+#ifndef UINT64_C
+# define UINT64_C(v) v ## ULL
+#endif // UINT64_C
+
+namespace sc_dt {
+
+const uint_type mask_int[SC_INTWIDTH][SC_INTWIDTH] = {
+ {
+ UINT64_C(0xfffffffffffffffe)
+ },
+ {
+ UINT64_C(0xfffffffffffffffc),
+ UINT64_C(0xfffffffffffffffd)
+ },
+ {
+ UINT64_C(0xfffffffffffffff8),
+ UINT64_C(0xfffffffffffffff9),
+ UINT64_C(0xfffffffffffffffb)
+ },
+ {
+ UINT64_C(0xfffffffffffffff0),
+ UINT64_C(0xfffffffffffffff1),
+ UINT64_C(0xfffffffffffffff3),
+ UINT64_C(0xfffffffffffffff7)
+ },
+ {
+ UINT64_C(0xffffffffffffffe0),
+ UINT64_C(0xffffffffffffffe1),
+ UINT64_C(0xffffffffffffffe3),
+ UINT64_C(0xffffffffffffffe7),
+ UINT64_C(0xffffffffffffffef)
+ },
+ {
+ UINT64_C(0xffffffffffffffc0),
+ UINT64_C(0xffffffffffffffc1),
+ UINT64_C(0xffffffffffffffc3),
+ UINT64_C(0xffffffffffffffc7),
+ UINT64_C(0xffffffffffffffcf),
+ UINT64_C(0xffffffffffffffdf)
+ },
+ {
+ UINT64_C(0xffffffffffffff80),
+ UINT64_C(0xffffffffffffff81),
+ UINT64_C(0xffffffffffffff83),
+ UINT64_C(0xffffffffffffff87),
+ UINT64_C(0xffffffffffffff8f),
+ UINT64_C(0xffffffffffffff9f),
+ UINT64_C(0xffffffffffffffbf)
+ },
+ {
+ UINT64_C(0xffffffffffffff00),
+ UINT64_C(0xffffffffffffff01),
+ UINT64_C(0xffffffffffffff03),
+ UINT64_C(0xffffffffffffff07),
+ UINT64_C(0xffffffffffffff0f),
+ UINT64_C(0xffffffffffffff1f),
+ UINT64_C(0xffffffffffffff3f),
+ UINT64_C(0xffffffffffffff7f)
+ },
+ {
+ UINT64_C(0xfffffffffffffe00),
+ UINT64_C(0xfffffffffffffe01),
+ UINT64_C(0xfffffffffffffe03),
+ UINT64_C(0xfffffffffffffe07),
+ UINT64_C(0xfffffffffffffe0f),
+ UINT64_C(0xfffffffffffffe1f),
+ UINT64_C(0xfffffffffffffe3f),
+ UINT64_C(0xfffffffffffffe7f),
+ UINT64_C(0xfffffffffffffeff)
+ },
+ {
+ UINT64_C(0xfffffffffffffc00),
+ UINT64_C(0xfffffffffffffc01),
+ UINT64_C(0xfffffffffffffc03),
+ UINT64_C(0xfffffffffffffc07),
+ UINT64_C(0xfffffffffffffc0f),
+ UINT64_C(0xfffffffffffffc1f),
+ UINT64_C(0xfffffffffffffc3f),
+ UINT64_C(0xfffffffffffffc7f),
+ UINT64_C(0xfffffffffffffcff),
+ UINT64_C(0xfffffffffffffdff)
+ },
+ {
+ UINT64_C(0xfffffffffffff800),
+ UINT64_C(0xfffffffffffff801),
+ UINT64_C(0xfffffffffffff803),
+ UINT64_C(0xfffffffffffff807),
+ UINT64_C(0xfffffffffffff80f),
+ UINT64_C(0xfffffffffffff81f),
+ UINT64_C(0xfffffffffffff83f),
+ UINT64_C(0xfffffffffffff87f),
+ UINT64_C(0xfffffffffffff8ff),
+ UINT64_C(0xfffffffffffff9ff),
+ UINT64_C(0xfffffffffffffbff)
+ },
+ {
+ UINT64_C(0xfffffffffffff000),
+ UINT64_C(0xfffffffffffff001),
+ UINT64_C(0xfffffffffffff003),
+ UINT64_C(0xfffffffffffff007),
+ UINT64_C(0xfffffffffffff00f),
+ UINT64_C(0xfffffffffffff01f),
+ UINT64_C(0xfffffffffffff03f),
+ UINT64_C(0xfffffffffffff07f),
+ UINT64_C(0xfffffffffffff0ff),
+ UINT64_C(0xfffffffffffff1ff),
+ UINT64_C(0xfffffffffffff3ff),
+ UINT64_C(0xfffffffffffff7ff)
+ },
+ {
+ UINT64_C(0xffffffffffffe000),
+ UINT64_C(0xffffffffffffe001),
+ UINT64_C(0xffffffffffffe003),
+ UINT64_C(0xffffffffffffe007),
+ UINT64_C(0xffffffffffffe00f),
+ UINT64_C(0xffffffffffffe01f),
+ UINT64_C(0xffffffffffffe03f),
+ UINT64_C(0xffffffffffffe07f),
+ UINT64_C(0xffffffffffffe0ff),
+ UINT64_C(0xffffffffffffe1ff),
+ UINT64_C(0xffffffffffffe3ff),
+ UINT64_C(0xffffffffffffe7ff),
+ UINT64_C(0xffffffffffffefff)
+ },
+ {
+ UINT64_C(0xffffffffffffc000),
+ UINT64_C(0xffffffffffffc001),
+ UINT64_C(0xffffffffffffc003),
+ UINT64_C(0xffffffffffffc007),
+ UINT64_C(0xffffffffffffc00f),
+ UINT64_C(0xffffffffffffc01f),
+ UINT64_C(0xffffffffffffc03f),
+ UINT64_C(0xffffffffffffc07f),
+ UINT64_C(0xffffffffffffc0ff),
+ UINT64_C(0xffffffffffffc1ff),
+ UINT64_C(0xffffffffffffc3ff),
+ UINT64_C(0xffffffffffffc7ff),
+ UINT64_C(0xffffffffffffcfff),
+ UINT64_C(0xffffffffffffdfff)
+ },
+ {
+ UINT64_C(0xffffffffffff8000),
+ UINT64_C(0xffffffffffff8001),
+ UINT64_C(0xffffffffffff8003),
+ UINT64_C(0xffffffffffff8007),
+ UINT64_C(0xffffffffffff800f),
+ UINT64_C(0xffffffffffff801f),
+ UINT64_C(0xffffffffffff803f),
+ UINT64_C(0xffffffffffff807f),
+ UINT64_C(0xffffffffffff80ff),
+ UINT64_C(0xffffffffffff81ff),
+ UINT64_C(0xffffffffffff83ff),
+ UINT64_C(0xffffffffffff87ff),
+ UINT64_C(0xffffffffffff8fff),
+ UINT64_C(0xffffffffffff9fff),
+ UINT64_C(0xffffffffffffbfff)
+ },
+ {
+ UINT64_C(0xffffffffffff0000),
+ UINT64_C(0xffffffffffff0001),
+ UINT64_C(0xffffffffffff0003),
+ UINT64_C(0xffffffffffff0007),
+ UINT64_C(0xffffffffffff000f),
+ UINT64_C(0xffffffffffff001f),
+ UINT64_C(0xffffffffffff003f),
+ UINT64_C(0xffffffffffff007f),
+ UINT64_C(0xffffffffffff00ff),
+ UINT64_C(0xffffffffffff01ff),
+ UINT64_C(0xffffffffffff03ff),
+ UINT64_C(0xffffffffffff07ff),
+ UINT64_C(0xffffffffffff0fff),
+ UINT64_C(0xffffffffffff1fff),
+ UINT64_C(0xffffffffffff3fff),
+ UINT64_C(0xffffffffffff7fff)
+ },
+ {
+ UINT64_C(0xfffffffffffe0000),
+ UINT64_C(0xfffffffffffe0001),
+ UINT64_C(0xfffffffffffe0003),
+ UINT64_C(0xfffffffffffe0007),
+ UINT64_C(0xfffffffffffe000f),
+ UINT64_C(0xfffffffffffe001f),
+ UINT64_C(0xfffffffffffe003f),
+ UINT64_C(0xfffffffffffe007f),
+ UINT64_C(0xfffffffffffe00ff),
+ UINT64_C(0xfffffffffffe01ff),
+ UINT64_C(0xfffffffffffe03ff),
+ UINT64_C(0xfffffffffffe07ff),
+ UINT64_C(0xfffffffffffe0fff),
+ UINT64_C(0xfffffffffffe1fff),
+ UINT64_C(0xfffffffffffe3fff),
+ UINT64_C(0xfffffffffffe7fff),
+ UINT64_C(0xfffffffffffeffff)
+ },
+ {
+ UINT64_C(0xfffffffffffc0000),
+ UINT64_C(0xfffffffffffc0001),
+ UINT64_C(0xfffffffffffc0003),
+ UINT64_C(0xfffffffffffc0007),
+ UINT64_C(0xfffffffffffc000f),
+ UINT64_C(0xfffffffffffc001f),
+ UINT64_C(0xfffffffffffc003f),
+ UINT64_C(0xfffffffffffc007f),
+ UINT64_C(0xfffffffffffc00ff),
+ UINT64_C(0xfffffffffffc01ff),
+ UINT64_C(0xfffffffffffc03ff),
+ UINT64_C(0xfffffffffffc07ff),
+ UINT64_C(0xfffffffffffc0fff),
+ UINT64_C(0xfffffffffffc1fff),
+ UINT64_C(0xfffffffffffc3fff),
+ UINT64_C(0xfffffffffffc7fff),
+ UINT64_C(0xfffffffffffcffff),
+ UINT64_C(0xfffffffffffdffff)
+ },
+ {
+ UINT64_C(0xfffffffffff80000),
+ UINT64_C(0xfffffffffff80001),
+ UINT64_C(0xfffffffffff80003),
+ UINT64_C(0xfffffffffff80007),
+ UINT64_C(0xfffffffffff8000f),
+ UINT64_C(0xfffffffffff8001f),
+ UINT64_C(0xfffffffffff8003f),
+ UINT64_C(0xfffffffffff8007f),
+ UINT64_C(0xfffffffffff800ff),
+ UINT64_C(0xfffffffffff801ff),
+ UINT64_C(0xfffffffffff803ff),
+ UINT64_C(0xfffffffffff807ff),
+ UINT64_C(0xfffffffffff80fff),
+ UINT64_C(0xfffffffffff81fff),
+ UINT64_C(0xfffffffffff83fff),
+ UINT64_C(0xfffffffffff87fff),
+ UINT64_C(0xfffffffffff8ffff),
+ UINT64_C(0xfffffffffff9ffff),
+ UINT64_C(0xfffffffffffbffff)
+ },
+ {
+ UINT64_C(0xfffffffffff00000),
+ UINT64_C(0xfffffffffff00001),
+ UINT64_C(0xfffffffffff00003),
+ UINT64_C(0xfffffffffff00007),
+ UINT64_C(0xfffffffffff0000f),
+ UINT64_C(0xfffffffffff0001f),
+ UINT64_C(0xfffffffffff0003f),
+ UINT64_C(0xfffffffffff0007f),
+ UINT64_C(0xfffffffffff000ff),
+ UINT64_C(0xfffffffffff001ff),
+ UINT64_C(0xfffffffffff003ff),
+ UINT64_C(0xfffffffffff007ff),
+ UINT64_C(0xfffffffffff00fff),
+ UINT64_C(0xfffffffffff01fff),
+ UINT64_C(0xfffffffffff03fff),
+ UINT64_C(0xfffffffffff07fff),
+ UINT64_C(0xfffffffffff0ffff),
+ UINT64_C(0xfffffffffff1ffff),
+ UINT64_C(0xfffffffffff3ffff),
+ UINT64_C(0xfffffffffff7ffff)
+ },
+ {
+ UINT64_C(0xffffffffffe00000),
+ UINT64_C(0xffffffffffe00001),
+ UINT64_C(0xffffffffffe00003),
+ UINT64_C(0xffffffffffe00007),
+ UINT64_C(0xffffffffffe0000f),
+ UINT64_C(0xffffffffffe0001f),
+ UINT64_C(0xffffffffffe0003f),
+ UINT64_C(0xffffffffffe0007f),
+ UINT64_C(0xffffffffffe000ff),
+ UINT64_C(0xffffffffffe001ff),
+ UINT64_C(0xffffffffffe003ff),
+ UINT64_C(0xffffffffffe007ff),
+ UINT64_C(0xffffffffffe00fff),
+ UINT64_C(0xffffffffffe01fff),
+ UINT64_C(0xffffffffffe03fff),
+ UINT64_C(0xffffffffffe07fff),
+ UINT64_C(0xffffffffffe0ffff),
+ UINT64_C(0xffffffffffe1ffff),
+ UINT64_C(0xffffffffffe3ffff),
+ UINT64_C(0xffffffffffe7ffff),
+ UINT64_C(0xffffffffffefffff)
+ },
+ {
+ UINT64_C(0xffffffffffc00000),
+ UINT64_C(0xffffffffffc00001),
+ UINT64_C(0xffffffffffc00003),
+ UINT64_C(0xffffffffffc00007),
+ UINT64_C(0xffffffffffc0000f),
+ UINT64_C(0xffffffffffc0001f),
+ UINT64_C(0xffffffffffc0003f),
+ UINT64_C(0xffffffffffc0007f),
+ UINT64_C(0xffffffffffc000ff),
+ UINT64_C(0xffffffffffc001ff),
+ UINT64_C(0xffffffffffc003ff),
+ UINT64_C(0xffffffffffc007ff),
+ UINT64_C(0xffffffffffc00fff),
+ UINT64_C(0xffffffffffc01fff),
+ UINT64_C(0xffffffffffc03fff),
+ UINT64_C(0xffffffffffc07fff),
+ UINT64_C(0xffffffffffc0ffff),
+ UINT64_C(0xffffffffffc1ffff),
+ UINT64_C(0xffffffffffc3ffff),
+ UINT64_C(0xffffffffffc7ffff),
+ UINT64_C(0xffffffffffcfffff),
+ UINT64_C(0xffffffffffdfffff)
+ },
+ {
+ UINT64_C(0xffffffffff800000),
+ UINT64_C(0xffffffffff800001),
+ UINT64_C(0xffffffffff800003),
+ UINT64_C(0xffffffffff800007),
+ UINT64_C(0xffffffffff80000f),
+ UINT64_C(0xffffffffff80001f),
+ UINT64_C(0xffffffffff80003f),
+ UINT64_C(0xffffffffff80007f),
+ UINT64_C(0xffffffffff8000ff),
+ UINT64_C(0xffffffffff8001ff),
+ UINT64_C(0xffffffffff8003ff),
+ UINT64_C(0xffffffffff8007ff),
+ UINT64_C(0xffffffffff800fff),
+ UINT64_C(0xffffffffff801fff),
+ UINT64_C(0xffffffffff803fff),
+ UINT64_C(0xffffffffff807fff),
+ UINT64_C(0xffffffffff80ffff),
+ UINT64_C(0xffffffffff81ffff),
+ UINT64_C(0xffffffffff83ffff),
+ UINT64_C(0xffffffffff87ffff),
+ UINT64_C(0xffffffffff8fffff),
+ UINT64_C(0xffffffffff9fffff),
+ UINT64_C(0xffffffffffbfffff)
+ },
+ {
+ UINT64_C(0xffffffffff000000),
+ UINT64_C(0xffffffffff000001),
+ UINT64_C(0xffffffffff000003),
+ UINT64_C(0xffffffffff000007),
+ UINT64_C(0xffffffffff00000f),
+ UINT64_C(0xffffffffff00001f),
+ UINT64_C(0xffffffffff00003f),
+ UINT64_C(0xffffffffff00007f),
+ UINT64_C(0xffffffffff0000ff),
+ UINT64_C(0xffffffffff0001ff),
+ UINT64_C(0xffffffffff0003ff),
+ UINT64_C(0xffffffffff0007ff),
+ UINT64_C(0xffffffffff000fff),
+ UINT64_C(0xffffffffff001fff),
+ UINT64_C(0xffffffffff003fff),
+ UINT64_C(0xffffffffff007fff),
+ UINT64_C(0xffffffffff00ffff),
+ UINT64_C(0xffffffffff01ffff),
+ UINT64_C(0xffffffffff03ffff),
+ UINT64_C(0xffffffffff07ffff),
+ UINT64_C(0xffffffffff0fffff),
+ UINT64_C(0xffffffffff1fffff),
+ UINT64_C(0xffffffffff3fffff),
+ UINT64_C(0xffffffffff7fffff)
+ },
+ {
+ UINT64_C(0xfffffffffe000000),
+ UINT64_C(0xfffffffffe000001),
+ UINT64_C(0xfffffffffe000003),
+ UINT64_C(0xfffffffffe000007),
+ UINT64_C(0xfffffffffe00000f),
+ UINT64_C(0xfffffffffe00001f),
+ UINT64_C(0xfffffffffe00003f),
+ UINT64_C(0xfffffffffe00007f),
+ UINT64_C(0xfffffffffe0000ff),
+ UINT64_C(0xfffffffffe0001ff),
+ UINT64_C(0xfffffffffe0003ff),
+ UINT64_C(0xfffffffffe0007ff),
+ UINT64_C(0xfffffffffe000fff),
+ UINT64_C(0xfffffffffe001fff),
+ UINT64_C(0xfffffffffe003fff),
+ UINT64_C(0xfffffffffe007fff),
+ UINT64_C(0xfffffffffe00ffff),
+ UINT64_C(0xfffffffffe01ffff),
+ UINT64_C(0xfffffffffe03ffff),
+ UINT64_C(0xfffffffffe07ffff),
+ UINT64_C(0xfffffffffe0fffff),
+ UINT64_C(0xfffffffffe1fffff),
+ UINT64_C(0xfffffffffe3fffff),
+ UINT64_C(0xfffffffffe7fffff),
+ UINT64_C(0xfffffffffeffffff)
+ },
+ {
+ UINT64_C(0xfffffffffc000000),
+ UINT64_C(0xfffffffffc000001),
+ UINT64_C(0xfffffffffc000003),
+ UINT64_C(0xfffffffffc000007),
+ UINT64_C(0xfffffffffc00000f),
+ UINT64_C(0xfffffffffc00001f),
+ UINT64_C(0xfffffffffc00003f),
+ UINT64_C(0xfffffffffc00007f),
+ UINT64_C(0xfffffffffc0000ff),
+ UINT64_C(0xfffffffffc0001ff),
+ UINT64_C(0xfffffffffc0003ff),
+ UINT64_C(0xfffffffffc0007ff),
+ UINT64_C(0xfffffffffc000fff),
+ UINT64_C(0xfffffffffc001fff),
+ UINT64_C(0xfffffffffc003fff),
+ UINT64_C(0xfffffffffc007fff),
+ UINT64_C(0xfffffffffc00ffff),
+ UINT64_C(0xfffffffffc01ffff),
+ UINT64_C(0xfffffffffc03ffff),
+ UINT64_C(0xfffffffffc07ffff),
+ UINT64_C(0xfffffffffc0fffff),
+ UINT64_C(0xfffffffffc1fffff),
+ UINT64_C(0xfffffffffc3fffff),
+ UINT64_C(0xfffffffffc7fffff),
+ UINT64_C(0xfffffffffcffffff),
+ UINT64_C(0xfffffffffdffffff)
+ },
+ {
+ UINT64_C(0xfffffffff8000000),
+ UINT64_C(0xfffffffff8000001),
+ UINT64_C(0xfffffffff8000003),
+ UINT64_C(0xfffffffff8000007),
+ UINT64_C(0xfffffffff800000f),
+ UINT64_C(0xfffffffff800001f),
+ UINT64_C(0xfffffffff800003f),
+ UINT64_C(0xfffffffff800007f),
+ UINT64_C(0xfffffffff80000ff),
+ UINT64_C(0xfffffffff80001ff),
+ UINT64_C(0xfffffffff80003ff),
+ UINT64_C(0xfffffffff80007ff),
+ UINT64_C(0xfffffffff8000fff),
+ UINT64_C(0xfffffffff8001fff),
+ UINT64_C(0xfffffffff8003fff),
+ UINT64_C(0xfffffffff8007fff),
+ UINT64_C(0xfffffffff800ffff),
+ UINT64_C(0xfffffffff801ffff),
+ UINT64_C(0xfffffffff803ffff),
+ UINT64_C(0xfffffffff807ffff),
+ UINT64_C(0xfffffffff80fffff),
+ UINT64_C(0xfffffffff81fffff),
+ UINT64_C(0xfffffffff83fffff),
+ UINT64_C(0xfffffffff87fffff),
+ UINT64_C(0xfffffffff8ffffff),
+ UINT64_C(0xfffffffff9ffffff),
+ UINT64_C(0xfffffffffbffffff)
+ },
+ {
+ UINT64_C(0xfffffffff0000000),
+ UINT64_C(0xfffffffff0000001),
+ UINT64_C(0xfffffffff0000003),
+ UINT64_C(0xfffffffff0000007),
+ UINT64_C(0xfffffffff000000f),
+ UINT64_C(0xfffffffff000001f),
+ UINT64_C(0xfffffffff000003f),
+ UINT64_C(0xfffffffff000007f),
+ UINT64_C(0xfffffffff00000ff),
+ UINT64_C(0xfffffffff00001ff),
+ UINT64_C(0xfffffffff00003ff),
+ UINT64_C(0xfffffffff00007ff),
+ UINT64_C(0xfffffffff0000fff),
+ UINT64_C(0xfffffffff0001fff),
+ UINT64_C(0xfffffffff0003fff),
+ UINT64_C(0xfffffffff0007fff),
+ UINT64_C(0xfffffffff000ffff),
+ UINT64_C(0xfffffffff001ffff),
+ UINT64_C(0xfffffffff003ffff),
+ UINT64_C(0xfffffffff007ffff),
+ UINT64_C(0xfffffffff00fffff),
+ UINT64_C(0xfffffffff01fffff),
+ UINT64_C(0xfffffffff03fffff),
+ UINT64_C(0xfffffffff07fffff),
+ UINT64_C(0xfffffffff0ffffff),
+ UINT64_C(0xfffffffff1ffffff),
+ UINT64_C(0xfffffffff3ffffff),
+ UINT64_C(0xfffffffff7ffffff)
+ },
+ {
+ UINT64_C(0xffffffffe0000000),
+ UINT64_C(0xffffffffe0000001),
+ UINT64_C(0xffffffffe0000003),
+ UINT64_C(0xffffffffe0000007),
+ UINT64_C(0xffffffffe000000f),
+ UINT64_C(0xffffffffe000001f),
+ UINT64_C(0xffffffffe000003f),
+ UINT64_C(0xffffffffe000007f),
+ UINT64_C(0xffffffffe00000ff),
+ UINT64_C(0xffffffffe00001ff),
+ UINT64_C(0xffffffffe00003ff),
+ UINT64_C(0xffffffffe00007ff),
+ UINT64_C(0xffffffffe0000fff),
+ UINT64_C(0xffffffffe0001fff),
+ UINT64_C(0xffffffffe0003fff),
+ UINT64_C(0xffffffffe0007fff),
+ UINT64_C(0xffffffffe000ffff),
+ UINT64_C(0xffffffffe001ffff),
+ UINT64_C(0xffffffffe003ffff),
+ UINT64_C(0xffffffffe007ffff),
+ UINT64_C(0xffffffffe00fffff),
+ UINT64_C(0xffffffffe01fffff),
+ UINT64_C(0xffffffffe03fffff),
+ UINT64_C(0xffffffffe07fffff),
+ UINT64_C(0xffffffffe0ffffff),
+ UINT64_C(0xffffffffe1ffffff),
+ UINT64_C(0xffffffffe3ffffff),
+ UINT64_C(0xffffffffe7ffffff),
+ UINT64_C(0xffffffffefffffff)
+ },
+ {
+ UINT64_C(0xffffffffc0000000),
+ UINT64_C(0xffffffffc0000001),
+ UINT64_C(0xffffffffc0000003),
+ UINT64_C(0xffffffffc0000007),
+ UINT64_C(0xffffffffc000000f),
+ UINT64_C(0xffffffffc000001f),
+ UINT64_C(0xffffffffc000003f),
+ UINT64_C(0xffffffffc000007f),
+ UINT64_C(0xffffffffc00000ff),
+ UINT64_C(0xffffffffc00001ff),
+ UINT64_C(0xffffffffc00003ff),
+ UINT64_C(0xffffffffc00007ff),
+ UINT64_C(0xffffffffc0000fff),
+ UINT64_C(0xffffffffc0001fff),
+ UINT64_C(0xffffffffc0003fff),
+ UINT64_C(0xffffffffc0007fff),
+ UINT64_C(0xffffffffc000ffff),
+ UINT64_C(0xffffffffc001ffff),
+ UINT64_C(0xffffffffc003ffff),
+ UINT64_C(0xffffffffc007ffff),
+ UINT64_C(0xffffffffc00fffff),
+ UINT64_C(0xffffffffc01fffff),
+ UINT64_C(0xffffffffc03fffff),
+ UINT64_C(0xffffffffc07fffff),
+ UINT64_C(0xffffffffc0ffffff),
+ UINT64_C(0xffffffffc1ffffff),
+ UINT64_C(0xffffffffc3ffffff),
+ UINT64_C(0xffffffffc7ffffff),
+ UINT64_C(0xffffffffcfffffff),
+ UINT64_C(0xffffffffdfffffff)
+ },
+ {
+ UINT64_C(0xffffffff80000000),
+ UINT64_C(0xffffffff80000001),
+ UINT64_C(0xffffffff80000003),
+ UINT64_C(0xffffffff80000007),
+ UINT64_C(0xffffffff8000000f),
+ UINT64_C(0xffffffff8000001f),
+ UINT64_C(0xffffffff8000003f),
+ UINT64_C(0xffffffff8000007f),
+ UINT64_C(0xffffffff800000ff),
+ UINT64_C(0xffffffff800001ff),
+ UINT64_C(0xffffffff800003ff),
+ UINT64_C(0xffffffff800007ff),
+ UINT64_C(0xffffffff80000fff),
+ UINT64_C(0xffffffff80001fff),
+ UINT64_C(0xffffffff80003fff),
+ UINT64_C(0xffffffff80007fff),
+ UINT64_C(0xffffffff8000ffff),
+ UINT64_C(0xffffffff8001ffff),
+ UINT64_C(0xffffffff8003ffff),
+ UINT64_C(0xffffffff8007ffff),
+ UINT64_C(0xffffffff800fffff),
+ UINT64_C(0xffffffff801fffff),
+ UINT64_C(0xffffffff803fffff),
+ UINT64_C(0xffffffff807fffff),
+ UINT64_C(0xffffffff80ffffff),
+ UINT64_C(0xffffffff81ffffff),
+ UINT64_C(0xffffffff83ffffff),
+ UINT64_C(0xffffffff87ffffff),
+ UINT64_C(0xffffffff8fffffff),
+ UINT64_C(0xffffffff9fffffff),
+ UINT64_C(0xffffffffbfffffff)
+ },
+ {
+ UINT64_C(0xffffffff00000000),
+ UINT64_C(0xffffffff00000001),
+ UINT64_C(0xffffffff00000003),
+ UINT64_C(0xffffffff00000007),
+ UINT64_C(0xffffffff0000000f),
+ UINT64_C(0xffffffff0000001f),
+ UINT64_C(0xffffffff0000003f),
+ UINT64_C(0xffffffff0000007f),
+ UINT64_C(0xffffffff000000ff),
+ UINT64_C(0xffffffff000001ff),
+ UINT64_C(0xffffffff000003ff),
+ UINT64_C(0xffffffff000007ff),
+ UINT64_C(0xffffffff00000fff),
+ UINT64_C(0xffffffff00001fff),
+ UINT64_C(0xffffffff00003fff),
+ UINT64_C(0xffffffff00007fff),
+ UINT64_C(0xffffffff0000ffff),
+ UINT64_C(0xffffffff0001ffff),
+ UINT64_C(0xffffffff0003ffff),
+ UINT64_C(0xffffffff0007ffff),
+ UINT64_C(0xffffffff000fffff),
+ UINT64_C(0xffffffff001fffff),
+ UINT64_C(0xffffffff003fffff),
+ UINT64_C(0xffffffff007fffff),
+ UINT64_C(0xffffffff00ffffff),
+ UINT64_C(0xffffffff01ffffff),
+ UINT64_C(0xffffffff03ffffff),
+ UINT64_C(0xffffffff07ffffff),
+ UINT64_C(0xffffffff0fffffff),
+ UINT64_C(0xffffffff1fffffff),
+ UINT64_C(0xffffffff3fffffff),
+ UINT64_C(0xffffffff7fffffff)
+ },
+ {
+ UINT64_C(0xfffffffe00000000),
+ UINT64_C(0xfffffffe00000001),
+ UINT64_C(0xfffffffe00000003),
+ UINT64_C(0xfffffffe00000007),
+ UINT64_C(0xfffffffe0000000f),
+ UINT64_C(0xfffffffe0000001f),
+ UINT64_C(0xfffffffe0000003f),
+ UINT64_C(0xfffffffe0000007f),
+ UINT64_C(0xfffffffe000000ff),
+ UINT64_C(0xfffffffe000001ff),
+ UINT64_C(0xfffffffe000003ff),
+ UINT64_C(0xfffffffe000007ff),
+ UINT64_C(0xfffffffe00000fff),
+ UINT64_C(0xfffffffe00001fff),
+ UINT64_C(0xfffffffe00003fff),
+ UINT64_C(0xfffffffe00007fff),
+ UINT64_C(0xfffffffe0000ffff),
+ UINT64_C(0xfffffffe0001ffff),
+ UINT64_C(0xfffffffe0003ffff),
+ UINT64_C(0xfffffffe0007ffff),
+ UINT64_C(0xfffffffe000fffff),
+ UINT64_C(0xfffffffe001fffff),
+ UINT64_C(0xfffffffe003fffff),
+ UINT64_C(0xfffffffe007fffff),
+ UINT64_C(0xfffffffe00ffffff),
+ UINT64_C(0xfffffffe01ffffff),
+ UINT64_C(0xfffffffe03ffffff),
+ UINT64_C(0xfffffffe07ffffff),
+ UINT64_C(0xfffffffe0fffffff),
+ UINT64_C(0xfffffffe1fffffff),
+ UINT64_C(0xfffffffe3fffffff),
+ UINT64_C(0xfffffffe7fffffff),
+ UINT64_C(0xfffffffeffffffff)
+ },
+ {
+ UINT64_C(0xfffffffc00000000),
+ UINT64_C(0xfffffffc00000001),
+ UINT64_C(0xfffffffc00000003),
+ UINT64_C(0xfffffffc00000007),
+ UINT64_C(0xfffffffc0000000f),
+ UINT64_C(0xfffffffc0000001f),
+ UINT64_C(0xfffffffc0000003f),
+ UINT64_C(0xfffffffc0000007f),
+ UINT64_C(0xfffffffc000000ff),
+ UINT64_C(0xfffffffc000001ff),
+ UINT64_C(0xfffffffc000003ff),
+ UINT64_C(0xfffffffc000007ff),
+ UINT64_C(0xfffffffc00000fff),
+ UINT64_C(0xfffffffc00001fff),
+ UINT64_C(0xfffffffc00003fff),
+ UINT64_C(0xfffffffc00007fff),
+ UINT64_C(0xfffffffc0000ffff),
+ UINT64_C(0xfffffffc0001ffff),
+ UINT64_C(0xfffffffc0003ffff),
+ UINT64_C(0xfffffffc0007ffff),
+ UINT64_C(0xfffffffc000fffff),
+ UINT64_C(0xfffffffc001fffff),
+ UINT64_C(0xfffffffc003fffff),
+ UINT64_C(0xfffffffc007fffff),
+ UINT64_C(0xfffffffc00ffffff),
+ UINT64_C(0xfffffffc01ffffff),
+ UINT64_C(0xfffffffc03ffffff),
+ UINT64_C(0xfffffffc07ffffff),
+ UINT64_C(0xfffffffc0fffffff),
+ UINT64_C(0xfffffffc1fffffff),
+ UINT64_C(0xfffffffc3fffffff),
+ UINT64_C(0xfffffffc7fffffff),
+ UINT64_C(0xfffffffcffffffff),
+ UINT64_C(0xfffffffdffffffff)
+ },
+ {
+ UINT64_C(0xfffffff800000000),
+ UINT64_C(0xfffffff800000001),
+ UINT64_C(0xfffffff800000003),
+ UINT64_C(0xfffffff800000007),
+ UINT64_C(0xfffffff80000000f),
+ UINT64_C(0xfffffff80000001f),
+ UINT64_C(0xfffffff80000003f),
+ UINT64_C(0xfffffff80000007f),
+ UINT64_C(0xfffffff8000000ff),
+ UINT64_C(0xfffffff8000001ff),
+ UINT64_C(0xfffffff8000003ff),
+ UINT64_C(0xfffffff8000007ff),
+ UINT64_C(0xfffffff800000fff),
+ UINT64_C(0xfffffff800001fff),
+ UINT64_C(0xfffffff800003fff),
+ UINT64_C(0xfffffff800007fff),
+ UINT64_C(0xfffffff80000ffff),
+ UINT64_C(0xfffffff80001ffff),
+ UINT64_C(0xfffffff80003ffff),
+ UINT64_C(0xfffffff80007ffff),
+ UINT64_C(0xfffffff8000fffff),
+ UINT64_C(0xfffffff8001fffff),
+ UINT64_C(0xfffffff8003fffff),
+ UINT64_C(0xfffffff8007fffff),
+ UINT64_C(0xfffffff800ffffff),
+ UINT64_C(0xfffffff801ffffff),
+ UINT64_C(0xfffffff803ffffff),
+ UINT64_C(0xfffffff807ffffff),
+ UINT64_C(0xfffffff80fffffff),
+ UINT64_C(0xfffffff81fffffff),
+ UINT64_C(0xfffffff83fffffff),
+ UINT64_C(0xfffffff87fffffff),
+ UINT64_C(0xfffffff8ffffffff),
+ UINT64_C(0xfffffff9ffffffff),
+ UINT64_C(0xfffffffbffffffff)
+ },
+ {
+ UINT64_C(0xfffffff000000000),
+ UINT64_C(0xfffffff000000001),
+ UINT64_C(0xfffffff000000003),
+ UINT64_C(0xfffffff000000007),
+ UINT64_C(0xfffffff00000000f),
+ UINT64_C(0xfffffff00000001f),
+ UINT64_C(0xfffffff00000003f),
+ UINT64_C(0xfffffff00000007f),
+ UINT64_C(0xfffffff0000000ff),
+ UINT64_C(0xfffffff0000001ff),
+ UINT64_C(0xfffffff0000003ff),
+ UINT64_C(0xfffffff0000007ff),
+ UINT64_C(0xfffffff000000fff),
+ UINT64_C(0xfffffff000001fff),
+ UINT64_C(0xfffffff000003fff),
+ UINT64_C(0xfffffff000007fff),
+ UINT64_C(0xfffffff00000ffff),
+ UINT64_C(0xfffffff00001ffff),
+ UINT64_C(0xfffffff00003ffff),
+ UINT64_C(0xfffffff00007ffff),
+ UINT64_C(0xfffffff0000fffff),
+ UINT64_C(0xfffffff0001fffff),
+ UINT64_C(0xfffffff0003fffff),
+ UINT64_C(0xfffffff0007fffff),
+ UINT64_C(0xfffffff000ffffff),
+ UINT64_C(0xfffffff001ffffff),
+ UINT64_C(0xfffffff003ffffff),
+ UINT64_C(0xfffffff007ffffff),
+ UINT64_C(0xfffffff00fffffff),
+ UINT64_C(0xfffffff01fffffff),
+ UINT64_C(0xfffffff03fffffff),
+ UINT64_C(0xfffffff07fffffff),
+ UINT64_C(0xfffffff0ffffffff),
+ UINT64_C(0xfffffff1ffffffff),
+ UINT64_C(0xfffffff3ffffffff),
+ UINT64_C(0xfffffff7ffffffff)
+ },
+ {
+ UINT64_C(0xffffffe000000000),
+ UINT64_C(0xffffffe000000001),
+ UINT64_C(0xffffffe000000003),
+ UINT64_C(0xffffffe000000007),
+ UINT64_C(0xffffffe00000000f),
+ UINT64_C(0xffffffe00000001f),
+ UINT64_C(0xffffffe00000003f),
+ UINT64_C(0xffffffe00000007f),
+ UINT64_C(0xffffffe0000000ff),
+ UINT64_C(0xffffffe0000001ff),
+ UINT64_C(0xffffffe0000003ff),
+ UINT64_C(0xffffffe0000007ff),
+ UINT64_C(0xffffffe000000fff),
+ UINT64_C(0xffffffe000001fff),
+ UINT64_C(0xffffffe000003fff),
+ UINT64_C(0xffffffe000007fff),
+ UINT64_C(0xffffffe00000ffff),
+ UINT64_C(0xffffffe00001ffff),
+ UINT64_C(0xffffffe00003ffff),
+ UINT64_C(0xffffffe00007ffff),
+ UINT64_C(0xffffffe0000fffff),
+ UINT64_C(0xffffffe0001fffff),
+ UINT64_C(0xffffffe0003fffff),
+ UINT64_C(0xffffffe0007fffff),
+ UINT64_C(0xffffffe000ffffff),
+ UINT64_C(0xffffffe001ffffff),
+ UINT64_C(0xffffffe003ffffff),
+ UINT64_C(0xffffffe007ffffff),
+ UINT64_C(0xffffffe00fffffff),
+ UINT64_C(0xffffffe01fffffff),
+ UINT64_C(0xffffffe03fffffff),
+ UINT64_C(0xffffffe07fffffff),
+ UINT64_C(0xffffffe0ffffffff),
+ UINT64_C(0xffffffe1ffffffff),
+ UINT64_C(0xffffffe3ffffffff),
+ UINT64_C(0xffffffe7ffffffff),
+ UINT64_C(0xffffffefffffffff)
+ },
+ {
+ UINT64_C(0xffffffc000000000),
+ UINT64_C(0xffffffc000000001),
+ UINT64_C(0xffffffc000000003),
+ UINT64_C(0xffffffc000000007),
+ UINT64_C(0xffffffc00000000f),
+ UINT64_C(0xffffffc00000001f),
+ UINT64_C(0xffffffc00000003f),
+ UINT64_C(0xffffffc00000007f),
+ UINT64_C(0xffffffc0000000ff),
+ UINT64_C(0xffffffc0000001ff),
+ UINT64_C(0xffffffc0000003ff),
+ UINT64_C(0xffffffc0000007ff),
+ UINT64_C(0xffffffc000000fff),
+ UINT64_C(0xffffffc000001fff),
+ UINT64_C(0xffffffc000003fff),
+ UINT64_C(0xffffffc000007fff),
+ UINT64_C(0xffffffc00000ffff),
+ UINT64_C(0xffffffc00001ffff),
+ UINT64_C(0xffffffc00003ffff),
+ UINT64_C(0xffffffc00007ffff),
+ UINT64_C(0xffffffc0000fffff),
+ UINT64_C(0xffffffc0001fffff),
+ UINT64_C(0xffffffc0003fffff),
+ UINT64_C(0xffffffc0007fffff),
+ UINT64_C(0xffffffc000ffffff),
+ UINT64_C(0xffffffc001ffffff),
+ UINT64_C(0xffffffc003ffffff),
+ UINT64_C(0xffffffc007ffffff),
+ UINT64_C(0xffffffc00fffffff),
+ UINT64_C(0xffffffc01fffffff),
+ UINT64_C(0xffffffc03fffffff),
+ UINT64_C(0xffffffc07fffffff),
+ UINT64_C(0xffffffc0ffffffff),
+ UINT64_C(0xffffffc1ffffffff),
+ UINT64_C(0xffffffc3ffffffff),
+ UINT64_C(0xffffffc7ffffffff),
+ UINT64_C(0xffffffcfffffffff),
+ UINT64_C(0xffffffdfffffffff)
+ },
+ {
+ UINT64_C(0xffffff8000000000),
+ UINT64_C(0xffffff8000000001),
+ UINT64_C(0xffffff8000000003),
+ UINT64_C(0xffffff8000000007),
+ UINT64_C(0xffffff800000000f),
+ UINT64_C(0xffffff800000001f),
+ UINT64_C(0xffffff800000003f),
+ UINT64_C(0xffffff800000007f),
+ UINT64_C(0xffffff80000000ff),
+ UINT64_C(0xffffff80000001ff),
+ UINT64_C(0xffffff80000003ff),
+ UINT64_C(0xffffff80000007ff),
+ UINT64_C(0xffffff8000000fff),
+ UINT64_C(0xffffff8000001fff),
+ UINT64_C(0xffffff8000003fff),
+ UINT64_C(0xffffff8000007fff),
+ UINT64_C(0xffffff800000ffff),
+ UINT64_C(0xffffff800001ffff),
+ UINT64_C(0xffffff800003ffff),
+ UINT64_C(0xffffff800007ffff),
+ UINT64_C(0xffffff80000fffff),
+ UINT64_C(0xffffff80001fffff),
+ UINT64_C(0xffffff80003fffff),
+ UINT64_C(0xffffff80007fffff),
+ UINT64_C(0xffffff8000ffffff),
+ UINT64_C(0xffffff8001ffffff),
+ UINT64_C(0xffffff8003ffffff),
+ UINT64_C(0xffffff8007ffffff),
+ UINT64_C(0xffffff800fffffff),
+ UINT64_C(0xffffff801fffffff),
+ UINT64_C(0xffffff803fffffff),
+ UINT64_C(0xffffff807fffffff),
+ UINT64_C(0xffffff80ffffffff),
+ UINT64_C(0xffffff81ffffffff),
+ UINT64_C(0xffffff83ffffffff),
+ UINT64_C(0xffffff87ffffffff),
+ UINT64_C(0xffffff8fffffffff),
+ UINT64_C(0xffffff9fffffffff),
+ UINT64_C(0xffffffbfffffffff)
+ },
+ {
+ UINT64_C(0xffffff0000000000),
+ UINT64_C(0xffffff0000000001),
+ UINT64_C(0xffffff0000000003),
+ UINT64_C(0xffffff0000000007),
+ UINT64_C(0xffffff000000000f),
+ UINT64_C(0xffffff000000001f),
+ UINT64_C(0xffffff000000003f),
+ UINT64_C(0xffffff000000007f),
+ UINT64_C(0xffffff00000000ff),
+ UINT64_C(0xffffff00000001ff),
+ UINT64_C(0xffffff00000003ff),
+ UINT64_C(0xffffff00000007ff),
+ UINT64_C(0xffffff0000000fff),
+ UINT64_C(0xffffff0000001fff),
+ UINT64_C(0xffffff0000003fff),
+ UINT64_C(0xffffff0000007fff),
+ UINT64_C(0xffffff000000ffff),
+ UINT64_C(0xffffff000001ffff),
+ UINT64_C(0xffffff000003ffff),
+ UINT64_C(0xffffff000007ffff),
+ UINT64_C(0xffffff00000fffff),
+ UINT64_C(0xffffff00001fffff),
+ UINT64_C(0xffffff00003fffff),
+ UINT64_C(0xffffff00007fffff),
+ UINT64_C(0xffffff0000ffffff),
+ UINT64_C(0xffffff0001ffffff),
+ UINT64_C(0xffffff0003ffffff),
+ UINT64_C(0xffffff0007ffffff),
+ UINT64_C(0xffffff000fffffff),
+ UINT64_C(0xffffff001fffffff),
+ UINT64_C(0xffffff003fffffff),
+ UINT64_C(0xffffff007fffffff),
+ UINT64_C(0xffffff00ffffffff),
+ UINT64_C(0xffffff01ffffffff),
+ UINT64_C(0xffffff03ffffffff),
+ UINT64_C(0xffffff07ffffffff),
+ UINT64_C(0xffffff0fffffffff),
+ UINT64_C(0xffffff1fffffffff),
+ UINT64_C(0xffffff3fffffffff),
+ UINT64_C(0xffffff7fffffffff)
+ },
+ {
+ UINT64_C(0xfffffe0000000000),
+ UINT64_C(0xfffffe0000000001),
+ UINT64_C(0xfffffe0000000003),
+ UINT64_C(0xfffffe0000000007),
+ UINT64_C(0xfffffe000000000f),
+ UINT64_C(0xfffffe000000001f),
+ UINT64_C(0xfffffe000000003f),
+ UINT64_C(0xfffffe000000007f),
+ UINT64_C(0xfffffe00000000ff),
+ UINT64_C(0xfffffe00000001ff),
+ UINT64_C(0xfffffe00000003ff),
+ UINT64_C(0xfffffe00000007ff),
+ UINT64_C(0xfffffe0000000fff),
+ UINT64_C(0xfffffe0000001fff),
+ UINT64_C(0xfffffe0000003fff),
+ UINT64_C(0xfffffe0000007fff),
+ UINT64_C(0xfffffe000000ffff),
+ UINT64_C(0xfffffe000001ffff),
+ UINT64_C(0xfffffe000003ffff),
+ UINT64_C(0xfffffe000007ffff),
+ UINT64_C(0xfffffe00000fffff),
+ UINT64_C(0xfffffe00001fffff),
+ UINT64_C(0xfffffe00003fffff),
+ UINT64_C(0xfffffe00007fffff),
+ UINT64_C(0xfffffe0000ffffff),
+ UINT64_C(0xfffffe0001ffffff),
+ UINT64_C(0xfffffe0003ffffff),
+ UINT64_C(0xfffffe0007ffffff),
+ UINT64_C(0xfffffe000fffffff),
+ UINT64_C(0xfffffe001fffffff),
+ UINT64_C(0xfffffe003fffffff),
+ UINT64_C(0xfffffe007fffffff),
+ UINT64_C(0xfffffe00ffffffff),
+ UINT64_C(0xfffffe01ffffffff),
+ UINT64_C(0xfffffe03ffffffff),
+ UINT64_C(0xfffffe07ffffffff),
+ UINT64_C(0xfffffe0fffffffff),
+ UINT64_C(0xfffffe1fffffffff),
+ UINT64_C(0xfffffe3fffffffff),
+ UINT64_C(0xfffffe7fffffffff),
+ UINT64_C(0xfffffeffffffffff)
+ },
+ {
+ UINT64_C(0xfffffc0000000000),
+ UINT64_C(0xfffffc0000000001),
+ UINT64_C(0xfffffc0000000003),
+ UINT64_C(0xfffffc0000000007),
+ UINT64_C(0xfffffc000000000f),
+ UINT64_C(0xfffffc000000001f),
+ UINT64_C(0xfffffc000000003f),
+ UINT64_C(0xfffffc000000007f),
+ UINT64_C(0xfffffc00000000ff),
+ UINT64_C(0xfffffc00000001ff),
+ UINT64_C(0xfffffc00000003ff),
+ UINT64_C(0xfffffc00000007ff),
+ UINT64_C(0xfffffc0000000fff),
+ UINT64_C(0xfffffc0000001fff),
+ UINT64_C(0xfffffc0000003fff),
+ UINT64_C(0xfffffc0000007fff),
+ UINT64_C(0xfffffc000000ffff),
+ UINT64_C(0xfffffc000001ffff),
+ UINT64_C(0xfffffc000003ffff),
+ UINT64_C(0xfffffc000007ffff),
+ UINT64_C(0xfffffc00000fffff),
+ UINT64_C(0xfffffc00001fffff),
+ UINT64_C(0xfffffc00003fffff),
+ UINT64_C(0xfffffc00007fffff),
+ UINT64_C(0xfffffc0000ffffff),
+ UINT64_C(0xfffffc0001ffffff),
+ UINT64_C(0xfffffc0003ffffff),
+ UINT64_C(0xfffffc0007ffffff),
+ UINT64_C(0xfffffc000fffffff),
+ UINT64_C(0xfffffc001fffffff),
+ UINT64_C(0xfffffc003fffffff),
+ UINT64_C(0xfffffc007fffffff),
+ UINT64_C(0xfffffc00ffffffff),
+ UINT64_C(0xfffffc01ffffffff),
+ UINT64_C(0xfffffc03ffffffff),
+ UINT64_C(0xfffffc07ffffffff),
+ UINT64_C(0xfffffc0fffffffff),
+ UINT64_C(0xfffffc1fffffffff),
+ UINT64_C(0xfffffc3fffffffff),
+ UINT64_C(0xfffffc7fffffffff),
+ UINT64_C(0xfffffcffffffffff),
+ UINT64_C(0xfffffdffffffffff)
+ },
+ {
+ UINT64_C(0xfffff80000000000),
+ UINT64_C(0xfffff80000000001),
+ UINT64_C(0xfffff80000000003),
+ UINT64_C(0xfffff80000000007),
+ UINT64_C(0xfffff8000000000f),
+ UINT64_C(0xfffff8000000001f),
+ UINT64_C(0xfffff8000000003f),
+ UINT64_C(0xfffff8000000007f),
+ UINT64_C(0xfffff800000000ff),
+ UINT64_C(0xfffff800000001ff),
+ UINT64_C(0xfffff800000003ff),
+ UINT64_C(0xfffff800000007ff),
+ UINT64_C(0xfffff80000000fff),
+ UINT64_C(0xfffff80000001fff),
+ UINT64_C(0xfffff80000003fff),
+ UINT64_C(0xfffff80000007fff),
+ UINT64_C(0xfffff8000000ffff),
+ UINT64_C(0xfffff8000001ffff),
+ UINT64_C(0xfffff8000003ffff),
+ UINT64_C(0xfffff8000007ffff),
+ UINT64_C(0xfffff800000fffff),
+ UINT64_C(0xfffff800001fffff),
+ UINT64_C(0xfffff800003fffff),
+ UINT64_C(0xfffff800007fffff),
+ UINT64_C(0xfffff80000ffffff),
+ UINT64_C(0xfffff80001ffffff),
+ UINT64_C(0xfffff80003ffffff),
+ UINT64_C(0xfffff80007ffffff),
+ UINT64_C(0xfffff8000fffffff),
+ UINT64_C(0xfffff8001fffffff),
+ UINT64_C(0xfffff8003fffffff),
+ UINT64_C(0xfffff8007fffffff),
+ UINT64_C(0xfffff800ffffffff),
+ UINT64_C(0xfffff801ffffffff),
+ UINT64_C(0xfffff803ffffffff),
+ UINT64_C(0xfffff807ffffffff),
+ UINT64_C(0xfffff80fffffffff),
+ UINT64_C(0xfffff81fffffffff),
+ UINT64_C(0xfffff83fffffffff),
+ UINT64_C(0xfffff87fffffffff),
+ UINT64_C(0xfffff8ffffffffff),
+ UINT64_C(0xfffff9ffffffffff),
+ UINT64_C(0xfffffbffffffffff)
+ },
+ {
+ UINT64_C(0xfffff00000000000),
+ UINT64_C(0xfffff00000000001),
+ UINT64_C(0xfffff00000000003),
+ UINT64_C(0xfffff00000000007),
+ UINT64_C(0xfffff0000000000f),
+ UINT64_C(0xfffff0000000001f),
+ UINT64_C(0xfffff0000000003f),
+ UINT64_C(0xfffff0000000007f),
+ UINT64_C(0xfffff000000000ff),
+ UINT64_C(0xfffff000000001ff),
+ UINT64_C(0xfffff000000003ff),
+ UINT64_C(0xfffff000000007ff),
+ UINT64_C(0xfffff00000000fff),
+ UINT64_C(0xfffff00000001fff),
+ UINT64_C(0xfffff00000003fff),
+ UINT64_C(0xfffff00000007fff),
+ UINT64_C(0xfffff0000000ffff),
+ UINT64_C(0xfffff0000001ffff),
+ UINT64_C(0xfffff0000003ffff),
+ UINT64_C(0xfffff0000007ffff),
+ UINT64_C(0xfffff000000fffff),
+ UINT64_C(0xfffff000001fffff),
+ UINT64_C(0xfffff000003fffff),
+ UINT64_C(0xfffff000007fffff),
+ UINT64_C(0xfffff00000ffffff),
+ UINT64_C(0xfffff00001ffffff),
+ UINT64_C(0xfffff00003ffffff),
+ UINT64_C(0xfffff00007ffffff),
+ UINT64_C(0xfffff0000fffffff),
+ UINT64_C(0xfffff0001fffffff),
+ UINT64_C(0xfffff0003fffffff),
+ UINT64_C(0xfffff0007fffffff),
+ UINT64_C(0xfffff000ffffffff),
+ UINT64_C(0xfffff001ffffffff),
+ UINT64_C(0xfffff003ffffffff),
+ UINT64_C(0xfffff007ffffffff),
+ UINT64_C(0xfffff00fffffffff),
+ UINT64_C(0xfffff01fffffffff),
+ UINT64_C(0xfffff03fffffffff),
+ UINT64_C(0xfffff07fffffffff),
+ UINT64_C(0xfffff0ffffffffff),
+ UINT64_C(0xfffff1ffffffffff),
+ UINT64_C(0xfffff3ffffffffff),
+ UINT64_C(0xfffff7ffffffffff)
+ },
+ {
+ UINT64_C(0xffffe00000000000),
+ UINT64_C(0xffffe00000000001),
+ UINT64_C(0xffffe00000000003),
+ UINT64_C(0xffffe00000000007),
+ UINT64_C(0xffffe0000000000f),
+ UINT64_C(0xffffe0000000001f),
+ UINT64_C(0xffffe0000000003f),
+ UINT64_C(0xffffe0000000007f),
+ UINT64_C(0xffffe000000000ff),
+ UINT64_C(0xffffe000000001ff),
+ UINT64_C(0xffffe000000003ff),
+ UINT64_C(0xffffe000000007ff),
+ UINT64_C(0xffffe00000000fff),
+ UINT64_C(0xffffe00000001fff),
+ UINT64_C(0xffffe00000003fff),
+ UINT64_C(0xffffe00000007fff),
+ UINT64_C(0xffffe0000000ffff),
+ UINT64_C(0xffffe0000001ffff),
+ UINT64_C(0xffffe0000003ffff),
+ UINT64_C(0xffffe0000007ffff),
+ UINT64_C(0xffffe000000fffff),
+ UINT64_C(0xffffe000001fffff),
+ UINT64_C(0xffffe000003fffff),
+ UINT64_C(0xffffe000007fffff),
+ UINT64_C(0xffffe00000ffffff),
+ UINT64_C(0xffffe00001ffffff),
+ UINT64_C(0xffffe00003ffffff),
+ UINT64_C(0xffffe00007ffffff),
+ UINT64_C(0xffffe0000fffffff),
+ UINT64_C(0xffffe0001fffffff),
+ UINT64_C(0xffffe0003fffffff),
+ UINT64_C(0xffffe0007fffffff),
+ UINT64_C(0xffffe000ffffffff),
+ UINT64_C(0xffffe001ffffffff),
+ UINT64_C(0xffffe003ffffffff),
+ UINT64_C(0xffffe007ffffffff),
+ UINT64_C(0xffffe00fffffffff),
+ UINT64_C(0xffffe01fffffffff),
+ UINT64_C(0xffffe03fffffffff),
+ UINT64_C(0xffffe07fffffffff),
+ UINT64_C(0xffffe0ffffffffff),
+ UINT64_C(0xffffe1ffffffffff),
+ UINT64_C(0xffffe3ffffffffff),
+ UINT64_C(0xffffe7ffffffffff),
+ UINT64_C(0xffffefffffffffff)
+ },
+ {
+ UINT64_C(0xffffc00000000000),
+ UINT64_C(0xffffc00000000001),
+ UINT64_C(0xffffc00000000003),
+ UINT64_C(0xffffc00000000007),
+ UINT64_C(0xffffc0000000000f),
+ UINT64_C(0xffffc0000000001f),
+ UINT64_C(0xffffc0000000003f),
+ UINT64_C(0xffffc0000000007f),
+ UINT64_C(0xffffc000000000ff),
+ UINT64_C(0xffffc000000001ff),
+ UINT64_C(0xffffc000000003ff),
+ UINT64_C(0xffffc000000007ff),
+ UINT64_C(0xffffc00000000fff),
+ UINT64_C(0xffffc00000001fff),
+ UINT64_C(0xffffc00000003fff),
+ UINT64_C(0xffffc00000007fff),
+ UINT64_C(0xffffc0000000ffff),
+ UINT64_C(0xffffc0000001ffff),
+ UINT64_C(0xffffc0000003ffff),
+ UINT64_C(0xffffc0000007ffff),
+ UINT64_C(0xffffc000000fffff),
+ UINT64_C(0xffffc000001fffff),
+ UINT64_C(0xffffc000003fffff),
+ UINT64_C(0xffffc000007fffff),
+ UINT64_C(0xffffc00000ffffff),
+ UINT64_C(0xffffc00001ffffff),
+ UINT64_C(0xffffc00003ffffff),
+ UINT64_C(0xffffc00007ffffff),
+ UINT64_C(0xffffc0000fffffff),
+ UINT64_C(0xffffc0001fffffff),
+ UINT64_C(0xffffc0003fffffff),
+ UINT64_C(0xffffc0007fffffff),
+ UINT64_C(0xffffc000ffffffff),
+ UINT64_C(0xffffc001ffffffff),
+ UINT64_C(0xffffc003ffffffff),
+ UINT64_C(0xffffc007ffffffff),
+ UINT64_C(0xffffc00fffffffff),
+ UINT64_C(0xffffc01fffffffff),
+ UINT64_C(0xffffc03fffffffff),
+ UINT64_C(0xffffc07fffffffff),
+ UINT64_C(0xffffc0ffffffffff),
+ UINT64_C(0xffffc1ffffffffff),
+ UINT64_C(0xffffc3ffffffffff),
+ UINT64_C(0xffffc7ffffffffff),
+ UINT64_C(0xffffcfffffffffff),
+ UINT64_C(0xffffdfffffffffff)
+ },
+ {
+ UINT64_C(0xffff800000000000),
+ UINT64_C(0xffff800000000001),
+ UINT64_C(0xffff800000000003),
+ UINT64_C(0xffff800000000007),
+ UINT64_C(0xffff80000000000f),
+ UINT64_C(0xffff80000000001f),
+ UINT64_C(0xffff80000000003f),
+ UINT64_C(0xffff80000000007f),
+ UINT64_C(0xffff8000000000ff),
+ UINT64_C(0xffff8000000001ff),
+ UINT64_C(0xffff8000000003ff),
+ UINT64_C(0xffff8000000007ff),
+ UINT64_C(0xffff800000000fff),
+ UINT64_C(0xffff800000001fff),
+ UINT64_C(0xffff800000003fff),
+ UINT64_C(0xffff800000007fff),
+ UINT64_C(0xffff80000000ffff),
+ UINT64_C(0xffff80000001ffff),
+ UINT64_C(0xffff80000003ffff),
+ UINT64_C(0xffff80000007ffff),
+ UINT64_C(0xffff8000000fffff),
+ UINT64_C(0xffff8000001fffff),
+ UINT64_C(0xffff8000003fffff),
+ UINT64_C(0xffff8000007fffff),
+ UINT64_C(0xffff800000ffffff),
+ UINT64_C(0xffff800001ffffff),
+ UINT64_C(0xffff800003ffffff),
+ UINT64_C(0xffff800007ffffff),
+ UINT64_C(0xffff80000fffffff),
+ UINT64_C(0xffff80001fffffff),
+ UINT64_C(0xffff80003fffffff),
+ UINT64_C(0xffff80007fffffff),
+ UINT64_C(0xffff8000ffffffff),
+ UINT64_C(0xffff8001ffffffff),
+ UINT64_C(0xffff8003ffffffff),
+ UINT64_C(0xffff8007ffffffff),
+ UINT64_C(0xffff800fffffffff),
+ UINT64_C(0xffff801fffffffff),
+ UINT64_C(0xffff803fffffffff),
+ UINT64_C(0xffff807fffffffff),
+ UINT64_C(0xffff80ffffffffff),
+ UINT64_C(0xffff81ffffffffff),
+ UINT64_C(0xffff83ffffffffff),
+ UINT64_C(0xffff87ffffffffff),
+ UINT64_C(0xffff8fffffffffff),
+ UINT64_C(0xffff9fffffffffff),
+ UINT64_C(0xffffbfffffffffff)
+ },
+ {
+ UINT64_C(0xffff000000000000),
+ UINT64_C(0xffff000000000001),
+ UINT64_C(0xffff000000000003),
+ UINT64_C(0xffff000000000007),
+ UINT64_C(0xffff00000000000f),
+ UINT64_C(0xffff00000000001f),
+ UINT64_C(0xffff00000000003f),
+ UINT64_C(0xffff00000000007f),
+ UINT64_C(0xffff0000000000ff),
+ UINT64_C(0xffff0000000001ff),
+ UINT64_C(0xffff0000000003ff),
+ UINT64_C(0xffff0000000007ff),
+ UINT64_C(0xffff000000000fff),
+ UINT64_C(0xffff000000001fff),
+ UINT64_C(0xffff000000003fff),
+ UINT64_C(0xffff000000007fff),
+ UINT64_C(0xffff00000000ffff),
+ UINT64_C(0xffff00000001ffff),
+ UINT64_C(0xffff00000003ffff),
+ UINT64_C(0xffff00000007ffff),
+ UINT64_C(0xffff0000000fffff),
+ UINT64_C(0xffff0000001fffff),
+ UINT64_C(0xffff0000003fffff),
+ UINT64_C(0xffff0000007fffff),
+ UINT64_C(0xffff000000ffffff),
+ UINT64_C(0xffff000001ffffff),
+ UINT64_C(0xffff000003ffffff),
+ UINT64_C(0xffff000007ffffff),
+ UINT64_C(0xffff00000fffffff),
+ UINT64_C(0xffff00001fffffff),
+ UINT64_C(0xffff00003fffffff),
+ UINT64_C(0xffff00007fffffff),
+ UINT64_C(0xffff0000ffffffff),
+ UINT64_C(0xffff0001ffffffff),
+ UINT64_C(0xffff0003ffffffff),
+ UINT64_C(0xffff0007ffffffff),
+ UINT64_C(0xffff000fffffffff),
+ UINT64_C(0xffff001fffffffff),
+ UINT64_C(0xffff003fffffffff),
+ UINT64_C(0xffff007fffffffff),
+ UINT64_C(0xffff00ffffffffff),
+ UINT64_C(0xffff01ffffffffff),
+ UINT64_C(0xffff03ffffffffff),
+ UINT64_C(0xffff07ffffffffff),
+ UINT64_C(0xffff0fffffffffff),
+ UINT64_C(0xffff1fffffffffff),
+ UINT64_C(0xffff3fffffffffff),
+ UINT64_C(0xffff7fffffffffff)
+ },
+ {
+ UINT64_C(0xfffe000000000000),
+ UINT64_C(0xfffe000000000001),
+ UINT64_C(0xfffe000000000003),
+ UINT64_C(0xfffe000000000007),
+ UINT64_C(0xfffe00000000000f),
+ UINT64_C(0xfffe00000000001f),
+ UINT64_C(0xfffe00000000003f),
+ UINT64_C(0xfffe00000000007f),
+ UINT64_C(0xfffe0000000000ff),
+ UINT64_C(0xfffe0000000001ff),
+ UINT64_C(0xfffe0000000003ff),
+ UINT64_C(0xfffe0000000007ff),
+ UINT64_C(0xfffe000000000fff),
+ UINT64_C(0xfffe000000001fff),
+ UINT64_C(0xfffe000000003fff),
+ UINT64_C(0xfffe000000007fff),
+ UINT64_C(0xfffe00000000ffff),
+ UINT64_C(0xfffe00000001ffff),
+ UINT64_C(0xfffe00000003ffff),
+ UINT64_C(0xfffe00000007ffff),
+ UINT64_C(0xfffe0000000fffff),
+ UINT64_C(0xfffe0000001fffff),
+ UINT64_C(0xfffe0000003fffff),
+ UINT64_C(0xfffe0000007fffff),
+ UINT64_C(0xfffe000000ffffff),
+ UINT64_C(0xfffe000001ffffff),
+ UINT64_C(0xfffe000003ffffff),
+ UINT64_C(0xfffe000007ffffff),
+ UINT64_C(0xfffe00000fffffff),
+ UINT64_C(0xfffe00001fffffff),
+ UINT64_C(0xfffe00003fffffff),
+ UINT64_C(0xfffe00007fffffff),
+ UINT64_C(0xfffe0000ffffffff),
+ UINT64_C(0xfffe0001ffffffff),
+ UINT64_C(0xfffe0003ffffffff),
+ UINT64_C(0xfffe0007ffffffff),
+ UINT64_C(0xfffe000fffffffff),
+ UINT64_C(0xfffe001fffffffff),
+ UINT64_C(0xfffe003fffffffff),
+ UINT64_C(0xfffe007fffffffff),
+ UINT64_C(0xfffe00ffffffffff),
+ UINT64_C(0xfffe01ffffffffff),
+ UINT64_C(0xfffe03ffffffffff),
+ UINT64_C(0xfffe07ffffffffff),
+ UINT64_C(0xfffe0fffffffffff),
+ UINT64_C(0xfffe1fffffffffff),
+ UINT64_C(0xfffe3fffffffffff),
+ UINT64_C(0xfffe7fffffffffff),
+ UINT64_C(0xfffeffffffffffff)
+ },
+ {
+ UINT64_C(0xfffc000000000000),
+ UINT64_C(0xfffc000000000001),
+ UINT64_C(0xfffc000000000003),
+ UINT64_C(0xfffc000000000007),
+ UINT64_C(0xfffc00000000000f),
+ UINT64_C(0xfffc00000000001f),
+ UINT64_C(0xfffc00000000003f),
+ UINT64_C(0xfffc00000000007f),
+ UINT64_C(0xfffc0000000000ff),
+ UINT64_C(0xfffc0000000001ff),
+ UINT64_C(0xfffc0000000003ff),
+ UINT64_C(0xfffc0000000007ff),
+ UINT64_C(0xfffc000000000fff),
+ UINT64_C(0xfffc000000001fff),
+ UINT64_C(0xfffc000000003fff),
+ UINT64_C(0xfffc000000007fff),
+ UINT64_C(0xfffc00000000ffff),
+ UINT64_C(0xfffc00000001ffff),
+ UINT64_C(0xfffc00000003ffff),
+ UINT64_C(0xfffc00000007ffff),
+ UINT64_C(0xfffc0000000fffff),
+ UINT64_C(0xfffc0000001fffff),
+ UINT64_C(0xfffc0000003fffff),
+ UINT64_C(0xfffc0000007fffff),
+ UINT64_C(0xfffc000000ffffff),
+ UINT64_C(0xfffc000001ffffff),
+ UINT64_C(0xfffc000003ffffff),
+ UINT64_C(0xfffc000007ffffff),
+ UINT64_C(0xfffc00000fffffff),
+ UINT64_C(0xfffc00001fffffff),
+ UINT64_C(0xfffc00003fffffff),
+ UINT64_C(0xfffc00007fffffff),
+ UINT64_C(0xfffc0000ffffffff),
+ UINT64_C(0xfffc0001ffffffff),
+ UINT64_C(0xfffc0003ffffffff),
+ UINT64_C(0xfffc0007ffffffff),
+ UINT64_C(0xfffc000fffffffff),
+ UINT64_C(0xfffc001fffffffff),
+ UINT64_C(0xfffc003fffffffff),
+ UINT64_C(0xfffc007fffffffff),
+ UINT64_C(0xfffc00ffffffffff),
+ UINT64_C(0xfffc01ffffffffff),
+ UINT64_C(0xfffc03ffffffffff),
+ UINT64_C(0xfffc07ffffffffff),
+ UINT64_C(0xfffc0fffffffffff),
+ UINT64_C(0xfffc1fffffffffff),
+ UINT64_C(0xfffc3fffffffffff),
+ UINT64_C(0xfffc7fffffffffff),
+ UINT64_C(0xfffcffffffffffff),
+ UINT64_C(0xfffdffffffffffff)
+ },
+ {
+ UINT64_C(0xfff8000000000000),
+ UINT64_C(0xfff8000000000001),
+ UINT64_C(0xfff8000000000003),
+ UINT64_C(0xfff8000000000007),
+ UINT64_C(0xfff800000000000f),
+ UINT64_C(0xfff800000000001f),
+ UINT64_C(0xfff800000000003f),
+ UINT64_C(0xfff800000000007f),
+ UINT64_C(0xfff80000000000ff),
+ UINT64_C(0xfff80000000001ff),
+ UINT64_C(0xfff80000000003ff),
+ UINT64_C(0xfff80000000007ff),
+ UINT64_C(0xfff8000000000fff),
+ UINT64_C(0xfff8000000001fff),
+ UINT64_C(0xfff8000000003fff),
+ UINT64_C(0xfff8000000007fff),
+ UINT64_C(0xfff800000000ffff),
+ UINT64_C(0xfff800000001ffff),
+ UINT64_C(0xfff800000003ffff),
+ UINT64_C(0xfff800000007ffff),
+ UINT64_C(0xfff80000000fffff),
+ UINT64_C(0xfff80000001fffff),
+ UINT64_C(0xfff80000003fffff),
+ UINT64_C(0xfff80000007fffff),
+ UINT64_C(0xfff8000000ffffff),
+ UINT64_C(0xfff8000001ffffff),
+ UINT64_C(0xfff8000003ffffff),
+ UINT64_C(0xfff8000007ffffff),
+ UINT64_C(0xfff800000fffffff),
+ UINT64_C(0xfff800001fffffff),
+ UINT64_C(0xfff800003fffffff),
+ UINT64_C(0xfff800007fffffff),
+ UINT64_C(0xfff80000ffffffff),
+ UINT64_C(0xfff80001ffffffff),
+ UINT64_C(0xfff80003ffffffff),
+ UINT64_C(0xfff80007ffffffff),
+ UINT64_C(0xfff8000fffffffff),
+ UINT64_C(0xfff8001fffffffff),
+ UINT64_C(0xfff8003fffffffff),
+ UINT64_C(0xfff8007fffffffff),
+ UINT64_C(0xfff800ffffffffff),
+ UINT64_C(0xfff801ffffffffff),
+ UINT64_C(0xfff803ffffffffff),
+ UINT64_C(0xfff807ffffffffff),
+ UINT64_C(0xfff80fffffffffff),
+ UINT64_C(0xfff81fffffffffff),
+ UINT64_C(0xfff83fffffffffff),
+ UINT64_C(0xfff87fffffffffff),
+ UINT64_C(0xfff8ffffffffffff),
+ UINT64_C(0xfff9ffffffffffff),
+ UINT64_C(0xfffbffffffffffff)
+ },
+ {
+ UINT64_C(0xfff0000000000000),
+ UINT64_C(0xfff0000000000001),
+ UINT64_C(0xfff0000000000003),
+ UINT64_C(0xfff0000000000007),
+ UINT64_C(0xfff000000000000f),
+ UINT64_C(0xfff000000000001f),
+ UINT64_C(0xfff000000000003f),
+ UINT64_C(0xfff000000000007f),
+ UINT64_C(0xfff00000000000ff),
+ UINT64_C(0xfff00000000001ff),
+ UINT64_C(0xfff00000000003ff),
+ UINT64_C(0xfff00000000007ff),
+ UINT64_C(0xfff0000000000fff),
+ UINT64_C(0xfff0000000001fff),
+ UINT64_C(0xfff0000000003fff),
+ UINT64_C(0xfff0000000007fff),
+ UINT64_C(0xfff000000000ffff),
+ UINT64_C(0xfff000000001ffff),
+ UINT64_C(0xfff000000003ffff),
+ UINT64_C(0xfff000000007ffff),
+ UINT64_C(0xfff00000000fffff),
+ UINT64_C(0xfff00000001fffff),
+ UINT64_C(0xfff00000003fffff),
+ UINT64_C(0xfff00000007fffff),
+ UINT64_C(0xfff0000000ffffff),
+ UINT64_C(0xfff0000001ffffff),
+ UINT64_C(0xfff0000003ffffff),
+ UINT64_C(0xfff0000007ffffff),
+ UINT64_C(0xfff000000fffffff),
+ UINT64_C(0xfff000001fffffff),
+ UINT64_C(0xfff000003fffffff),
+ UINT64_C(0xfff000007fffffff),
+ UINT64_C(0xfff00000ffffffff),
+ UINT64_C(0xfff00001ffffffff),
+ UINT64_C(0xfff00003ffffffff),
+ UINT64_C(0xfff00007ffffffff),
+ UINT64_C(0xfff0000fffffffff),
+ UINT64_C(0xfff0001fffffffff),
+ UINT64_C(0xfff0003fffffffff),
+ UINT64_C(0xfff0007fffffffff),
+ UINT64_C(0xfff000ffffffffff),
+ UINT64_C(0xfff001ffffffffff),
+ UINT64_C(0xfff003ffffffffff),
+ UINT64_C(0xfff007ffffffffff),
+ UINT64_C(0xfff00fffffffffff),
+ UINT64_C(0xfff01fffffffffff),
+ UINT64_C(0xfff03fffffffffff),
+ UINT64_C(0xfff07fffffffffff),
+ UINT64_C(0xfff0ffffffffffff),
+ UINT64_C(0xfff1ffffffffffff),
+ UINT64_C(0xfff3ffffffffffff),
+ UINT64_C(0xfff7ffffffffffff)
+ },
+ {
+ UINT64_C(0xffe0000000000000),
+ UINT64_C(0xffe0000000000001),
+ UINT64_C(0xffe0000000000003),
+ UINT64_C(0xffe0000000000007),
+ UINT64_C(0xffe000000000000f),
+ UINT64_C(0xffe000000000001f),
+ UINT64_C(0xffe000000000003f),
+ UINT64_C(0xffe000000000007f),
+ UINT64_C(0xffe00000000000ff),
+ UINT64_C(0xffe00000000001ff),
+ UINT64_C(0xffe00000000003ff),
+ UINT64_C(0xffe00000000007ff),
+ UINT64_C(0xffe0000000000fff),
+ UINT64_C(0xffe0000000001fff),
+ UINT64_C(0xffe0000000003fff),
+ UINT64_C(0xffe0000000007fff),
+ UINT64_C(0xffe000000000ffff),
+ UINT64_C(0xffe000000001ffff),
+ UINT64_C(0xffe000000003ffff),
+ UINT64_C(0xffe000000007ffff),
+ UINT64_C(0xffe00000000fffff),
+ UINT64_C(0xffe00000001fffff),
+ UINT64_C(0xffe00000003fffff),
+ UINT64_C(0xffe00000007fffff),
+ UINT64_C(0xffe0000000ffffff),
+ UINT64_C(0xffe0000001ffffff),
+ UINT64_C(0xffe0000003ffffff),
+ UINT64_C(0xffe0000007ffffff),
+ UINT64_C(0xffe000000fffffff),
+ UINT64_C(0xffe000001fffffff),
+ UINT64_C(0xffe000003fffffff),
+ UINT64_C(0xffe000007fffffff),
+ UINT64_C(0xffe00000ffffffff),
+ UINT64_C(0xffe00001ffffffff),
+ UINT64_C(0xffe00003ffffffff),
+ UINT64_C(0xffe00007ffffffff),
+ UINT64_C(0xffe0000fffffffff),
+ UINT64_C(0xffe0001fffffffff),
+ UINT64_C(0xffe0003fffffffff),
+ UINT64_C(0xffe0007fffffffff),
+ UINT64_C(0xffe000ffffffffff),
+ UINT64_C(0xffe001ffffffffff),
+ UINT64_C(0xffe003ffffffffff),
+ UINT64_C(0xffe007ffffffffff),
+ UINT64_C(0xffe00fffffffffff),
+ UINT64_C(0xffe01fffffffffff),
+ UINT64_C(0xffe03fffffffffff),
+ UINT64_C(0xffe07fffffffffff),
+ UINT64_C(0xffe0ffffffffffff),
+ UINT64_C(0xffe1ffffffffffff),
+ UINT64_C(0xffe3ffffffffffff),
+ UINT64_C(0xffe7ffffffffffff),
+ UINT64_C(0xffefffffffffffff)
+ },
+ {
+ UINT64_C(0xffc0000000000000),
+ UINT64_C(0xffc0000000000001),
+ UINT64_C(0xffc0000000000003),
+ UINT64_C(0xffc0000000000007),
+ UINT64_C(0xffc000000000000f),
+ UINT64_C(0xffc000000000001f),
+ UINT64_C(0xffc000000000003f),
+ UINT64_C(0xffc000000000007f),
+ UINT64_C(0xffc00000000000ff),
+ UINT64_C(0xffc00000000001ff),
+ UINT64_C(0xffc00000000003ff),
+ UINT64_C(0xffc00000000007ff),
+ UINT64_C(0xffc0000000000fff),
+ UINT64_C(0xffc0000000001fff),
+ UINT64_C(0xffc0000000003fff),
+ UINT64_C(0xffc0000000007fff),
+ UINT64_C(0xffc000000000ffff),
+ UINT64_C(0xffc000000001ffff),
+ UINT64_C(0xffc000000003ffff),
+ UINT64_C(0xffc000000007ffff),
+ UINT64_C(0xffc00000000fffff),
+ UINT64_C(0xffc00000001fffff),
+ UINT64_C(0xffc00000003fffff),
+ UINT64_C(0xffc00000007fffff),
+ UINT64_C(0xffc0000000ffffff),
+ UINT64_C(0xffc0000001ffffff),
+ UINT64_C(0xffc0000003ffffff),
+ UINT64_C(0xffc0000007ffffff),
+ UINT64_C(0xffc000000fffffff),
+ UINT64_C(0xffc000001fffffff),
+ UINT64_C(0xffc000003fffffff),
+ UINT64_C(0xffc000007fffffff),
+ UINT64_C(0xffc00000ffffffff),
+ UINT64_C(0xffc00001ffffffff),
+ UINT64_C(0xffc00003ffffffff),
+ UINT64_C(0xffc00007ffffffff),
+ UINT64_C(0xffc0000fffffffff),
+ UINT64_C(0xffc0001fffffffff),
+ UINT64_C(0xffc0003fffffffff),
+ UINT64_C(0xffc0007fffffffff),
+ UINT64_C(0xffc000ffffffffff),
+ UINT64_C(0xffc001ffffffffff),
+ UINT64_C(0xffc003ffffffffff),
+ UINT64_C(0xffc007ffffffffff),
+ UINT64_C(0xffc00fffffffffff),
+ UINT64_C(0xffc01fffffffffff),
+ UINT64_C(0xffc03fffffffffff),
+ UINT64_C(0xffc07fffffffffff),
+ UINT64_C(0xffc0ffffffffffff),
+ UINT64_C(0xffc1ffffffffffff),
+ UINT64_C(0xffc3ffffffffffff),
+ UINT64_C(0xffc7ffffffffffff),
+ UINT64_C(0xffcfffffffffffff),
+ UINT64_C(0xffdfffffffffffff)
+ },
+ {
+ UINT64_C(0xff80000000000000),
+ UINT64_C(0xff80000000000001),
+ UINT64_C(0xff80000000000003),
+ UINT64_C(0xff80000000000007),
+ UINT64_C(0xff8000000000000f),
+ UINT64_C(0xff8000000000001f),
+ UINT64_C(0xff8000000000003f),
+ UINT64_C(0xff8000000000007f),
+ UINT64_C(0xff800000000000ff),
+ UINT64_C(0xff800000000001ff),
+ UINT64_C(0xff800000000003ff),
+ UINT64_C(0xff800000000007ff),
+ UINT64_C(0xff80000000000fff),
+ UINT64_C(0xff80000000001fff),
+ UINT64_C(0xff80000000003fff),
+ UINT64_C(0xff80000000007fff),
+ UINT64_C(0xff8000000000ffff),
+ UINT64_C(0xff8000000001ffff),
+ UINT64_C(0xff8000000003ffff),
+ UINT64_C(0xff8000000007ffff),
+ UINT64_C(0xff800000000fffff),
+ UINT64_C(0xff800000001fffff),
+ UINT64_C(0xff800000003fffff),
+ UINT64_C(0xff800000007fffff),
+ UINT64_C(0xff80000000ffffff),
+ UINT64_C(0xff80000001ffffff),
+ UINT64_C(0xff80000003ffffff),
+ UINT64_C(0xff80000007ffffff),
+ UINT64_C(0xff8000000fffffff),
+ UINT64_C(0xff8000001fffffff),
+ UINT64_C(0xff8000003fffffff),
+ UINT64_C(0xff8000007fffffff),
+ UINT64_C(0xff800000ffffffff),
+ UINT64_C(0xff800001ffffffff),
+ UINT64_C(0xff800003ffffffff),
+ UINT64_C(0xff800007ffffffff),
+ UINT64_C(0xff80000fffffffff),
+ UINT64_C(0xff80001fffffffff),
+ UINT64_C(0xff80003fffffffff),
+ UINT64_C(0xff80007fffffffff),
+ UINT64_C(0xff8000ffffffffff),
+ UINT64_C(0xff8001ffffffffff),
+ UINT64_C(0xff8003ffffffffff),
+ UINT64_C(0xff8007ffffffffff),
+ UINT64_C(0xff800fffffffffff),
+ UINT64_C(0xff801fffffffffff),
+ UINT64_C(0xff803fffffffffff),
+ UINT64_C(0xff807fffffffffff),
+ UINT64_C(0xff80ffffffffffff),
+ UINT64_C(0xff81ffffffffffff),
+ UINT64_C(0xff83ffffffffffff),
+ UINT64_C(0xff87ffffffffffff),
+ UINT64_C(0xff8fffffffffffff),
+ UINT64_C(0xff9fffffffffffff),
+ UINT64_C(0xffbfffffffffffff)
+ },
+ {
+ UINT64_C(0xff00000000000000),
+ UINT64_C(0xff00000000000001),
+ UINT64_C(0xff00000000000003),
+ UINT64_C(0xff00000000000007),
+ UINT64_C(0xff0000000000000f),
+ UINT64_C(0xff0000000000001f),
+ UINT64_C(0xff0000000000003f),
+ UINT64_C(0xff0000000000007f),
+ UINT64_C(0xff000000000000ff),
+ UINT64_C(0xff000000000001ff),
+ UINT64_C(0xff000000000003ff),
+ UINT64_C(0xff000000000007ff),
+ UINT64_C(0xff00000000000fff),
+ UINT64_C(0xff00000000001fff),
+ UINT64_C(0xff00000000003fff),
+ UINT64_C(0xff00000000007fff),
+ UINT64_C(0xff0000000000ffff),
+ UINT64_C(0xff0000000001ffff),
+ UINT64_C(0xff0000000003ffff),
+ UINT64_C(0xff0000000007ffff),
+ UINT64_C(0xff000000000fffff),
+ UINT64_C(0xff000000001fffff),
+ UINT64_C(0xff000000003fffff),
+ UINT64_C(0xff000000007fffff),
+ UINT64_C(0xff00000000ffffff),
+ UINT64_C(0xff00000001ffffff),
+ UINT64_C(0xff00000003ffffff),
+ UINT64_C(0xff00000007ffffff),
+ UINT64_C(0xff0000000fffffff),
+ UINT64_C(0xff0000001fffffff),
+ UINT64_C(0xff0000003fffffff),
+ UINT64_C(0xff0000007fffffff),
+ UINT64_C(0xff000000ffffffff),
+ UINT64_C(0xff000001ffffffff),
+ UINT64_C(0xff000003ffffffff),
+ UINT64_C(0xff000007ffffffff),
+ UINT64_C(0xff00000fffffffff),
+ UINT64_C(0xff00001fffffffff),
+ UINT64_C(0xff00003fffffffff),
+ UINT64_C(0xff00007fffffffff),
+ UINT64_C(0xff0000ffffffffff),
+ UINT64_C(0xff0001ffffffffff),
+ UINT64_C(0xff0003ffffffffff),
+ UINT64_C(0xff0007ffffffffff),
+ UINT64_C(0xff000fffffffffff),
+ UINT64_C(0xff001fffffffffff),
+ UINT64_C(0xff003fffffffffff),
+ UINT64_C(0xff007fffffffffff),
+ UINT64_C(0xff00ffffffffffff),
+ UINT64_C(0xff01ffffffffffff),
+ UINT64_C(0xff03ffffffffffff),
+ UINT64_C(0xff07ffffffffffff),
+ UINT64_C(0xff0fffffffffffff),
+ UINT64_C(0xff1fffffffffffff),
+ UINT64_C(0xff3fffffffffffff),
+ UINT64_C(0xff7fffffffffffff)
+ },
+ {
+ UINT64_C(0xfe00000000000000),
+ UINT64_C(0xfe00000000000001),
+ UINT64_C(0xfe00000000000003),
+ UINT64_C(0xfe00000000000007),
+ UINT64_C(0xfe0000000000000f),
+ UINT64_C(0xfe0000000000001f),
+ UINT64_C(0xfe0000000000003f),
+ UINT64_C(0xfe0000000000007f),
+ UINT64_C(0xfe000000000000ff),
+ UINT64_C(0xfe000000000001ff),
+ UINT64_C(0xfe000000000003ff),
+ UINT64_C(0xfe000000000007ff),
+ UINT64_C(0xfe00000000000fff),
+ UINT64_C(0xfe00000000001fff),
+ UINT64_C(0xfe00000000003fff),
+ UINT64_C(0xfe00000000007fff),
+ UINT64_C(0xfe0000000000ffff),
+ UINT64_C(0xfe0000000001ffff),
+ UINT64_C(0xfe0000000003ffff),
+ UINT64_C(0xfe0000000007ffff),
+ UINT64_C(0xfe000000000fffff),
+ UINT64_C(0xfe000000001fffff),
+ UINT64_C(0xfe000000003fffff),
+ UINT64_C(0xfe000000007fffff),
+ UINT64_C(0xfe00000000ffffff),
+ UINT64_C(0xfe00000001ffffff),
+ UINT64_C(0xfe00000003ffffff),
+ UINT64_C(0xfe00000007ffffff),
+ UINT64_C(0xfe0000000fffffff),
+ UINT64_C(0xfe0000001fffffff),
+ UINT64_C(0xfe0000003fffffff),
+ UINT64_C(0xfe0000007fffffff),
+ UINT64_C(0xfe000000ffffffff),
+ UINT64_C(0xfe000001ffffffff),
+ UINT64_C(0xfe000003ffffffff),
+ UINT64_C(0xfe000007ffffffff),
+ UINT64_C(0xfe00000fffffffff),
+ UINT64_C(0xfe00001fffffffff),
+ UINT64_C(0xfe00003fffffffff),
+ UINT64_C(0xfe00007fffffffff),
+ UINT64_C(0xfe0000ffffffffff),
+ UINT64_C(0xfe0001ffffffffff),
+ UINT64_C(0xfe0003ffffffffff),
+ UINT64_C(0xfe0007ffffffffff),
+ UINT64_C(0xfe000fffffffffff),
+ UINT64_C(0xfe001fffffffffff),
+ UINT64_C(0xfe003fffffffffff),
+ UINT64_C(0xfe007fffffffffff),
+ UINT64_C(0xfe00ffffffffffff),
+ UINT64_C(0xfe01ffffffffffff),
+ UINT64_C(0xfe03ffffffffffff),
+ UINT64_C(0xfe07ffffffffffff),
+ UINT64_C(0xfe0fffffffffffff),
+ UINT64_C(0xfe1fffffffffffff),
+ UINT64_C(0xfe3fffffffffffff),
+ UINT64_C(0xfe7fffffffffffff),
+ UINT64_C(0xfeffffffffffffff)
+ },
+ {
+ UINT64_C(0xfc00000000000000),
+ UINT64_C(0xfc00000000000001),
+ UINT64_C(0xfc00000000000003),
+ UINT64_C(0xfc00000000000007),
+ UINT64_C(0xfc0000000000000f),
+ UINT64_C(0xfc0000000000001f),
+ UINT64_C(0xfc0000000000003f),
+ UINT64_C(0xfc0000000000007f),
+ UINT64_C(0xfc000000000000ff),
+ UINT64_C(0xfc000000000001ff),
+ UINT64_C(0xfc000000000003ff),
+ UINT64_C(0xfc000000000007ff),
+ UINT64_C(0xfc00000000000fff),
+ UINT64_C(0xfc00000000001fff),
+ UINT64_C(0xfc00000000003fff),
+ UINT64_C(0xfc00000000007fff),
+ UINT64_C(0xfc0000000000ffff),
+ UINT64_C(0xfc0000000001ffff),
+ UINT64_C(0xfc0000000003ffff),
+ UINT64_C(0xfc0000000007ffff),
+ UINT64_C(0xfc000000000fffff),
+ UINT64_C(0xfc000000001fffff),
+ UINT64_C(0xfc000000003fffff),
+ UINT64_C(0xfc000000007fffff),
+ UINT64_C(0xfc00000000ffffff),
+ UINT64_C(0xfc00000001ffffff),
+ UINT64_C(0xfc00000003ffffff),
+ UINT64_C(0xfc00000007ffffff),
+ UINT64_C(0xfc0000000fffffff),
+ UINT64_C(0xfc0000001fffffff),
+ UINT64_C(0xfc0000003fffffff),
+ UINT64_C(0xfc0000007fffffff),
+ UINT64_C(0xfc000000ffffffff),
+ UINT64_C(0xfc000001ffffffff),
+ UINT64_C(0xfc000003ffffffff),
+ UINT64_C(0xfc000007ffffffff),
+ UINT64_C(0xfc00000fffffffff),
+ UINT64_C(0xfc00001fffffffff),
+ UINT64_C(0xfc00003fffffffff),
+ UINT64_C(0xfc00007fffffffff),
+ UINT64_C(0xfc0000ffffffffff),
+ UINT64_C(0xfc0001ffffffffff),
+ UINT64_C(0xfc0003ffffffffff),
+ UINT64_C(0xfc0007ffffffffff),
+ UINT64_C(0xfc000fffffffffff),
+ UINT64_C(0xfc001fffffffffff),
+ UINT64_C(0xfc003fffffffffff),
+ UINT64_C(0xfc007fffffffffff),
+ UINT64_C(0xfc00ffffffffffff),
+ UINT64_C(0xfc01ffffffffffff),
+ UINT64_C(0xfc03ffffffffffff),
+ UINT64_C(0xfc07ffffffffffff),
+ UINT64_C(0xfc0fffffffffffff),
+ UINT64_C(0xfc1fffffffffffff),
+ UINT64_C(0xfc3fffffffffffff),
+ UINT64_C(0xfc7fffffffffffff),
+ UINT64_C(0xfcffffffffffffff),
+ UINT64_C(0xfdffffffffffffff)
+ },
+ {
+ UINT64_C(0xf800000000000000),
+ UINT64_C(0xf800000000000001),
+ UINT64_C(0xf800000000000003),
+ UINT64_C(0xf800000000000007),
+ UINT64_C(0xf80000000000000f),
+ UINT64_C(0xf80000000000001f),
+ UINT64_C(0xf80000000000003f),
+ UINT64_C(0xf80000000000007f),
+ UINT64_C(0xf8000000000000ff),
+ UINT64_C(0xf8000000000001ff),
+ UINT64_C(0xf8000000000003ff),
+ UINT64_C(0xf8000000000007ff),
+ UINT64_C(0xf800000000000fff),
+ UINT64_C(0xf800000000001fff),
+ UINT64_C(0xf800000000003fff),
+ UINT64_C(0xf800000000007fff),
+ UINT64_C(0xf80000000000ffff),
+ UINT64_C(0xf80000000001ffff),
+ UINT64_C(0xf80000000003ffff),
+ UINT64_C(0xf80000000007ffff),
+ UINT64_C(0xf8000000000fffff),
+ UINT64_C(0xf8000000001fffff),
+ UINT64_C(0xf8000000003fffff),
+ UINT64_C(0xf8000000007fffff),
+ UINT64_C(0xf800000000ffffff),
+ UINT64_C(0xf800000001ffffff),
+ UINT64_C(0xf800000003ffffff),
+ UINT64_C(0xf800000007ffffff),
+ UINT64_C(0xf80000000fffffff),
+ UINT64_C(0xf80000001fffffff),
+ UINT64_C(0xf80000003fffffff),
+ UINT64_C(0xf80000007fffffff),
+ UINT64_C(0xf8000000ffffffff),
+ UINT64_C(0xf8000001ffffffff),
+ UINT64_C(0xf8000003ffffffff),
+ UINT64_C(0xf8000007ffffffff),
+ UINT64_C(0xf800000fffffffff),
+ UINT64_C(0xf800001fffffffff),
+ UINT64_C(0xf800003fffffffff),
+ UINT64_C(0xf800007fffffffff),
+ UINT64_C(0xf80000ffffffffff),
+ UINT64_C(0xf80001ffffffffff),
+ UINT64_C(0xf80003ffffffffff),
+ UINT64_C(0xf80007ffffffffff),
+ UINT64_C(0xf8000fffffffffff),
+ UINT64_C(0xf8001fffffffffff),
+ UINT64_C(0xf8003fffffffffff),
+ UINT64_C(0xf8007fffffffffff),
+ UINT64_C(0xf800ffffffffffff),
+ UINT64_C(0xf801ffffffffffff),
+ UINT64_C(0xf803ffffffffffff),
+ UINT64_C(0xf807ffffffffffff),
+ UINT64_C(0xf80fffffffffffff),
+ UINT64_C(0xf81fffffffffffff),
+ UINT64_C(0xf83fffffffffffff),
+ UINT64_C(0xf87fffffffffffff),
+ UINT64_C(0xf8ffffffffffffff),
+ UINT64_C(0xf9ffffffffffffff),
+ UINT64_C(0xfbffffffffffffff)
+ },
+ {
+ UINT64_C(0xf000000000000000),
+ UINT64_C(0xf000000000000001),
+ UINT64_C(0xf000000000000003),
+ UINT64_C(0xf000000000000007),
+ UINT64_C(0xf00000000000000f),
+ UINT64_C(0xf00000000000001f),
+ UINT64_C(0xf00000000000003f),
+ UINT64_C(0xf00000000000007f),
+ UINT64_C(0xf0000000000000ff),
+ UINT64_C(0xf0000000000001ff),
+ UINT64_C(0xf0000000000003ff),
+ UINT64_C(0xf0000000000007ff),
+ UINT64_C(0xf000000000000fff),
+ UINT64_C(0xf000000000001fff),
+ UINT64_C(0xf000000000003fff),
+ UINT64_C(0xf000000000007fff),
+ UINT64_C(0xf00000000000ffff),
+ UINT64_C(0xf00000000001ffff),
+ UINT64_C(0xf00000000003ffff),
+ UINT64_C(0xf00000000007ffff),
+ UINT64_C(0xf0000000000fffff),
+ UINT64_C(0xf0000000001fffff),
+ UINT64_C(0xf0000000003fffff),
+ UINT64_C(0xf0000000007fffff),
+ UINT64_C(0xf000000000ffffff),
+ UINT64_C(0xf000000001ffffff),
+ UINT64_C(0xf000000003ffffff),
+ UINT64_C(0xf000000007ffffff),
+ UINT64_C(0xf00000000fffffff),
+ UINT64_C(0xf00000001fffffff),
+ UINT64_C(0xf00000003fffffff),
+ UINT64_C(0xf00000007fffffff),
+ UINT64_C(0xf0000000ffffffff),
+ UINT64_C(0xf0000001ffffffff),
+ UINT64_C(0xf0000003ffffffff),
+ UINT64_C(0xf0000007ffffffff),
+ UINT64_C(0xf000000fffffffff),
+ UINT64_C(0xf000001fffffffff),
+ UINT64_C(0xf000003fffffffff),
+ UINT64_C(0xf000007fffffffff),
+ UINT64_C(0xf00000ffffffffff),
+ UINT64_C(0xf00001ffffffffff),
+ UINT64_C(0xf00003ffffffffff),
+ UINT64_C(0xf00007ffffffffff),
+ UINT64_C(0xf0000fffffffffff),
+ UINT64_C(0xf0001fffffffffff),
+ UINT64_C(0xf0003fffffffffff),
+ UINT64_C(0xf0007fffffffffff),
+ UINT64_C(0xf000ffffffffffff),
+ UINT64_C(0xf001ffffffffffff),
+ UINT64_C(0xf003ffffffffffff),
+ UINT64_C(0xf007ffffffffffff),
+ UINT64_C(0xf00fffffffffffff),
+ UINT64_C(0xf01fffffffffffff),
+ UINT64_C(0xf03fffffffffffff),
+ UINT64_C(0xf07fffffffffffff),
+ UINT64_C(0xf0ffffffffffffff),
+ UINT64_C(0xf1ffffffffffffff),
+ UINT64_C(0xf3ffffffffffffff),
+ UINT64_C(0xf7ffffffffffffff)
+ },
+ {
+ UINT64_C(0xe000000000000000),
+ UINT64_C(0xe000000000000001),
+ UINT64_C(0xe000000000000003),
+ UINT64_C(0xe000000000000007),
+ UINT64_C(0xe00000000000000f),
+ UINT64_C(0xe00000000000001f),
+ UINT64_C(0xe00000000000003f),
+ UINT64_C(0xe00000000000007f),
+ UINT64_C(0xe0000000000000ff),
+ UINT64_C(0xe0000000000001ff),
+ UINT64_C(0xe0000000000003ff),
+ UINT64_C(0xe0000000000007ff),
+ UINT64_C(0xe000000000000fff),
+ UINT64_C(0xe000000000001fff),
+ UINT64_C(0xe000000000003fff),
+ UINT64_C(0xe000000000007fff),
+ UINT64_C(0xe00000000000ffff),
+ UINT64_C(0xe00000000001ffff),
+ UINT64_C(0xe00000000003ffff),
+ UINT64_C(0xe00000000007ffff),
+ UINT64_C(0xe0000000000fffff),
+ UINT64_C(0xe0000000001fffff),
+ UINT64_C(0xe0000000003fffff),
+ UINT64_C(0xe0000000007fffff),
+ UINT64_C(0xe000000000ffffff),
+ UINT64_C(0xe000000001ffffff),
+ UINT64_C(0xe000000003ffffff),
+ UINT64_C(0xe000000007ffffff),
+ UINT64_C(0xe00000000fffffff),
+ UINT64_C(0xe00000001fffffff),
+ UINT64_C(0xe00000003fffffff),
+ UINT64_C(0xe00000007fffffff),
+ UINT64_C(0xe0000000ffffffff),
+ UINT64_C(0xe0000001ffffffff),
+ UINT64_C(0xe0000003ffffffff),
+ UINT64_C(0xe0000007ffffffff),
+ UINT64_C(0xe000000fffffffff),
+ UINT64_C(0xe000001fffffffff),
+ UINT64_C(0xe000003fffffffff),
+ UINT64_C(0xe000007fffffffff),
+ UINT64_C(0xe00000ffffffffff),
+ UINT64_C(0xe00001ffffffffff),
+ UINT64_C(0xe00003ffffffffff),
+ UINT64_C(0xe00007ffffffffff),
+ UINT64_C(0xe0000fffffffffff),
+ UINT64_C(0xe0001fffffffffff),
+ UINT64_C(0xe0003fffffffffff),
+ UINT64_C(0xe0007fffffffffff),
+ UINT64_C(0xe000ffffffffffff),
+ UINT64_C(0xe001ffffffffffff),
+ UINT64_C(0xe003ffffffffffff),
+ UINT64_C(0xe007ffffffffffff),
+ UINT64_C(0xe00fffffffffffff),
+ UINT64_C(0xe01fffffffffffff),
+ UINT64_C(0xe03fffffffffffff),
+ UINT64_C(0xe07fffffffffffff),
+ UINT64_C(0xe0ffffffffffffff),
+ UINT64_C(0xe1ffffffffffffff),
+ UINT64_C(0xe3ffffffffffffff),
+ UINT64_C(0xe7ffffffffffffff),
+ UINT64_C(0xefffffffffffffff)
+ },
+ {
+ UINT64_C(0xc000000000000000),
+ UINT64_C(0xc000000000000001),
+ UINT64_C(0xc000000000000003),
+ UINT64_C(0xc000000000000007),
+ UINT64_C(0xc00000000000000f),
+ UINT64_C(0xc00000000000001f),
+ UINT64_C(0xc00000000000003f),
+ UINT64_C(0xc00000000000007f),
+ UINT64_C(0xc0000000000000ff),
+ UINT64_C(0xc0000000000001ff),
+ UINT64_C(0xc0000000000003ff),
+ UINT64_C(0xc0000000000007ff),
+ UINT64_C(0xc000000000000fff),
+ UINT64_C(0xc000000000001fff),
+ UINT64_C(0xc000000000003fff),
+ UINT64_C(0xc000000000007fff),
+ UINT64_C(0xc00000000000ffff),
+ UINT64_C(0xc00000000001ffff),
+ UINT64_C(0xc00000000003ffff),
+ UINT64_C(0xc00000000007ffff),
+ UINT64_C(0xc0000000000fffff),
+ UINT64_C(0xc0000000001fffff),
+ UINT64_C(0xc0000000003fffff),
+ UINT64_C(0xc0000000007fffff),
+ UINT64_C(0xc000000000ffffff),
+ UINT64_C(0xc000000001ffffff),
+ UINT64_C(0xc000000003ffffff),
+ UINT64_C(0xc000000007ffffff),
+ UINT64_C(0xc00000000fffffff),
+ UINT64_C(0xc00000001fffffff),
+ UINT64_C(0xc00000003fffffff),
+ UINT64_C(0xc00000007fffffff),
+ UINT64_C(0xc0000000ffffffff),
+ UINT64_C(0xc0000001ffffffff),
+ UINT64_C(0xc0000003ffffffff),
+ UINT64_C(0xc0000007ffffffff),
+ UINT64_C(0xc000000fffffffff),
+ UINT64_C(0xc000001fffffffff),
+ UINT64_C(0xc000003fffffffff),
+ UINT64_C(0xc000007fffffffff),
+ UINT64_C(0xc00000ffffffffff),
+ UINT64_C(0xc00001ffffffffff),
+ UINT64_C(0xc00003ffffffffff),
+ UINT64_C(0xc00007ffffffffff),
+ UINT64_C(0xc0000fffffffffff),
+ UINT64_C(0xc0001fffffffffff),
+ UINT64_C(0xc0003fffffffffff),
+ UINT64_C(0xc0007fffffffffff),
+ UINT64_C(0xc000ffffffffffff),
+ UINT64_C(0xc001ffffffffffff),
+ UINT64_C(0xc003ffffffffffff),
+ UINT64_C(0xc007ffffffffffff),
+ UINT64_C(0xc00fffffffffffff),
+ UINT64_C(0xc01fffffffffffff),
+ UINT64_C(0xc03fffffffffffff),
+ UINT64_C(0xc07fffffffffffff),
+ UINT64_C(0xc0ffffffffffffff),
+ UINT64_C(0xc1ffffffffffffff),
+ UINT64_C(0xc3ffffffffffffff),
+ UINT64_C(0xc7ffffffffffffff),
+ UINT64_C(0xcfffffffffffffff),
+ UINT64_C(0xdfffffffffffffff)
+ },
+ {
+ UINT64_C(0x8000000000000000),
+ UINT64_C(0x8000000000000001),
+ UINT64_C(0x8000000000000003),
+ UINT64_C(0x8000000000000007),
+ UINT64_C(0x800000000000000f),
+ UINT64_C(0x800000000000001f),
+ UINT64_C(0x800000000000003f),
+ UINT64_C(0x800000000000007f),
+ UINT64_C(0x80000000000000ff),
+ UINT64_C(0x80000000000001ff),
+ UINT64_C(0x80000000000003ff),
+ UINT64_C(0x80000000000007ff),
+ UINT64_C(0x8000000000000fff),
+ UINT64_C(0x8000000000001fff),
+ UINT64_C(0x8000000000003fff),
+ UINT64_C(0x8000000000007fff),
+ UINT64_C(0x800000000000ffff),
+ UINT64_C(0x800000000001ffff),
+ UINT64_C(0x800000000003ffff),
+ UINT64_C(0x800000000007ffff),
+ UINT64_C(0x80000000000fffff),
+ UINT64_C(0x80000000001fffff),
+ UINT64_C(0x80000000003fffff),
+ UINT64_C(0x80000000007fffff),
+ UINT64_C(0x8000000000ffffff),
+ UINT64_C(0x8000000001ffffff),
+ UINT64_C(0x8000000003ffffff),
+ UINT64_C(0x8000000007ffffff),
+ UINT64_C(0x800000000fffffff),
+ UINT64_C(0x800000001fffffff),
+ UINT64_C(0x800000003fffffff),
+ UINT64_C(0x800000007fffffff),
+ UINT64_C(0x80000000ffffffff),
+ UINT64_C(0x80000001ffffffff),
+ UINT64_C(0x80000003ffffffff),
+ UINT64_C(0x80000007ffffffff),
+ UINT64_C(0x8000000fffffffff),
+ UINT64_C(0x8000001fffffffff),
+ UINT64_C(0x8000003fffffffff),
+ UINT64_C(0x8000007fffffffff),
+ UINT64_C(0x800000ffffffffff),
+ UINT64_C(0x800001ffffffffff),
+ UINT64_C(0x800003ffffffffff),
+ UINT64_C(0x800007ffffffffff),
+ UINT64_C(0x80000fffffffffff),
+ UINT64_C(0x80001fffffffffff),
+ UINT64_C(0x80003fffffffffff),
+ UINT64_C(0x80007fffffffffff),
+ UINT64_C(0x8000ffffffffffff),
+ UINT64_C(0x8001ffffffffffff),
+ UINT64_C(0x8003ffffffffffff),
+ UINT64_C(0x8007ffffffffffff),
+ UINT64_C(0x800fffffffffffff),
+ UINT64_C(0x801fffffffffffff),
+ UINT64_C(0x803fffffffffffff),
+ UINT64_C(0x807fffffffffffff),
+ UINT64_C(0x80ffffffffffffff),
+ UINT64_C(0x81ffffffffffffff),
+ UINT64_C(0x83ffffffffffffff),
+ UINT64_C(0x87ffffffffffffff),
+ UINT64_C(0x8fffffffffffffff),
+ UINT64_C(0x9fffffffffffffff),
+ UINT64_C(0xbfffffffffffffff)
+ },
+ {
+ UINT64_C(0x0),
+ UINT64_C(0x1),
+ UINT64_C(0x3),
+ UINT64_C(0x7),
+ UINT64_C(0xf),
+ UINT64_C(0x1f),
+ UINT64_C(0x3f),
+ UINT64_C(0x7f),
+ UINT64_C(0xff),
+ UINT64_C(0x1ff),
+ UINT64_C(0x3ff),
+ UINT64_C(0x7ff),
+ UINT64_C(0xfff),
+ UINT64_C(0x1fff),
+ UINT64_C(0x3fff),
+ UINT64_C(0x7fff),
+ UINT64_C(0xffff),
+ UINT64_C(0x1ffff),
+ UINT64_C(0x3ffff),
+ UINT64_C(0x7ffff),
+ UINT64_C(0xfffff),
+ UINT64_C(0x1fffff),
+ UINT64_C(0x3fffff),
+ UINT64_C(0x7fffff),
+ UINT64_C(0xffffff),
+ UINT64_C(0x1ffffff),
+ UINT64_C(0x3ffffff),
+ UINT64_C(0x7ffffff),
+ UINT64_C(0xfffffff),
+ UINT64_C(0x1fffffff),
+ UINT64_C(0x3fffffff),
+ UINT64_C(0x7fffffff),
+ UINT64_C(0xffffffff),
+ UINT64_C(0x1ffffffff),
+ UINT64_C(0x3ffffffff),
+ UINT64_C(0x7ffffffff),
+ UINT64_C(0xfffffffff),
+ UINT64_C(0x1fffffffff),
+ UINT64_C(0x3fffffffff),
+ UINT64_C(0x7fffffffff),
+ UINT64_C(0xffffffffff),
+ UINT64_C(0x1ffffffffff),
+ UINT64_C(0x3ffffffffff),
+ UINT64_C(0x7ffffffffff),
+ UINT64_C(0xfffffffffff),
+ UINT64_C(0x1fffffffffff),
+ UINT64_C(0x3fffffffffff),
+ UINT64_C(0x7fffffffffff),
+ UINT64_C(0xffffffffffff),
+ UINT64_C(0x1ffffffffffff),
+ UINT64_C(0x3ffffffffffff),
+ UINT64_C(0x7ffffffffffff),
+ UINT64_C(0xfffffffffffff),
+ UINT64_C(0x1fffffffffffff),
+ UINT64_C(0x3fffffffffffff),
+ UINT64_C(0x7fffffffffffff),
+ UINT64_C(0xffffffffffffff),
+ UINT64_C(0x1ffffffffffffff),
+ UINT64_C(0x3ffffffffffffff),
+ UINT64_C(0x7ffffffffffffff),
+ UINT64_C(0xfffffffffffffff),
+ UINT64_C(0x1fffffffffffffff),
+ UINT64_C(0x3fffffffffffffff),
+ UINT64_C(0x7fffffffffffffff)
+ }
+};
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_length_param.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc., 2002-03-19
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_length_param.cpp,v $
+// Revision 1.2 2011/02/18 20:19:15 acg
+// Andy Goodrich: updating Copyright notice.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:49:32 acg
+// Added $Log command so that CVS check in comments are reproduced in the
+// source.
+//
+
+#include <sstream>
+
+#include "systemc/ext/dt/int/sc_length_param.hh"
+
+namespace sc_dt
+{
+
+// explicit template instantiations
+template class sc_global<sc_length_param>;
+template class sc_context<sc_length_param>;
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_length_param
+//
+// Length parameter type.
+// ----------------------------------------------------------------------------
+
+const std::string
+sc_length_param::to_string() const
+{
+ std::stringstream ss;
+ print(ss);
+ return ss.str();
+}
+
+void
+sc_length_param::print(::std::ostream &os) const
+{
+ os << "(" << m_len << ")";
+}
+
+void
+sc_length_param::dump(::std::ostream &os) const
+{
+ os << "sc_length_param" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "len = " << m_len << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_nbcommon.cpp -- Functions common to both sc_signed and sc_unsigned.
+ This file is included in sc_signed.cpp and
+ sc_unsigned.cpp after the macros are defined accordingly.
+ For example, sc_signed.cpp will first define CLASS_TYPE
+ as sc_signed before including this file. This file like
+ sc_nbfriends.cpp and sc_nbexterns.cpp is created in order
+ to ensure only one version of each function, regardless
+ of the class that they interface to.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// ----------------------------------------------------------------------------
+// SECTION : Public members
+// ----------------------------------------------------------------------------
+
+// Create a CLASS_TYPE number with nb bits.
+CLASS_TYPE::CLASS_TYPE(int nb) :
+ sc_value_base(), sgn(), nbits(), ndigits(), digit()
+{
+ sgn = default_sign();
+ if (nb > 0) {
+ nbits = num_bits(nb);
+ } else {
+ invalid_init("int nb", nb);
+ sc_core::sc_abort(); // can't recover from here
+ }
+ ndigits = DIV_CEIL(nbits);
+#ifdef SC_MAX_NBITS
+ test_bound(nb);
+#else
+ digit = new sc_digit[ndigits];
+#endif
+ makezero();
+}
+
+
+// Create a copy of v with sgn s. v is of the same type.
+CLASS_TYPE::CLASS_TYPE(const CLASS_TYPE &v) :
+ sc_value_base(v), sgn(v.sgn), nbits(v.nbits), ndigits(v.ndigits), digit()
+{
+#ifndef SC_MAX_NBITS
+ digit = new sc_digit[ndigits];
+#endif
+
+ vec_copy(ndigits, digit, v.digit);
+}
+
+
+// Create a copy of v where v is of the different type.
+CLASS_TYPE::CLASS_TYPE(const OTHER_CLASS_TYPE &v) :
+ sc_value_base(v), sgn(v.sgn), nbits(num_bits(v.nbits)), ndigits(), digit()
+{
+#if (IF_SC_SIGNED == 1)
+ ndigits = v.ndigits;
+#else
+ ndigits = DIV_CEIL(nbits);
+#endif
+
+#ifndef SC_MAX_NBITS
+ digit = new sc_digit[ndigits];
+#endif
+
+ copy_digits(v.nbits, v.ndigits, v.digit);
+}
+
+// Create a copy of v where v is an sign-less instance.
+CLASS_TYPE::CLASS_TYPE(const sc_bv_base &v) :
+ sc_value_base(), sgn(), nbits(), ndigits(), digit()
+{
+ int nb = v.length();
+ sgn = default_sign();
+ if (nb > 0) {
+ nbits = num_bits(nb);
+ } else {
+ invalid_init("sc_bv_base", nb);
+ sc_core::sc_abort(); // can't recover from here
+ }
+ ndigits = DIV_CEIL(nbits);
+# ifdef SC_MAX_NBITS
+ test_bound(nb);
+# else
+ digit = new sc_digit[ndigits];
+# endif
+ makezero();
+ *this = v;
+}
+
+CLASS_TYPE::CLASS_TYPE(const sc_lv_base &v) :
+ sc_value_base(), sgn(), nbits(), ndigits(), digit()
+{
+ int nb = v.length();
+ sgn = default_sign();
+ if (nb > 0) {
+ nbits = num_bits(nb);
+ } else {
+ invalid_init("sc_lv_base", nb);
+ sc_core::sc_abort(); // can't recover from here
+ }
+ ndigits = DIV_CEIL(nbits);
+# ifdef SC_MAX_NBITS
+ test_bound(nb);
+# else
+ digit = new sc_digit[ndigits];
+# endif
+ makezero();
+ *this = v;
+}
+
+CLASS_TYPE::CLASS_TYPE(const sc_int_subref_r &v) :
+ sc_value_base(v), sgn(), nbits(), ndigits(), digit()
+{
+ int nb = v.length();
+ sgn = default_sign();
+ if (nb > 0) {
+ nbits = num_bits(nb);
+ } else {
+ invalid_init("sc_int_subref", nb);
+ sc_core::sc_abort(); // can't recover from here
+ }
+ ndigits = DIV_CEIL(nbits);
+# ifdef SC_MAX_NBITS
+ test_bound(nb);
+# else
+ digit = new sc_digit[ndigits];
+# endif
+ makezero();
+ *this = v.to_uint64();
+}
+
+CLASS_TYPE::CLASS_TYPE(const sc_uint_subref_r &v) :
+ sc_value_base(v), sgn(), nbits(), ndigits(), digit()
+{
+ int nb = v.length();
+ sgn = default_sign();
+ if (nb > 0) {
+ nbits = num_bits(nb);
+ } else {
+ invalid_init("sc_uint_subref", nb);
+ sc_core::sc_abort(); // can't recover from here
+ }
+ ndigits = DIV_CEIL(nbits);
+# ifdef SC_MAX_NBITS
+ test_bound(nb);
+# else
+ digit = new sc_digit[ndigits];
+# endif
+ makezero();
+ *this = v.to_uint64();
+}
+
+CLASS_TYPE::CLASS_TYPE(const sc_signed_subref_r &v) :
+ sc_value_base(v), sgn(), nbits(), ndigits(), digit()
+{
+ int nb = v.length();
+ sgn = default_sign();
+ if (nb > 0) {
+ nbits = num_bits(nb);
+ } else {
+ invalid_init("sc_signed_subref", nb);
+ sc_core::sc_abort(); // can't recover from here
+ }
+ ndigits = DIV_CEIL(nbits);
+# ifdef SC_MAX_NBITS
+ test_bound(nb);
+# else
+ digit = new sc_digit[ndigits];
+# endif
+ makezero();
+ *this = sc_unsigned(v.m_obj_p, v.m_left, v.m_right);
+}
+
+CLASS_TYPE::CLASS_TYPE(const sc_unsigned_subref_r &v) :
+ sc_value_base(v), sgn(), nbits(), ndigits(), digit()
+{
+ int nb = v.length();
+ sgn = default_sign();
+ if (nb > 0) {
+ nbits = num_bits(nb);
+ } else {
+ invalid_init("sc_unsigned_subref", nb);
+ sc_core::sc_abort(); // can't recover from here
+ }
+ ndigits = DIV_CEIL(nbits);
+# ifdef SC_MAX_NBITS
+ test_bound(nb);
+# else
+ digit = new sc_digit[ndigits];
+# endif
+ makezero();
+ *this = sc_unsigned(v.m_obj_p, v.m_left, v.m_right);
+}
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Concatenation support.
+// ----------------------------------------------------------------------------
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Assignment operators.
+// ----------------------------------------------------------------------------
+
+// Assignment from v of the same type.
+const CLASS_TYPE &
+CLASS_TYPE::operator = (const CLASS_TYPE &v)
+{
+ if (this != &v) {
+ sgn = v.sgn;
+
+ if (sgn == SC_ZERO)
+ vec_zero(ndigits, digit);
+ else
+ copy_digits(v.nbits, v.ndigits, v.digit);
+ }
+ return *this;
+}
+
+
+// Assignment from v of the different type.
+const CLASS_TYPE &
+CLASS_TYPE::operator = (const OTHER_CLASS_TYPE &v)
+{
+ sgn = v.sgn;
+
+ if (sgn == SC_ZERO)
+ vec_zero(ndigits, digit);
+ else
+ copy_digits(v.nbits, v.ndigits, v.digit);
+
+ return *this;
+}
+
+
+// Assignment from an sc_unsigned_subref_r
+const CLASS_TYPE &
+CLASS_TYPE::operator = (const sc_unsigned_subref_r &v)
+{
+ return operator=(sc_unsigned(v));
+}
+
+
+// Assignment from an sc_signed_subref_r
+const CLASS_TYPE &
+CLASS_TYPE::operator = (const sc_signed_subref_r &v)
+{
+ return operator = (sc_unsigned(v));
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Input and output operators
+// ----------------------------------------------------------------------------
+
+void
+CLASS_TYPE::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: PLUS operators: +, +=, ++
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u + v:
+// 1. 0 + v = v
+// 2. u + 0 = u
+// 3. if sgn(u) == sgn(v)
+// 3.1 u + v = +(u + v) = sgn(u) * (u + v)
+// 3.2 (-u) + (-v) = -(u + v) = sgn(u) * (u + v)
+// 4. if sgn(u) != sgn(v)
+// 4.1 u + (-v) = u - v = sgn(u) * (u - v)
+// 4.2 (-u) + v = -(u - v) ==> sgn(u) * (u - v)
+//
+// Specialization of above cases for computing ++u or u++:
+// 1. 0 + 1 = 1
+// 3. u + 1 = u + 1 = sgn(u) * (u + 1)
+// 4. (-u) + 1 = -(u - 1) = sgn(u) * (u - 1)
+
+const CLASS_TYPE &
+CLASS_TYPE::operator += (const CLASS_TYPE &v)
+{
+ // u = *this
+
+ if (sgn == SC_ZERO) // case 1
+ return (*this = v);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return *this;
+
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+
+ convert_SM_to_2C_to_SM();
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator += (const OTHER_CLASS_TYPE &v)
+{
+ // u = *this
+
+ if (sgn == SC_ZERO) // case 1
+ return (*this = v);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return *this;
+
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+
+ convert_SM_to_2C_to_SM();
+
+ return *this;
+}
+
+
+CLASS_TYPE &
+CLASS_TYPE::operator ++ () // prefix
+{
+ *this = *this + 1;
+ return *this;
+}
+
+
+const CLASS_TYPE
+CLASS_TYPE::operator ++ (int) // postfix
+{
+ // Copy digit into d.
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[ndigits];
+#endif
+
+ small_type s = sgn;
+
+ vec_copy(ndigits, d, digit);
+
+ *this = *this + 1;
+
+ return CLASS_TYPE(s, nbits, ndigits, d);
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator += (int64 v)
+{
+ // u = *this
+
+ if (sgn == SC_ZERO) // case 1
+ return (*this = v);
+
+ if (v == 0) // case 2
+ return *this;
+
+ CONVERT_INT64(v);
+
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+
+ convert_SM_to_2C_to_SM();
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator += (uint64 v)
+{
+ // u = *this
+
+ if (sgn == SC_ZERO) // case 1
+ return (*this = v);
+
+ if (v == 0) // case 2
+ return *this;
+
+ CONVERT_INT64(v);
+
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+
+ convert_SM_to_2C_to_SM();
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator += (long v)
+{
+ // u = *this
+
+ if (sgn == SC_ZERO) // case 1
+ return (*this = v);
+
+ if (v == 0) // case 2
+ return *this;
+
+ CONVERT_LONG(v);
+
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+
+ convert_SM_to_2C_to_SM();
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator += (unsigned long v)
+{
+ // u = *this
+
+ if (sgn == SC_ZERO) // case 1
+ return (*this = v);
+
+ if (v == 0) // case 2
+ return *this;
+
+ CONVERT_LONG(v);
+
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+
+ convert_SM_to_2C_to_SM();
+
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: MINUS operators: -, -=, --
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u + v:
+// 1. u - 0 = u
+// 2. 0 - v = -v
+// 3. if sgn(u) != sgn(v)
+// 3.1 u - (-v) = u + v = sgn(u) * (u + v)
+// 3.2 (-u) - v = -(u + v) ==> sgn(u) * (u + v)
+// 4. if sgn(u) == sgn(v)
+// 4.1 u - v = +(u - v) = sgn(u) * (u - v)
+// 4.2 (-u) - (-v) = -(u - v) = sgn(u) * (u - v)
+//
+// Specialization of above cases for computing --u or u--:
+// 1. 0 - 1 = -1
+// 3. (-u) - 1 = -(u + 1) = sgn(u) * (u + 1)
+// 4. u - 1 = u - 1 = sgn(u) * (u - 1)
+
+const CLASS_TYPE &
+CLASS_TYPE::operator -= (const CLASS_TYPE &v)
+{
+ // u = *this
+ if (v.sgn == SC_ZERO) // case 1
+ return *this;
+ if (sgn == SC_ZERO) { // case 2
+ sgn = -v.sgn;
+ copy_digits(v.nbits, v.ndigits, v.digit);
+ } else {
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+ convert_SM_to_2C_to_SM();
+ }
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator -= (const OTHER_CLASS_TYPE &v)
+{
+ // u = *this
+ if (v.sgn == SC_ZERO) // case 1
+ return *this;
+ if (sgn == SC_ZERO) { // case 2
+ sgn = -v.sgn;
+ copy_digits(v.nbits, v.ndigits, v.digit);
+ } else {
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+
+ convert_SM_to_2C_to_SM();
+ }
+ return *this;
+}
+
+CLASS_TYPE &
+CLASS_TYPE::operator -- () // prefix
+{
+ *this = *this - 1;
+ return *this;
+}
+
+const CLASS_TYPE
+CLASS_TYPE::operator -- (int) // postfix
+{
+ // Copy digit into d.
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[ndigits];
+#endif
+ small_type s = sgn;
+ vec_copy(ndigits, d, digit);
+ *this = *this - 1;
+ return CLASS_TYPE(s, nbits, ndigits, d);
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator -= (int64 v)
+{
+ // u = *this
+ if (v == 0) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = -v);
+
+ CONVERT_INT64(v);
+
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+
+ convert_SM_to_2C_to_SM();
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator -= (uint64 v)
+{
+ // u = *this
+
+ if (v == 0) // case 1
+ return *this;
+
+ int64 v2 = (int64) v;
+
+ if (sgn == SC_ZERO) // case 2
+ return (*this = -v2);
+
+ CONVERT_INT64(v);
+
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+
+ convert_SM_to_2C_to_SM();
+
+ return *this;
+}
+
+const CLASS_TYPE &
+CLASS_TYPE::operator -= (long v)
+{
+ // u = *this
+
+ if (v == 0) // case 1
+ return *this;
+
+ if (sgn == SC_ZERO) // case 2
+ return (*this = -v);
+
+ CONVERT_LONG(v);
+
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+
+ convert_SM_to_2C_to_SM();
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator -= (unsigned long v)
+{
+ // u = *this
+
+ if (v == 0) // case 1
+ return *this;
+
+ long v2 = (long) v;
+
+ if (sgn == SC_ZERO) // case 2
+ return (*this = -v2);
+
+ CONVERT_LONG(v);
+
+ // cases 3 and 4
+ add_on_help(sgn, nbits, ndigits, digit,
+ -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+
+ convert_SM_to_2C_to_SM();
+
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: MULTIPLICATION operators: *, *=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u * v:
+// 1. u * 0 = 0 * v = 0
+// 2. 1 * v = v and -1 * v = -v
+// 3. u * 1 = u and u * -1 = -u
+// 4. u * v = u * v
+
+const CLASS_TYPE &
+CLASS_TYPE::operator *= (const CLASS_TYPE &v)
+{
+ // u = *this
+
+ sgn = mul_signs(sgn, v.sgn);
+
+ if (sgn == SC_ZERO) { // case 1
+ vec_zero(ndigits, digit);
+ } else {
+ // cases 2-4
+ MUL_ON_HELPER(sgn, nbits, ndigits, digit,
+ v.nbits, v.ndigits, v.digit);
+ }
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator *= (const OTHER_CLASS_TYPE &v)
+{
+ // u = *this
+
+ sgn = mul_signs(sgn, v.sgn);
+
+ if (sgn == SC_ZERO) { // case 1
+ vec_zero(ndigits, digit);
+ } else {
+ // cases 2-4
+ MUL_ON_HELPER(sgn, nbits, ndigits, digit,
+ v.nbits, v.ndigits, v.digit);
+ }
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator *= (int64 v)
+{
+ // u = *this
+
+ sgn = mul_signs(sgn, get_sign(v));
+
+ if (sgn == SC_ZERO) { // case 1
+ vec_zero(ndigits, digit);
+ } else { // cases 2-4
+ CONVERT_INT64_2(v);
+ MUL_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ }
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator *= (uint64 v)
+{
+ // u = *this
+ sgn = mul_signs(sgn, get_sign(v));
+
+ if (sgn == SC_ZERO) { // case 1
+ vec_zero(ndigits, digit);
+ } else { // cases 2-4
+ CONVERT_INT64_2(v);
+ MUL_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ }
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator *= (long v)
+{
+ // u = *this
+
+ sgn = mul_signs(sgn, get_sign(v));
+
+ if (sgn == SC_ZERO) { // case 1
+ vec_zero(ndigits, digit);
+ } else { // cases 2-4
+ CONVERT_LONG_2(v);
+ MUL_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator *= (unsigned long v)
+{
+ // u = *this
+
+ sgn = mul_signs(sgn, get_sign(v));
+
+ if (sgn == SC_ZERO) { // case 1
+ vec_zero(ndigits, digit);
+ } else { // cases 2-4
+ CONVERT_LONG_2(v);
+ MUL_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ }
+
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: DIVISION operators: /, /=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when finding the quotient q = floor(u/v):
+// Note that u = q * v + r for r < q.
+// 1. 0 / 0 or u / 0 => error
+// 2. 0 / v => 0 = 0 * v + 0
+// 3. u / v && u = v => u = 1 * u + 0 - u or v can be 1 or -1
+// 4. u / v && u < v => u = 0 * v + u - u can be 1 or -1
+// 5. u / v && u > v => u = q * v + r - v can be 1 or -1
+
+const CLASS_TYPE &
+CLASS_TYPE::operator /= (const CLASS_TYPE &v)
+{
+ sgn = mul_signs(sgn, v.sgn);
+
+ if (sgn == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else { // other cases
+ DIV_ON_HELPER(sgn, nbits, ndigits, digit,
+ v.nbits, v.ndigits, v.digit);
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator /= (const OTHER_CLASS_TYPE &v)
+{
+ sgn = mul_signs(sgn, v.sgn);
+
+ if (sgn == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else { // other cases
+ DIV_ON_HELPER(sgn, nbits, ndigits, digit,
+ v.nbits, v.ndigits, v.digit);
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator /= (int64 v)
+{
+ // u = *this
+
+ sgn = mul_signs(sgn, get_sign(v));
+
+ if (sgn == SC_ZERO) {
+ div_by_zero(v); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else {
+ CONVERT_INT64_2(v);
+ // other cases
+ DIV_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator /= (uint64 v)
+{
+ // u = *this
+
+ sgn = mul_signs(sgn, get_sign(v));
+
+ if (sgn == SC_ZERO) {
+ div_by_zero(v); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else {
+ CONVERT_INT64_2(v);
+ // other cases
+ DIV_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator /= (long v)
+{
+ // u = *this
+
+ sgn = mul_signs(sgn, get_sign(v));
+
+ if (sgn == SC_ZERO) {
+ div_by_zero(v); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else {
+ CONVERT_LONG_2(v);
+ // other cases
+ DIV_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator /= (unsigned long v)
+{
+ // u = *this
+
+ sgn = mul_signs(sgn, get_sign(v));
+
+ if (sgn == SC_ZERO) {
+ div_by_zero(v); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else {
+ CONVERT_LONG_2(v);
+ // other cases
+ DIV_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ }
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: MOD operators: %, %=.
+// ----------------------------------------------------------------------------
+
+// Cases to consider when finding the remainder r = u % v:
+// Note that u = q * v + r for r < q.
+// 1. 0 % 0 or u % 0 => error
+// 2. 0 % v => 0 = 0 * v + 0
+// 3. u % v && u = v => u = 1 * u + 0 - u or v can be 1 or -1
+// 4. u % v && u < v => u = 0 * v + u - u can be 1 or -1
+// 5. u % v && u > v => u = q * v + r - v can be 1 or -1
+
+const CLASS_TYPE &
+CLASS_TYPE::operator %= (const CLASS_TYPE &v)
+{
+ if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else { // other cases
+ MOD_ON_HELPER(sgn, nbits, ndigits, digit,
+ v.nbits, v.ndigits, v.digit);
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator %= (const OTHER_CLASS_TYPE &v)
+{
+ if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else { // other cases
+ MOD_ON_HELPER(sgn, nbits, ndigits, digit,
+ v.nbits, v.ndigits, v.digit);
+ }
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator %= (int64 v)
+{
+ small_type vs = get_sign(v);
+
+ if ((sgn == SC_ZERO) || (vs == SC_ZERO)) {
+ div_by_zero(v); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else {
+ CONVERT_INT64_2(v);
+ // other cases
+ MOD_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator %= (uint64 v)
+{
+ if ((sgn == SC_ZERO) || (v == 0)) {
+ div_by_zero(v); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else {
+ CONVERT_INT64_2(v);
+ // other cases
+ MOD_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator %= (long v)
+{
+ small_type vs = get_sign(v);
+
+ if ((sgn == SC_ZERO) || (vs == SC_ZERO)) {
+ div_by_zero(v); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else {
+ CONVERT_LONG_2(v);
+ // other cases
+ MOD_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator %= (unsigned long v)
+{
+ if ((sgn == SC_ZERO) || (v == 0)) {
+ div_by_zero(v); // case 1
+ vec_zero(ndigits, digit); // case 2
+ } else {
+ CONVERT_LONG_2(v);
+ // other cases
+ MOD_ON_HELPER(sgn, nbits, ndigits, digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ }
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise AND operators: &, &=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u &v:
+// 1. u & 0 = 0 &v = 0
+// 2. u &v => sgn = +
+// 3. (-u) & (-v) => sgn = -
+// 4. u & (-v) => sgn = +
+// 5. (-u) &v => sgn = +
+
+const CLASS_TYPE &
+CLASS_TYPE::operator &= (const CLASS_TYPE &v)
+{
+ // u = *this
+ if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) { // case 1
+ makezero();
+ } else { // other cases
+ and_on_help(sgn, nbits, ndigits, digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+ convert_2C_to_SM();
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator &= (const OTHER_CLASS_TYPE &v)
+{
+ // u = *this
+
+ if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) { // case 1
+ makezero();
+ } else { // other cases
+ and_on_help(sgn, nbits, ndigits, digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+ convert_2C_to_SM();
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator &= (int64 v)
+{
+ // u = *this
+ if ((sgn == SC_ZERO) || (v == 0)) { // case 1
+ makezero();
+ } else { // other cases
+ CONVERT_INT64(v);
+ and_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ convert_2C_to_SM();
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator &= (uint64 v)
+{
+ // u = *this
+ if ((sgn == SC_ZERO) || (v == 0)) { // case 1
+ makezero();
+ } else { // other cases
+ CONVERT_INT64(v);
+ and_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ convert_2C_to_SM();
+ }
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator &= (long v)
+{
+ // u = *this
+
+ if ((sgn == SC_ZERO) || (v == 0)) { // case 1
+ makezero();
+ } else { // other cases
+ CONVERT_LONG(v);
+ and_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ convert_2C_to_SM();
+ }
+
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator &= (unsigned long v)
+{
+ // u = *this
+ if ((sgn == SC_ZERO) || (v == 0)) { // case 1
+ makezero();
+ } else { // other cases
+ CONVERT_LONG(v);
+ and_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ convert_2C_to_SM();
+ }
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise OR operators: |, |=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u | v:
+// 1. u | 0 = u
+// 2. 0 | v = v
+// 3. u | v => sgn = +
+// 4. (-u) | (-v) => sgn = -
+// 5. u | (-v) => sgn = -
+// 6. (-u) | v => sgn = -
+
+const CLASS_TYPE &
+CLASS_TYPE::operator |= (const CLASS_TYPE &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ or_on_help(sgn, nbits, ndigits, digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator |= (const OTHER_CLASS_TYPE &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ or_on_help(sgn, nbits, ndigits, digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+const CLASS_TYPE&
+CLASS_TYPE::operator |= (int64 v)
+{
+ if (v == 0) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ CONVERT_INT64(v);
+ or_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+const CLASS_TYPE&
+CLASS_TYPE::operator |= (uint64 v)
+{
+ if (v == 0) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ CONVERT_INT64(v);
+ or_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator |= (long v)
+{
+ if (v == 0) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ CONVERT_LONG(v);
+ or_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator |= (unsigned long v)
+{
+ if (v == 0) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ CONVERT_LONG(v);
+ or_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise XOR operators: ^, ^=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u ^ v:
+// Note that u ^ v = (~u &v) | (u & ~v).
+// 1. u ^ 0 = u
+// 2. 0 ^ v = v
+// 3. u ^ v => sgn = +
+// 4. (-u) ^ (-v) => sgn = -
+// 5. u ^ (-v) => sgn = -
+// 6. (-u) ^ v => sgn = +
+
+const CLASS_TYPE &
+CLASS_TYPE::operator ^= (const CLASS_TYPE &v)
+{
+ // u = *this
+ if (v.sgn == SC_ZERO) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ xor_on_help(sgn, nbits, ndigits, digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator ^= (const OTHER_CLASS_TYPE &v)
+{
+ // u = *this
+ if (v.sgn == SC_ZERO) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ xor_on_help(sgn, nbits, ndigits, digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+const CLASS_TYPE&
+CLASS_TYPE::operator ^= (int64 v)
+{
+ if (v == 0) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ CONVERT_INT64(v);
+ xor_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator ^= (uint64 v)
+{
+ if (v == 0) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ CONVERT_INT64(v);
+ xor_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator ^= (long v)
+{
+ if (v == 0) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ CONVERT_LONG(v);
+ xor_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator ^= (unsigned long v)
+{
+ if (v == 0) // case 1
+ return *this;
+ if (sgn == SC_ZERO) // case 2
+ return (*this = v);
+ // other cases
+ CONVERT_LONG(v);
+ xor_on_help(sgn, nbits, ndigits, digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise NOT operator: ~
+// ----------------------------------------------------------------------------
+
+CLASS_TYPE
+operator ~ (const CLASS_TYPE &u)
+{
+ small_type s = u.sgn;
+ if (s == SC_ZERO) {
+ sc_digit d = 1;
+ return CLASS_TYPE(SC_NEG, u.nbits, 1, &d, false);
+ }
+
+ int nd = u.ndigits;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_copy(nd, d, u.digit);
+ if (s == SC_POS) {
+ s = SC_NEG;
+ vec_add_small_on(nd, d, 1);
+ } else {
+ s = SC_POS;
+ vec_sub_small_on(nd, d, 1);
+ if (check_for_zero(nd, d))
+ s = SC_ZERO;
+ }
+ return CLASS_TYPE(s, u.nbits, nd, d);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: LEFT SHIFT operators: <<, <<=
+// ----------------------------------------------------------------------------
+
+CLASS_TYPE
+operator << (const CLASS_TYPE &u, const CLASS_TYPE &v)
+{
+ if (v.sgn == SC_ZERO)
+ return CLASS_TYPE(u);
+#ifdef SC_SIGNED
+ if (v.sgn == SC_NEG)
+ return CLASS_TYPE(u);
+#endif
+ return operator << (u, v.to_ulong());
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator <<= (const CLASS_TYPE &v)
+{
+ if (v.sgn == SC_ZERO)
+ return *this;
+#ifdef SC_SIGNED
+ if (v.sgn == SC_NEG)
+ return *this;
+#endif
+ return operator <<= (v.to_ulong());
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator <<= (const OTHER_CLASS_TYPE &v)
+{
+ if (v.sgn == SC_ZERO)
+ return *this;
+#ifdef SC_UNSIGNED
+ if (v.sgn == SC_NEG)
+ return *this;
+#endif
+ return operator <<= (v.to_ulong());
+}
+
+
+CLASS_TYPE
+operator << (const CLASS_TYPE &u, int64 v)
+{
+ if (v <= 0)
+ return CLASS_TYPE(u);
+ return operator << (u, (unsigned long)v);
+}
+
+
+CLASS_TYPE
+operator << (const CLASS_TYPE &u, uint64 v)
+{
+ if (v == 0)
+ return CLASS_TYPE(u);
+ return operator << (u, (unsigned long)v);
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator <<= (int64 v)
+{
+ if (v <= 0)
+ return *this;
+ return operator <<= ((unsigned long)v);
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator <<= (uint64 v)
+{
+ if (v == 0)
+ return *this;
+ return operator <<= ((unsigned long)v);
+}
+
+
+CLASS_TYPE
+operator << (const CLASS_TYPE &u, long v)
+{
+ if (v <= 0)
+ return CLASS_TYPE(u);
+ return operator << (u, (unsigned long)v);
+}
+
+CLASS_TYPE
+operator << (const CLASS_TYPE &u, unsigned long v)
+{
+ if (v == 0)
+ return CLASS_TYPE(u);
+ if (u.sgn == SC_ZERO)
+ return CLASS_TYPE(u);
+
+ int nb = u.nbits + v;
+ int nd = DIV_CEIL(nb);
+
+#ifdef SC_MAX_NBITS
+ test_bound(nb);
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_copy_and_zero(nd, d, u.ndigits, u.digit);
+ convert_SM_to_2C(u.sgn, nd, d);
+ vec_shift_left(nd, d, v);
+ small_type s = convert_signed_2C_to_SM(nb, nd, d);
+ return CLASS_TYPE(s, nb, nd, d);
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator <<= (long v)
+{
+ if (v <= 0)
+ return *this;
+ return operator <<= ((unsigned long)v);
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator <<= (unsigned long v)
+{
+ if (v == 0)
+ return *this;
+ if (sgn == SC_ZERO)
+ return *this;
+ convert_SM_to_2C();
+ vec_shift_left(ndigits, digit, v);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: RIGHT SHIFT operators: >>, >>=
+// ----------------------------------------------------------------------------
+
+CLASS_TYPE
+operator >> (const CLASS_TYPE &u, const CLASS_TYPE &v)
+{
+ if (v.sgn == SC_ZERO)
+ return CLASS_TYPE(u);
+#ifdef SC_SIGNED
+ if (v.sgn == SC_NEG)
+ return CLASS_TYPE(u);
+#endif
+ return operator >> (u, v.to_long());
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator >>= (const CLASS_TYPE &v)
+{
+ if (v.sgn == SC_ZERO)
+ return *this;
+#ifdef SC_SIGNED
+ if (v.sgn == SC_NEG)
+ return *this;
+#endif
+ return operator >>= (v.to_long());
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator >>= (const OTHER_CLASS_TYPE &v)
+{
+ if (v.sgn == SC_ZERO)
+ return *this;
+#ifdef SC_UNSIGNED
+ if (v.sgn == SC_NEG)
+ return *this;
+#endif
+ return operator >>= (v.to_ulong());
+}
+
+
+CLASS_TYPE
+operator >> (const CLASS_TYPE &u, int64 v)
+{
+ if (v <= 0)
+ return CLASS_TYPE(u);
+ return operator >> (u, (unsigned long)v);
+}
+
+
+CLASS_TYPE
+operator >> (const CLASS_TYPE &u, uint64 v)
+{
+ if (v == 0)
+ return CLASS_TYPE(u);
+ return operator >> (u, (unsigned long)v);
+}
+
+const CLASS_TYPE &
+CLASS_TYPE::operator >>= (int64 v)
+{
+ if (v <= 0)
+ return *this;
+ return operator >>= ((unsigned long)v);
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator >>= (uint64 v)
+{
+ if (v == 0)
+ return *this;
+ return operator >>= ((unsigned long)v);
+}
+
+
+CLASS_TYPE
+operator >> (const CLASS_TYPE &u, long v)
+{
+ if (v <= 0)
+ return CLASS_TYPE(u);
+ return operator >> (u, (unsigned long)v);
+}
+
+
+CLASS_TYPE
+operator >> (const CLASS_TYPE &u, unsigned long v)
+{
+ if (v == 0)
+ return CLASS_TYPE(u);
+ if (u.sgn == SC_ZERO)
+ return CLASS_TYPE(u);
+
+ int nb = u.nbits;
+ int nd = u.ndigits;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_copy(nd, d, u.digit);
+ convert_SM_to_2C(u.sgn, nd, d);
+ if (u.sgn == SC_NEG)
+ vec_shift_right(nd, d, v, DIGIT_MASK);
+ else
+ vec_shift_right(nd, d, v, 0);
+ small_type s = convert_signed_2C_to_SM(nb, nd, d);
+ return CLASS_TYPE(s, nb, nd, d);
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator >>= (long v)
+{
+ if (v <= 0)
+ return *this;
+ return operator >>= ((unsigned long)v);
+}
+
+
+const CLASS_TYPE &
+CLASS_TYPE::operator >>= (unsigned long v)
+{
+ if (v == 0)
+ return *this;
+ if (sgn == SC_ZERO)
+ return *this;
+
+ convert_SM_to_2C();
+
+ if (sgn == SC_NEG)
+ vec_shift_right(ndigits, digit, v, DIGIT_MASK);
+ else
+ vec_shift_right(ndigits, digit, v, 0);
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: EQUAL TO operator: ==
+// ----------------------------------------------------------------------------
+
+// Defined in the sc_signed.cpp and sc_unsigned.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: NOT_EQUAL operator: !=
+// ----------------------------------------------------------------------------
+
+bool
+operator != (const CLASS_TYPE &u, const CLASS_TYPE &v)
+{
+ return (!operator == (u, v));
+}
+
+
+bool
+operator != (const CLASS_TYPE &u, int64 v)
+{
+ return (!operator == (u, v));
+}
+
+
+bool
+operator != (int64 u, const CLASS_TYPE &v)
+{
+ return (!operator == (u, v));
+}
+
+
+bool
+operator != (const CLASS_TYPE &u, uint64 v)
+{
+ return (!operator == (u, v));
+}
+
+
+bool
+operator != (uint64 u, const CLASS_TYPE &v)
+{
+ return (!operator == (u, v));
+}
+
+
+bool
+operator != (const CLASS_TYPE &u, long v)
+{
+ return (!operator == (u, v));
+}
+
+
+bool
+operator != (long u, const CLASS_TYPE &v)
+{
+ return (!operator == (u, v));
+}
+
+
+bool
+operator != (const CLASS_TYPE &u, unsigned long v)
+{
+ return (!operator == (u, v));
+}
+
+
+bool
+operator != (unsigned long u, const CLASS_TYPE &v)
+{
+ return (!operator == (u, v));
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: LESS THAN operator: <
+// ----------------------------------------------------------------------------
+
+// Defined in the sc_signed.cpp and sc_unsigned.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: LESS THAN or EQUAL operator: <=
+// ----------------------------------------------------------------------------
+
+bool
+operator <= (const CLASS_TYPE &u, const CLASS_TYPE &v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+
+bool
+operator <= (const CLASS_TYPE &u, int64 v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+
+bool
+operator <= (int64 u, const CLASS_TYPE &v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+
+bool
+operator <= (const CLASS_TYPE &u, uint64 v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+
+bool
+operator <= (uint64 u, const CLASS_TYPE &v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+
+bool
+operator <= (const CLASS_TYPE &u, long v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+
+bool
+operator <= (long u, const CLASS_TYPE &v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+
+bool
+operator <= (const CLASS_TYPE &u, unsigned long v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+
+bool
+operator <= (unsigned long u, const CLASS_TYPE &v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: GREATER THAN operator: >
+// ----------------------------------------------------------------------------
+
+bool
+operator > (const CLASS_TYPE &u, const CLASS_TYPE &v)
+{
+ return (!(operator <= (u, v)));
+}
+
+
+bool
+operator > (const CLASS_TYPE &u, int64 v)
+{
+ return (!(operator <= (u, v)));
+}
+
+
+bool
+operator > (int64 u, const CLASS_TYPE &v)
+{
+ return (!(operator <= (u, v)));
+}
+
+
+bool
+operator > (const CLASS_TYPE &u, uint64 v)
+{
+ return (!(operator <= (u, v)));
+}
+
+
+bool
+operator > (uint64 u, const CLASS_TYPE &v)
+{
+ return (!(operator <= (u, v)));
+}
+
+
+bool
+operator > (const CLASS_TYPE &u, long v)
+{
+ return (!(operator <= (u, v)));
+}
+
+
+bool
+operator > (long u, const CLASS_TYPE &v)
+{
+ return (!(operator <= (u, v)));
+}
+
+
+bool
+operator > (const CLASS_TYPE &u, unsigned long v)
+{
+ return (!(operator <= (u, v)));
+}
+
+
+bool
+operator > (unsigned long u, const CLASS_TYPE &v)
+{
+ return (!(operator <= (u, v)));
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: GREATER THAN or EQUAL operator: >=
+// ----------------------------------------------------------------------------
+
+bool
+operator >= (const CLASS_TYPE &u, const CLASS_TYPE &v)
+{
+ return (!(operator < (u, v)));
+}
+
+
+bool
+operator >= (const CLASS_TYPE &u, int64 v)
+{
+ return (!(operator < (u, v)));
+}
+
+
+bool
+operator >= (int64 u, const CLASS_TYPE &v)
+{
+ return (!(operator < (u, v)));
+}
+
+
+bool
+operator >= (const CLASS_TYPE &u, uint64 v)
+{
+ return (!(operator < (u, v)));
+}
+
+
+bool
+operator >= (uint64 u, const CLASS_TYPE &v)
+{
+ return (!(operator < (u, v)));
+}
+
+
+bool
+operator >= (const CLASS_TYPE &u, long v)
+{
+ return (!(operator < (u, v)));
+}
+
+
+bool
+operator >= (long u, const CLASS_TYPE &v)
+{
+ return (!(operator < (u, v)));
+}
+
+
+bool
+operator >= (const CLASS_TYPE &u, unsigned long v)
+{
+ return (!(operator < (u, v)));
+}
+
+
+bool
+operator >= (unsigned long u, const CLASS_TYPE &v)
+{
+ return (!(operator < (u, v)));
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Other utils.
+// ----------------------------------------------------------------------------
+
+// Convert to int64, long, or int.
+#define TO_INTX(RET_TYPE, UP_RET_TYPE) \
+if (sgn == SC_ZERO) \
+ return 0; \
+int vnd = sc_min((int)DIGITS_PER_ ## UP_RET_TYPE, ndigits); \
+RET_TYPE v = 0; \
+while (--vnd >= 0) \
+ v = (v << BITS_PER_DIGIT) + digit[vnd]; \
+if (sgn == SC_NEG) \
+ return -v; \
+else \
+ return v;
+
+
+int64
+CLASS_TYPE::to_int64() const
+{
+ TO_INTX(int64, INT64);
+}
+
+
+long
+CLASS_TYPE::to_long() const
+{
+ TO_INTX(long, LONG);
+}
+
+
+int
+CLASS_TYPE::to_int() const
+{
+ TO_INTX(int, INT);
+}
+
+
+// Convert to unsigned int64, unsigned long or unsigned
+// int. to_uint64, to_ulong, and to_uint have the same body except for
+// the type of v defined inside.
+uint64
+CLASS_TYPE::to_uint64() const
+{
+ if (sgn == SC_ZERO)
+ return 0;
+
+ int vnd = sc_min((int)DIGITS_PER_INT64, ndigits);
+
+ uint64 v = 0;
+
+ if (sgn == SC_NEG) {
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[ndigits];
+#endif
+ vec_copy(ndigits, d, digit);
+ convert_SM_to_2C_trimmed(IF_SC_SIGNED, sgn, nbits, ndigits, d);
+ while (--vnd >= 0)
+ v = (v << BITS_PER_DIGIT) + d[vnd];
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ } else {
+ while (--vnd >= 0)
+ v = (v << BITS_PER_DIGIT) + digit[vnd];
+ }
+ return v;
+}
+
+
+unsigned long
+CLASS_TYPE::to_ulong() const
+{
+ if (sgn == SC_ZERO)
+ return 0;
+
+ int vnd = sc_min((int)DIGITS_PER_LONG, ndigits);
+ unsigned long v = 0;
+
+ if (sgn == SC_NEG) {
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[ndigits];
+#endif
+ vec_copy(ndigits, d, digit);
+ convert_SM_to_2C_trimmed(IF_SC_SIGNED, sgn, nbits, ndigits, d);
+ while (--vnd >= 0)
+ v = (v << BITS_PER_DIGIT) + d[vnd];
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ } else {
+ while (--vnd >= 0)
+ v = (v << BITS_PER_DIGIT) + digit[vnd];
+ }
+ return v;
+}
+
+
+unsigned int
+CLASS_TYPE::to_uint() const
+{
+ if (sgn == SC_ZERO)
+ return 0;
+
+ int vnd = sc_min((int)DIGITS_PER_INT, ndigits);
+ unsigned int v = 0;
+ if (sgn == SC_NEG) {
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[ndigits];
+#endif
+ vec_copy(ndigits, d, digit);
+ convert_SM_to_2C_trimmed(IF_SC_SIGNED, sgn, nbits, ndigits, d);
+ while (--vnd >= 0)
+ v = (v << BITS_PER_DIGIT) + d[vnd];
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ } else {
+ while (--vnd >= 0)
+ v = (v << BITS_PER_DIGIT) + digit[vnd];
+ }
+ return v;
+}
+
+
+// Convert to double.
+double
+CLASS_TYPE::to_double() const
+{
+ if (sgn == SC_ZERO)
+ return (double) 0.0;
+
+ int vnd = ndigits;
+ double v = 0.0;
+ while (--vnd >= 0)
+ v = v * DIGIT_RADIX + digit[vnd];
+ if (sgn == SC_NEG)
+ return -v;
+ else
+ return v;
+}
+
+
+// Return true if the bit i is 1, false otherwise. If i is outside the
+// bounds, return 1/0 according to the sign of the number by assuming
+// that the number has infinite length.
+
+bool
+CLASS_TYPE::test(int i) const
+{
+#ifdef SC_SIGNED
+ if (check_if_outside(i)) {
+ if (sgn == SC_NEG)
+ return 1;
+ else
+ return 0;
+ }
+#else
+ if (check_if_outside(i))
+ return 0;
+#endif
+
+ int bit_num = bit_ord(i);
+ int digit_num = digit_ord(i);
+
+ if (sgn == SC_NEG) {
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[ndigits];
+#endif
+ vec_copy(ndigits, d, digit);
+ vec_complement(ndigits, d);
+ bool val = ((d[digit_num] & one_and_zeros(bit_num)) != 0);
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ return val;
+ } else {
+ return ((digit[digit_num] & one_and_zeros(bit_num)) != 0);
+ }
+}
+
+
+// Set the ith bit with 1.
+void
+CLASS_TYPE::set(int i)
+{
+ if (check_if_outside(i))
+ return;
+
+ int bit_num = bit_ord(i);
+ int digit_num = digit_ord(i);
+
+ convert_SM_to_2C();
+ digit[digit_num] |= one_and_zeros(bit_num);
+ digit[digit_num] &= DIGIT_MASK; // Needed to zero the overflow bits.
+ convert_2C_to_SM();
+}
+
+
+// Set the ith bit with 0, i.e., clear the ith bit.
+void
+CLASS_TYPE::clear(int i)
+{
+ if (check_if_outside(i))
+ return;
+
+ int bit_num = bit_ord(i);
+ int digit_num = digit_ord(i);
+
+ convert_SM_to_2C();
+ digit[digit_num] &= ~(one_and_zeros(bit_num));
+ digit[digit_num] &= DIGIT_MASK; // Needed to zero the overflow bits.
+ convert_2C_to_SM();
+}
+
+
+// Create a mirror image of the number.
+void
+CLASS_TYPE::reverse()
+{
+ convert_SM_to_2C();
+ vec_reverse(length(), ndigits, digit, length() - 1);
+ convert_2C_to_SM();
+}
+
+
+// Get a packed bit representation of the number.
+void
+CLASS_TYPE::get_packed_rep(sc_digit *buf) const
+{
+ int buf_ndigits = (length() - 1) / BITS_PER_DIGIT_TYPE + 1;
+ // Initialize buf to zero.
+ vec_zero(buf_ndigits, buf);
+
+ if (sgn == SC_ZERO)
+ return;
+
+ const sc_digit *digit_or_d;
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[ndigits];
+#endif
+
+ if (sgn == SC_POS) {
+ digit_or_d = digit;
+ } else {
+ // If sgn is negative, we have to convert digit to its 2's
+ // complement. Since this function is const, we can not do it on
+ // digit. Since buf doesn't have overflow bits, we cannot also do
+ // it on buf. Thus, we have to do the complementation on a copy of
+ // digit, i.e., on d.
+
+ vec_copy(ndigits, d, digit);
+ vec_complement(ndigits, d);
+ buf[buf_ndigits - 1] = ~((sc_digit) 0);
+ digit_or_d = d;
+ }
+
+ // Copy the bits from digit to buf. The division and mod operations
+ // below can be converted to addition/subtraction and comparison
+ // operations at the expense of complicating the code. We can do it
+ // if we see any performance problems.
+
+ for (int i = length() - 1; i >= 0; --i) {
+
+ if ((digit_or_d[digit_ord(i)] &
+ one_and_zeros(bit_ord(i))) != 0) { // Test.
+ buf[i / BITS_PER_DIGIT_TYPE] |=
+ one_and_zeros(i % BITS_PER_DIGIT_TYPE); // Set.
+ } else {
+ buf[i / BITS_PER_DIGIT_TYPE] &=
+ ~(one_and_zeros(i % BITS_PER_DIGIT_TYPE)); // Clear.
+ }
+ }
+
+#ifndef SC_MAX_NBITS
+ delete[] d;
+#endif
+}
+
+
+// Set a packed bit representation of the number.
+void
+CLASS_TYPE::set_packed_rep(sc_digit *buf)
+{
+ // Initialize digit to zero.
+ vec_zero(ndigits, digit);
+
+ // Copy the bits from buf to digit.
+ for (int i = length() - 1; i >= 0; --i) {
+ if ((buf[i / BITS_PER_DIGIT_TYPE] &
+ one_and_zeros(i % BITS_PER_DIGIT_TYPE)) != 0) { // Test.
+ digit[digit_ord(i)] |= one_and_zeros(bit_ord(i)); // Set.
+ } else {
+ digit[digit_ord(i)] &= ~(one_and_zeros(bit_ord(i))); // Clear
+ }
+ }
+ convert_2C_to_SM();
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Private members.
+// ----------------------------------------------------------------------------
+
+// Create a copy of v with sgn s.
+CLASS_TYPE::CLASS_TYPE(const CLASS_TYPE &v, small_type s) :
+ sc_value_base(v), sgn(s), nbits(v.nbits), ndigits(v.ndigits), digit()
+{
+#ifndef SC_MAX_NBITS
+ digit = new sc_digit[ndigits];
+#endif
+ vec_copy(ndigits, digit, v.digit);
+}
+
+
+// Create a copy of v where v is of the different type.
+CLASS_TYPE::CLASS_TYPE(const OTHER_CLASS_TYPE &v, small_type s) :
+ sc_value_base(v), sgn(s), nbits(num_bits(v.nbits)), ndigits(), digit()
+{
+#if (IF_SC_SIGNED == 1)
+ ndigits = v.ndigits;
+#else
+ ndigits = DIV_CEIL(nbits);
+#endif
+
+#ifndef SC_MAX_NBITS
+ digit = new sc_digit[ndigits];
+#endif
+
+ copy_digits(v.nbits, v.ndigits, v.digit);
+}
+
+
+// Create a signed number with (s, nb, nd, d) as its attributes (as
+// defined in class CLASS_TYPE). If alloc is set, delete d.
+CLASS_TYPE::CLASS_TYPE(
+ small_type s, int nb, int nd, sc_digit *d, bool alloc) :
+ sc_value_base(), sgn(s), nbits(num_bits(nb)), ndigits(), digit()
+{
+ ndigits = DIV_CEIL(nbits);
+#ifndef SC_MAX_NBITS
+ digit = new sc_digit[ndigits];
+#endif
+
+ if (ndigits <= nd)
+ vec_copy(ndigits, digit, d);
+ else
+ vec_copy_and_zero(ndigits, digit, nd, d);
+
+#ifndef SC_MAX_NBITS
+ if (alloc)
+ delete [] d;
+#endif
+}
+
+// This constructor is mainly used in finding a "range" of bits from a
+// number of type CLASS_TYPE. The function range(l, r) can have
+// arbitrary precedence between l and r. If l is smaller than r, then
+// the output is the reverse of range(r, l).
+CLASS_TYPE::CLASS_TYPE(const CLASS_TYPE *u, int l, int r) :
+ sc_value_base(), sgn(), nbits(), ndigits(), digit()
+{
+ bool reversed = false;
+
+ if (l < r) {
+ reversed = true;
+ int tmp = l;
+ l = r;
+ r = tmp;
+ }
+
+ // at this point, l >= r
+
+ // make sure that l and r point to the bits of u
+ r = sc_max(r, 0);
+ l = sc_min(l, u->nbits - 1);
+
+ nbits = num_bits(l - r + 1);
+
+ // nbits can still be <= 0 because l and r have just been updated
+ // with the bounds of u.
+
+ // if u == 0 or the range is out of bounds, return 0
+ if (u->sgn == SC_ZERO || nbits <= num_bits(0)) {
+ sgn = SC_ZERO;
+ if (nbits <= num_bits(0)) {
+ nbits = 1;
+ }
+ ndigits = DIV_CEIL(nbits);
+#ifndef SC_MAX_NBITS
+ digit = new sc_digit[ndigits];
+#endif
+ vec_zero(ndigits, digit);
+ return;
+ }
+
+ // The rest will be executed if u is not zero.
+
+ ndigits = DIV_CEIL(nbits);
+
+ // The number of bits up to and including l and r, respectively.
+ int nl = l + 1;
+ int nr = r + 1;
+
+ // The indices of the digits that have lth and rth bits, respectively.
+ int left_digit = DIV_CEIL(nl) - 1;
+ int right_digit = DIV_CEIL(nr) - 1;
+
+ int nd;
+
+ // The range is performed on the 2's complement representation, so
+ // first get the indices for that.
+ if (u->sgn == SC_NEG)
+ nd = left_digit + 1;
+ else
+ nd = left_digit - right_digit + 1;
+
+ // Allocate memory for the range.
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ digit = new sc_digit[ndigits];
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ // Getting the range on the 2's complement representation.
+ if (u->sgn == SC_NEG) {
+ vec_copy(nd, d, u->digit);
+ vec_complement(nd, d); // d = -d;
+ vec_shift_right(nd, d, r, DIGIT_MASK);
+ } else {
+ for (int i = right_digit; i <= left_digit; ++i)
+ d[i - right_digit] = u->digit[i];
+ vec_shift_right(nd, d, r - right_digit * BITS_PER_DIGIT, 0);
+ }
+
+ vec_zero(ndigits, digit);
+
+ if (!reversed) {
+ vec_copy(sc_min(nd, ndigits), digit, d);
+ } else {
+ // If l < r, i.e., reversed is set, reverse the bits of digit. d
+ // will be used as a temporary store. The following code tries to
+ // minimize the use of bit_ord and digit_ord, which use mod and
+ // div operators. Since these operators are function calls to
+ // standard library routines, they are slow. The main idea in
+ // reversing is "read bits out of d from left to right and push
+ // them into digit using right shifting."
+
+ // Take care of the last digit.
+ int nd_less_1 = nd - 1;
+
+ // Deletions will start from the left end and move one position
+ // after each deletion.
+ sc_digit del_mask = one_and_zeros(bit_ord(l - r));
+
+ while (del_mask) {
+ vec_shift_right(ndigits, digit, 1,
+ ((d[nd_less_1] & del_mask) != 0));
+ del_mask >>= 1;
+ }
+
+ // Take care of the other digits if any.
+
+ // Insertion to digit will always occur at the left end.
+ sc_digit ins_mask = one_and_zeros(BITS_PER_DIGIT - 1);
+
+ for (int j = nd - 2; j >= 0; --j) { // j = nd - 2
+ // Deletions will start from the left end and move one position
+ // after each deletion.
+ del_mask = ins_mask;
+ while (del_mask) {
+ vec_shift_right(ndigits, digit, 1, ((d[j] & del_mask) != 0));
+ del_mask >>= 1;
+ }
+ }
+
+ if (u->sgn == SC_NEG)
+ vec_shift_right(ndigits, digit,
+ ndigits * BITS_PER_DIGIT - length(), DIGIT_MASK);
+ else
+ vec_shift_right(ndigits, digit,
+ ndigits * BITS_PER_DIGIT - length(), 0);
+
+
+ } // if reversed.
+
+ convert_2C_to_SM();
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+}
+
+// This constructor is mainly used in finding a "range" of bits from a
+// number of type OTHER_CLASS_TYPE. The function range(l, r) can have
+// arbitrary precedence between l and r. If l is smaller than r, then
+// the output is the reverse of range(r, l).
+CLASS_TYPE::CLASS_TYPE(const OTHER_CLASS_TYPE *u, int l, int r) :
+ sc_value_base(), sgn(), nbits(), ndigits(), digit()
+{
+ bool reversed = false;
+
+ if (l < r) {
+ reversed = true;
+ int tmp = l;
+ l = r;
+ r = tmp;
+ }
+
+ // at this point, l >= r
+
+ // make sure that l and r point to the bits of u
+ r = sc_max(r, 0);
+ l = sc_min(l, u->nbits - 1);
+
+ nbits = num_bits(l - r + 1);
+
+ // nbits can still be <= 0 because l and r have just been updated
+ // with the bounds of u.
+
+ // if u == 0 or the range is out of bounds, return 0
+ if (u->sgn == SC_ZERO || nbits <= num_bits(0)) {
+ sgn = SC_ZERO;
+ if (nbits <= num_bits(0)) {
+ nbits = 1;
+ }
+ ndigits = DIV_CEIL(nbits);
+#ifndef SC_MAX_NBITS
+ digit = new sc_digit[ndigits];
+#endif
+ vec_zero(ndigits, digit);
+ return;
+ }
+
+ // The rest will be executed if u is not zero.
+
+ ndigits = DIV_CEIL(nbits);
+
+ // The number of bits up to and including l and r, respectively.
+ int nl = l + 1;
+ int nr = r + 1;
+
+ // The indices of the digits that have lth and rth bits, respectively.
+ int left_digit = DIV_CEIL(nl) - 1;
+ int right_digit = DIV_CEIL(nr) - 1;
+
+ int nd;
+
+ // The range is performed on the 2's complement representation, so
+ // first get the indices for that.
+ if (u->sgn == SC_NEG)
+ nd = left_digit + 1;
+ else
+ nd = left_digit - right_digit + 1;
+
+ // Allocate memory for the range.
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ digit = new sc_digit[ndigits];
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ // Getting the range on the 2's complement representation.
+ if (u->sgn == SC_NEG) {
+ vec_copy(nd, d, u->digit);
+ vec_complement(nd, d); // d = -d;
+ vec_shift_right(nd, d, r, DIGIT_MASK);
+ } else {
+ for (int i = right_digit; i <= left_digit; ++i)
+ d[i - right_digit] = u->digit[i];
+ vec_shift_right(nd, d, r - right_digit * BITS_PER_DIGIT, 0);
+ }
+
+ vec_zero(ndigits, digit);
+
+ if (!reversed) {
+ vec_copy(sc_min(nd, ndigits), digit, d);
+ } else {
+ // If l < r, i.e., reversed is set, reverse the bits of digit. d
+ // will be used as a temporary store. The following code tries to
+ // minimize the use of bit_ord and digit_ord, which use mod and
+ // div operators. Since these operators are function calls to
+ // standard library routines, they are slow. The main idea in
+ // reversing is "read bits out of d from left to right and push
+ // them into digit using right shifting."
+
+ // Take care of the last digit.
+ int nd_less_1 = nd - 1;
+
+ // Deletions will start from the left end and move one position
+ // after each deletion.
+ sc_digit del_mask = one_and_zeros(bit_ord(l - r));
+
+ while (del_mask) {
+ vec_shift_right(ndigits, digit, 1,
+ ((d[nd_less_1] & del_mask) != 0));
+ del_mask >>= 1;
+ }
+
+ // Take care of the other digits if any.
+
+ // Insertion to digit will always occur at the left end.
+ sc_digit ins_mask = one_and_zeros(BITS_PER_DIGIT - 1);
+
+ for (int j = nd - 2; j >= 0; --j) { // j = nd - 2
+ // Deletions will start from the left end and move one position
+ // after each deletion.
+ del_mask = ins_mask;
+
+ while (del_mask) {
+ vec_shift_right(ndigits, digit, 1, ((d[j] & del_mask) != 0));
+ del_mask >>= 1;
+ }
+ }
+
+ if (u->sgn == SC_NEG)
+ vec_shift_right(ndigits, digit,
+ ndigits * BITS_PER_DIGIT - length(), DIGIT_MASK);
+ else
+ vec_shift_right(ndigits, digit,
+ ndigits * BITS_PER_DIGIT - length(), 0);
+
+
+ } // if reversed.
+
+ convert_2C_to_SM();
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+}
+
+
+// Print out all the physical attributes.
+void
+CLASS_TYPE::dump(::std::ostream &os) const
+{
+ // Save the current setting, and set the base to decimal.
+ ::std::ios::fmtflags old_flags =
+ os.setf(::std::ios::dec, ::std::ios::basefield);
+
+ os << "width = " << length() << ::std::endl;
+ os << "value = " << *this << ::std::endl;
+ os << "bits = ";
+
+ int len = length();
+
+ for (int i = len - 1; i >= 0; --i) {
+ os << "01"[test(i)];
+ if (--len % 4 == 0)
+ os << " ";
+ }
+
+ os << ::std::endl;
+
+ // Restore old_flags.
+ os.setf(old_flags, ::std::ios::basefield);
+}
+
+
+// Checks to see if bit_num is out of bounds.
+bool
+CLASS_TYPE::check_if_outside(int bit_num) const
+{
+ if ((bit_num < 0) || (num_bits(bit_num) >= nbits)) {
+#ifdef DEBUG_SYSTEMC
+ if (bit_num < 0 || bit_num >= nbits) {
+ std::stringstream msg;
+ msg << CLASS_TYPE_STR "::check_if_outside(int bit_num) : "
+ "bit_num = " << bit_num << " is out of bounds";
+ SC_REPORT_WARNING(sc_core::SC_ID_OUT_OF_BOUNDS_,
+ msg.str().c_str());
+ }
+#endif
+ return true;
+ }
+ return false;
+}
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_nbexterns.cpp -- External functions for both sc_signed and sc_unsigned
+ classes. These functions work on two parameters u and
+ v, and copy the result to the first parameter u. This
+ is also the reason that they are suffixed with _on_help.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_nbexterns.cpp,v $
+// Revision 1.2 2011/02/18 20:19:15 acg
+// Andy Goodrich: updating Copyright notice.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:49:32 acg
+// Added $Log command so that CVS check in comments are reproduced in the
+// source.
+//
+
+#include "systemc/ext/dt/int/sc_nbexterns.hh"
+#include "systemc/ext/utils/functions.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for PLUS operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 3 and 4 and returns the result in u.
+void
+add_on_help(small_type &us, int /* unb */, int und, sc_digit *ud,
+ small_type vs, int /* vnb */, int vnd, const sc_digit *vd)
+{
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ if (us == vs) { // case 3
+ if (und >= vnd)
+ vec_add_on(und, ud, vnd, vd);
+ else
+ vec_add_on2(und, ud, vnd, vd);
+
+ } else { // case 4
+ // vec_cmp expects that und is the number of non-zero digits in ud.
+ int new_und = vec_skip_leading_zeros(und, ud);
+ int cmp_res = vec_cmp(new_und, ud, vnd, vd);
+
+ if (cmp_res == 0) { // u == v
+ us = SC_ZERO;
+ vec_zero(und, ud);
+ return;
+ }
+
+ if (cmp_res > 0) { // u > v
+ vec_sub_on(und, ud, vnd, vd);
+ } else { // u < v
+ us = -us;
+ vec_sub_on2(und, ud, vnd, vd);
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+
+/*
+
+mul_on_help_signed and mul_on_help_unsigned have the same body except
+that CONVERT_SM_to_2C_to_SM and COPY_DIGITS are defined for signed and
+unsigned, respectively. This comment also applies to the
+signed/unsigned versions of div_on_help and mod_on_help. It is
+possible to take COPY_DIGITS out of these functions and create a
+single version of each of these helper functions; however, this will
+impose an onverhead on performance. In the versions below, any change
+in the signed version of a helper function must be carried to a
+corresponding change in the unsigned verion of the same function or
+vice versa.
+
+*/
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions of MULTIPLICATION operators.
+// ----------------------------------------------------------------------------
+
+void
+mul_on_help_signed(small_type &us, int unb, int und, sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+#define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM
+#define COPY_DIGITS copy_digits_signed
+ { // Body of mul_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ sc_digit ud0 = (*ud);
+ sc_digit vd0 = (*vd);
+
+ if ((vnd == 1) && (vd0 == 1)) {
+ us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
+ return;
+ }
+
+ if ((und == 1) && (ud0 == 1)) {
+ COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd);
+ return;
+ }
+
+ if ((und == 1) && (vnd == 1) &&
+ (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
+
+ sc_digit d = ud0 * vd0;
+ COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d);
+ return;
+ }
+
+ int nd = und + vnd;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ if ((und == 1) && (ud0 < HALF_DIGIT_RADIX))
+ vec_mul_small(vnd, vd, ud0, d);
+ else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ vec_mul_small(und, ud, vd0, d);
+ else if (vnd < und)
+ vec_mul(und, ud, vnd, vd, d);
+ else
+ vec_mul(vnd, vd, und, ud, d);
+
+ COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+#undef CONVERT_SM_to_2C_to_SM
+}
+
+
+void
+mul_on_help_unsigned(small_type &us, int unb, int und, sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+#define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM
+#define COPY_DIGITS copy_digits_unsigned
+ { // Body of mul_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ sc_digit ud0 = (*ud);
+ sc_digit vd0 = (*vd);
+
+ if ((vnd == 1) && (vd0 == 1)) {
+ us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
+ return;
+ }
+
+ if ((und == 1) && (ud0 == 1)) {
+ COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd);
+ return;
+ }
+
+ if ((und == 1) && (vnd == 1) &&
+ (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
+
+ sc_digit d = ud0 * vd0;
+ COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d);
+ return;
+ }
+
+ int nd = und + vnd;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ if ((und == 1) && (ud0 < HALF_DIGIT_RADIX))
+ vec_mul_small(vnd, vd, ud0, d);
+ else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ vec_mul_small(und, ud, vd0, d);
+ else if (vnd < und)
+ vec_mul(und, ud, vnd, vd, d);
+ else
+ vec_mul(vnd, vd, und, ud, d);
+
+ COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+#undef CONVERT_SM_to_2C_to_SM
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for DIVISION operators.
+// ----------------------------------------------------------------------------
+
+void
+div_on_help_signed(small_type &us, int unb, int und, sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+#define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM
+#define COPY_DIGITS copy_digits_signed
+ { // Body of div_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+
+ if (cmp_res < 0) { // u < v => u / v = 0 - case 4
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+
+ sc_digit vd0 = (*vd);
+
+ if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) {
+ us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
+ return;
+ }
+
+ // One extra digit for d is allocated to simplify vec_div_*().
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS + 1];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ // u = v => u / v = 1 - case 3
+ if (cmp_res == 0)
+ d[0] = 1;
+ else if ((vnd == 1) && (und == 1))
+ d[0] = (*ud) / vd0;
+ else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ vec_div_small(und, ud, vd0, d);
+ else
+ vec_div_large(und, ud, vnd, vd, d);
+
+ COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+#undef CONVERT_SM_to_2C_to_SM
+}
+
+
+void
+div_on_help_unsigned(small_type &us, int unb, int und, sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+#define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM
+#define COPY_DIGITS copy_digits_unsigned
+ { // Body of div_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+
+ if (cmp_res < 0) { // u < v => u / v = 0 - case 4
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+
+ sc_digit vd0 = (*vd);
+
+ if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) {
+ us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
+ return;
+ }
+
+ // One extra digit for d is allocated to simplify vec_div_*().
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS + 1];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ // u = v => u / v = 1 - case 3
+ if (cmp_res == 0)
+ d[0] = 1;
+ else if ((vnd == 1) && (und == 1))
+ d[0] = (*ud) / vd0;
+ else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ vec_div_small(und, ud, vd0, d);
+ else
+ vec_div_large(und, ud, vnd, vd, d);
+
+ COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+#undef CONVERT_SM_to_2C_to_SM
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for MOD operators.
+// ----------------------------------------------------------------------------
+
+void
+mod_on_help_signed(small_type &us, int unb, int und, sc_digit *ud,
+ int /* vnb */, int vnd, const sc_digit *vd)
+{
+#define COPY_DIGITS copy_digits_signed
+ { // Body of mod_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+
+ // u < v => u % v = u - case 4
+ if (cmp_res < 0)
+ return;
+
+ // u = v => u % v = 0 - case 3
+ if (cmp_res == 0) {
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+ // else if u > v - case 5
+
+ sc_digit vd0 = (*vd);
+
+ if ((vnd == 1) && (vd0 == 1)) {
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+
+ // One extra digit for d is allocated to simplify vec_div_*().
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS + 1];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ if ((vnd == 1) && (und == 1))
+ d[0] = (*ud) % vd0;
+ if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ d[0] = vec_rem_small(und, ud, vd0);
+ else
+ vec_rem_large(und, ud, vnd, vd, d);
+
+ us = check_for_zero(us, nd - 1, d);
+
+ if (us == SC_ZERO)
+ vec_zero(old_und, ud);
+ else
+ COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+}
+
+
+void
+mod_on_help_unsigned(small_type &us, int unb, int und, sc_digit *ud,
+ int /* vnb */, int vnd, const sc_digit *vd)
+{
+#define COPY_DIGITS copy_digits_unsigned
+ { // Body of mod_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+
+ // u < v => u % v = u - case 4
+ if (cmp_res < 0)
+ return;
+
+ // u = v => u % v = 0 - case 3
+ if (cmp_res == 0) {
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+
+ // else if u > v - case 5
+
+ sc_digit vd0 = (*vd);
+
+ if ((vnd == 1) && (vd0 == 1)) {
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+
+ // One extra digit for d is allocated to simplify vec_div_*().
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS + 1];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ if ((vnd == 1) && (und == 1))
+ d[0] = (*ud) % vd0;
+ if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ d[0] = vec_rem_small(und, ud, vd0);
+ else
+ vec_rem_large(und, ud, vnd, vd, d);
+
+ us = check_for_zero(us, nd - 1, d);
+
+ if (us == SC_ZERO)
+ vec_zero(old_und, ud);
+ else
+ COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for AND operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 2-5 and returns the result in u.
+void
+and_on_help(small_type us, int /* unb */, int und, sc_digit *ud,
+ small_type vs, int /* vnb */, int vnd, const sc_digit *vd)
+{
+ sc_digit *x = ud;
+ const sc_digit *y = vd;
+ int xnd = und;
+ int ynd = vnd;
+
+ // Truncate y.
+ if (xnd < ynd)
+ ynd = xnd;
+
+ const sc_digit *xend = (x + xnd);
+ const sc_digit *yend = (y + ynd);
+
+ // x is longer than y.
+ small_type s = mul_signs(us, vs);
+
+ if (s > 0) {
+ if (us > 0) { // case 2
+ while (y < yend)
+ (*x++) &= (*y++);
+ while (x < xend)
+ (*x++) = 0;
+ } else { // case 3
+ sc_digit xcarry = 1;
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x++) = (xcarry & ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += DIGIT_MASK;
+ (*x++) = (xcarry & ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+
+ }
+ } else {
+ if (us > 0) { // case 4
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x++) &= ycarry & DIGIT_MASK;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ ycarry += DIGIT_MASK;
+ (*x++) &= ycarry & DIGIT_MASK;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ } else { // case 5
+ sc_digit xcarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ (*x++) = (xcarry & (*y++)) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend)
+ (*x++) = 0;
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for OR operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 3-5 and returns the result in u.
+void
+or_on_help(small_type us, int /* unb */, int und, sc_digit *ud,
+ small_type vs, int /* vnb */, int vnd, const sc_digit *vd)
+{
+ sc_digit *x = ud;
+ const sc_digit *y = vd;
+ int xnd = und;
+ int ynd = vnd;
+
+ if (xnd < ynd)
+ ynd = xnd;
+
+ const sc_digit *xend = (x + xnd);
+ const sc_digit *yend = (y + ynd);
+
+ // x is longer than y.
+ small_type s = mul_signs(us, vs);
+
+ if (s > 0) {
+ if (us > 0) { // case 3
+ while (y < yend)
+ (*x++) |= (*y++);
+ // No change for the rest of x.
+ } else { // case 4
+ sc_digit xcarry = 1;
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x++) = (xcarry | ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += DIGIT_MASK;
+ (*x++) = (xcarry | ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ }
+ } else {
+ if (us > 0) { // case 5
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x) = ((*x) | ycarry) & DIGIT_MASK;
+ x++;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ ycarry += DIGIT_MASK;
+ (*x) = ((*x) | ycarry) & DIGIT_MASK;
+ x++;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ } else { // case 6
+ sc_digit xcarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ (*x++) = (xcarry | (*y++)) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ (*x++) = xcarry & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for XOR operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 3-5 and returns the result in u.
+void
+xor_on_help(small_type us, int /* unb */, int und, sc_digit *ud,
+ small_type vs, int /* vnb */, int vnd, const sc_digit *vd)
+{
+ sc_digit *x = ud;
+ const sc_digit *y = vd;
+ int xnd = und;
+ int ynd = vnd;
+
+ if (xnd < ynd)
+ ynd = xnd;
+
+ const sc_digit *xend = (x + xnd);
+ const sc_digit *yend = (y + ynd);
+
+ // x is longer than y.
+ small_type s = mul_signs(us, vs);
+
+ if (s > 0) {
+ if (us > 0) { // case 3
+ while (y < yend) {
+ (*x) = ((*x) ^ (*y)) & DIGIT_MASK;
+ x++;
+ y++;
+ }
+ // No change for the rest of x.
+ } else { // case 4
+ sc_digit xcarry = 1;
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x++) = (xcarry ^ ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += DIGIT_MASK;
+ (*x++) = (xcarry ^ ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ }
+ } else {
+ if (us > 0) { // case 5
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x) = ((*x) ^ ycarry) & DIGIT_MASK;
+ x++;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ ycarry += DIGIT_MASK;
+ (*x) = ((*x) ^ ycarry) & DIGIT_MASK;
+ x++;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ } else { // case 6
+ sc_digit xcarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ (*x++) = (xcarry ^ (*y++)) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ (*x++) = xcarry & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ }
+ }
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_nbfriends.inc -- Friend functions for both sc_signed and sc_unsigned
+ classes. The vec_* functions are called through either
+ these functions or those in sc_nbexterns.cpp. These
+ functions perform their work on two inputs u and v, and
+ return the result object. The functions in
+ sc_nbexterns.cpp perform their work on one of their
+ inputs.
+
+ The functions here try to use faster algorithms in case
+ the input numbers are small. The bitwise functions (and,
+ or, and xor) need the 2's complement representations of
+ their inputs. Instead of complementing their inputs
+ first and then processing, they complement their inputs
+ while processing without allocating extra temporary
+ memory.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// ----------------------------------------------------------------------------
+// Naming conventions:
+// For sc_signed or sc_unsigned number u:
+// us : u's sign, unb : u's number of bits,
+// und : u's number of digits, ud : u's digits array.
+// ----------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------
+// SECTION: Friend functions for PLUS operators.
+// ----------------------------------------------------------------------------
+
+// Handles cases 3 and 4 and returns the result.
+CLASS_TYPE
+ADD_HELPER(small_type us, int unb, int und, const sc_digit *ud,
+ small_type vs, int vnb, int vnd, const sc_digit *vd)
+{
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int nb = sc_max(unb, vnb);
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ test_bound(nb);
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ d[nd - 1] = d[nd - 2] = 0;
+
+ // case 3
+ if (us == vs) {
+
+ ++nb;
+
+ if ((und == 1) && (vnd == 1)) {
+ sc_digit carry = (*ud) + (*vd);
+ d[0] = carry & DIGIT_MASK;
+ d[1] = carry >> BITS_PER_DIGIT;
+ } else if (und >= vnd) {
+ vec_add(und, ud, vnd, vd, d);
+ } else {
+ vec_add(vnd, vd, und, ud, d);
+ }
+ } else {
+ // case 4
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+
+ if (cmp_res == 0) { // u == v
+#ifndef SC_MAX_NBITS
+ delete[] d;
+#endif
+ return CLASS_TYPE();
+ }
+
+ if (cmp_res > 0) { // u > v
+ if ((und == 1) && (vnd == 1))
+ d[0] = (*ud) - (*vd);
+ else
+ vec_sub(und, ud, vnd, vd, d);
+ } else { // u < v
+ us = -us;
+ if ((und == 1) && (vnd == 1))
+ d[0] = (*vd) - (*ud);
+ else
+ vec_sub(vnd, vd, und, ud, d);
+ }
+ }
+ return CLASS_TYPE(us, nb, nd, d);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Friend functions of MULTIPLICATION operators.
+// ----------------------------------------------------------------------------
+
+// Handles the case 4 and returns the result.
+CLASS_TYPE
+MUL_HELPER(small_type s, int unb, int und, const sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int nb = unb + vnb;
+ int nd = und + vnd;
+
+#ifdef SC_MAX_NBITS
+ test_bound(nb);
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ sc_digit ud0 = (*ud);
+ sc_digit vd0 = (*vd);
+
+ if ((vnd == 1) && (vd0 == 1)) {
+ vec_copy(und, d, ud);
+ } else if ((und == 1) && (ud0 == 1)) {
+ vec_copy(vnd, d, vd);
+ } else if ((und == 1) && (vnd == 1) &&
+ (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
+ d[0] = ud0 * vd0;
+ } else if ((und == 1) && (ud0 < HALF_DIGIT_RADIX)) {
+ vec_mul_small(vnd, vd, ud0, d);
+ } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
+ vec_mul_small(und, ud, vd0, d);
+ } else if (vnd < und) {
+ vec_mul(und, ud, vnd, vd, d);
+ } else {
+ vec_mul(vnd, vd, und, ud, d);
+ }
+ return CLASS_TYPE(s, nb, nd, d);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Friend functions for DIVISION operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 3-4 and returns the result.
+CLASS_TYPE
+DIV_HELPER(small_type s, int unb, int und, const sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+
+ // u < v => u / v = 0 - case 4
+ if (cmp_res < 0)
+ return CLASS_TYPE();
+
+ // One extra digit for d is allocated to simplify vec_div_*().
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS + 1];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+ sc_digit vd0 = (*vd);
+
+ // u = v => u / v = 1 - case 3
+ if (cmp_res == 0) {
+ d[0] = 1;
+ // else if u > v - case 5
+ } else if ((vnd == 1) && (vd0 == 1)) {
+ vec_copy(und, d, ud);
+ } else if ((vnd == 1) && (und == 1)) {
+ d[0] = (*ud) / vd0;
+ } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
+ vec_div_small(und, ud, vd0, d);
+ } else {
+ vec_div_large(und, ud, vnd, vd, d);
+ }
+
+ return CLASS_TYPE(s, sc_max(unb, vnb), nd - 1, d);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Friend functions for MOD operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 3-4 and returns the result.
+CLASS_TYPE
+MOD_HELPER(small_type us, int unb, int und, const sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+ // u = v => u % v = 0 - case 3
+ if (cmp_res == 0)
+ return CLASS_TYPE();
+
+ sc_digit vd0 = (*vd);
+ if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1))
+ return CLASS_TYPE();
+
+ // One extra digit for d is allocated to simplify vec_div_*().
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS + 1];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ // u < v => u % v = u - case 4
+ if (cmp_res < 0) {
+ vec_copy(und, d, ud);
+ // else if u > v - case 5
+ } else if ((vnd == 1) && (und == 1)) {
+ d[0] = (*ud) % vd0;
+ } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
+ d[0] = vec_rem_small(und, ud, vd0);
+ } else {
+ vec_rem_large(und, ud, vnd, vd, d);
+ }
+
+ us = check_for_zero(us, nd - 1, d);
+
+ if (us == SC_ZERO) {
+#ifndef SC_MAX_NBITS
+ delete[] d;
+#endif
+ return CLASS_TYPE();
+ } else {
+ return CLASS_TYPE(us, sc_min(unb, vnb), nd - 1, d);
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Friend functions for AND operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 2-5 and returns the result.
+CLASS_TYPE
+AND_HELPER(small_type us, int unb, int und, const sc_digit *ud,
+ small_type vs, int vnb, int vnd, const sc_digit *vd)
+{
+ int nb = sc_max(unb, vnb);
+ int nd = sc_max(und, vnd);
+
+#ifdef SC_MAX_NBITS
+ sc_digit dbegin[MAX_NDIGITS];
+#else
+ sc_digit *dbegin = new sc_digit[nd];
+#endif
+
+ sc_digit *d = dbegin;
+
+ const sc_digit *x;
+ const sc_digit *y;
+ int xnd;
+ int ynd;
+ small_type xs;
+ small_type ys;
+
+ if (und >= vnd) {
+ x = ud;
+ y = vd;
+ xnd = und;
+ ynd = vnd;
+ xs = us;
+ ys = vs;
+ } else {
+ y = ud;
+ x = vd;
+ ynd = und;
+ xnd = vnd;
+ ys = us;
+ xs = vs;
+ }
+
+ const sc_digit *xend = (x + xnd);
+ const sc_digit *yend = (y + ynd);
+
+ // x is longer than y.
+ small_type s = mul_signs(xs, ys);
+ if (s > 0) {
+ if (xs > 0) { // case 2
+ while (y < yend)
+ (*d++) = (*x++) & (*y++);
+ while (x++ < xend)
+ (*d++) = 0;
+ } else { // case 3
+ sc_digit xcarry = 1;
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*d++) = (xcarry & ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ ycarry += DIGIT_MASK;
+ (*d++) = (xcarry & ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ }
+ } else {
+ if (xs > 0) { // case 4
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*d++) = ((*x++) & ycarry) & DIGIT_MASK;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ ycarry += DIGIT_MASK;
+ (*d++) = ((*x++) & ycarry) & DIGIT_MASK;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ } else { // case 5
+ sc_digit xcarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ (*d++) = (xcarry & (*y++)) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ while (x++ < xend)
+ (*d++) = 0;
+ }
+ }
+ s = convert_signed_2C_to_SM(nb, nd, dbegin);
+ return CLASS_TYPE(s, nb, nd, dbegin);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Friend functions for OR operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 3-5 and returns the result.
+CLASS_TYPE
+OR_HELPER(small_type us, int unb, int und, const sc_digit *ud,
+ small_type vs, int vnb, int vnd, const sc_digit *vd)
+{
+ int nb = sc_max(unb, vnb);
+ int nd = sc_max(und, vnd);
+
+#ifdef SC_MAX_NBITS
+ sc_digit dbegin[MAX_NDIGITS];
+#else
+ sc_digit *dbegin = new sc_digit[nd];
+#endif
+ sc_digit *d = dbegin;
+ const sc_digit *x;
+ const sc_digit *y;
+ int xnd;
+ int ynd;
+ small_type xs;
+ small_type ys;
+
+ if (und >= vnd) {
+ x = ud;
+ y = vd;
+ xnd = und;
+ ynd = vnd;
+ xs = us;
+ ys = vs;
+ } else {
+ y = ud;
+ x = vd;
+ ynd = und;
+ xnd = vnd;
+ ys = us;
+ xs = vs;
+ }
+
+ const sc_digit *xend = (x + xnd);
+ const sc_digit *yend = (y + ynd);
+
+ // x is longer than y.
+ small_type s = mul_signs(xs, ys);
+ if (s > 0) {
+ if (xs > 0) { // case 3
+ while (y < yend)
+ (*d++) = (*x++) | (*y++);
+ while (x < xend)
+ (*d++) = (*x++);
+ } else { // case 4
+ sc_digit xcarry = 1;
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*d++) = (xcarry | ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ ycarry += DIGIT_MASK;
+ (*d++) = (xcarry | ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ }
+ } else {
+ if (xs > 0) { // case 5
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*d++) = ((*x++) | ycarry) & DIGIT_MASK;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ ycarry += DIGIT_MASK;
+ (*d++) = ((*x++) | ycarry) & DIGIT_MASK;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ } else { // case 6
+ sc_digit xcarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ (*d++) = (xcarry | (*y++)) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ (*d++) = xcarry & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ }
+ }
+ s = convert_signed_2C_to_SM(nb, nd, dbegin);
+ return CLASS_TYPE(s, nb, nd, dbegin);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Friend functions for XOR operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 3-5 and returns the result.
+CLASS_TYPE
+XOR_HELPER(small_type us, int unb, int und, const sc_digit *ud,
+ small_type vs, int vnb, int vnd, const sc_digit *vd)
+{
+ int nb = sc_max(unb, vnb);
+ int nd = sc_max(und, vnd);
+
+#ifdef SC_MAX_NBITS
+ sc_digit dbegin[MAX_NDIGITS];
+#else
+ sc_digit *dbegin = new sc_digit[nd];
+#endif
+
+ sc_digit *d = dbegin;
+
+ const sc_digit *x;
+ const sc_digit *y;
+ int xnd;
+ int ynd;
+ small_type xs;
+ small_type ys;
+
+ if (und >= vnd) {
+ x = ud;
+ y = vd;
+ xnd = und;
+ ynd = vnd;
+ xs = us;
+ ys = vs;
+ } else {
+ y = ud;
+ x = vd;
+ ynd = und;
+ xnd = vnd;
+ ys = us;
+ xs = vs;
+ }
+
+ const sc_digit *xend = (x + xnd);
+ const sc_digit *yend = (y + ynd);
+
+ // x is longer than y.
+ small_type s = mul_signs(xs, ys);
+ if (s > 0) {
+ if (xs > 0) { // case 3
+ while (y < yend)
+ (*d++) = ((*x++) ^ (*y++)) & DIGIT_MASK;
+ while (x < xend)
+ (*d++) = (*x++);
+ } else { // case 4
+ sc_digit xcarry = 1;
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*d++) = (xcarry ^ ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ ycarry += DIGIT_MASK;
+ (*d++) = (xcarry ^ ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ }
+ } else {
+ if (xs > 0) { // case 5
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*d++) = ((*x++) ^ ycarry) & DIGIT_MASK;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ ycarry += DIGIT_MASK;
+ (*d++) = ((*x++) ^ ycarry) & DIGIT_MASK;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ } else { // case 6
+ sc_digit xcarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ (*d++) = (xcarry ^ (*y++)) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x++) & DIGIT_MASK);
+ (*d++) = xcarry & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ }
+ }
+ s = convert_signed_2C_to_SM(nb, nd, dbegin);
+ return CLASS_TYPE(s, nb, nd, dbegin);
+}
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_nbutils.cpp -- External and friend functions for both sc_signed and
+ sc_unsigned classes.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_nbutils.cpp,v $
+// Revision 1.4 2011/08/24 22:05:46 acg
+// Torsten Maehne: initialization changes to remove warnings.
+//
+// Revision 1.3 2011/02/18 20:19:15 acg
+// Andy Goodrich: updating Copyright notice.
+//
+// Revision 1.2 2007/11/04 21:26:40 acg
+// Andy Goodrich: added a buffer to the allocation of the q array to address
+// an issue with references outside the array by 1 byte detected by valgrind.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:49:32 acg
+// Added $Log command so that CVS check in comments are reproduced in the
+// source.
+//
+
+#include <cctype>
+#include <cstdio>
+#include <cstring>
+#include <sstream>
+
+#include "systemc/ext/dt/int/sc_nbutils.hh"
+#include "systemc/ext/utils/functions.hh"
+
+namespace sc_dt
+{
+
+// only used within vec_from_str (non-standard, deprecated)
+static inline void
+is_valid_base(sc_numrep base)
+{
+ switch (base) {
+ case SC_NOBASE: case SC_BIN:
+ case SC_OCT: case SC_DEC:
+ case SC_HEX:
+ break;
+ case SC_BIN_US: case SC_BIN_SM:
+ case SC_OCT_US: case SC_OCT_SM:
+ case SC_HEX_US: case SC_HEX_SM:
+ case SC_CSD:
+ SC_REPORT_ERROR("not implemented",
+ "is_valid_base( sc_numrep base ) : "
+ "bases SC_CSD, or ending in _US and _SM are "
+ "not supported");
+ break;
+ default:
+ std::stringstream msg;
+ msg << "is_valid_base( sc_numrep base ) : base = " << base <<
+ " is not valid";
+ SC_REPORT_ERROR("value is not valid", msg.str().c_str() );
+ }
+}
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_numrep
+//
+// Enumeration of number representations for character string conversion.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_numrep numrep)
+{
+ switch (numrep) {
+#define CASE_ENUM2STR(Value) case Value: return #Value
+
+ CASE_ENUM2STR(SC_DEC);
+
+ CASE_ENUM2STR(SC_BIN);
+ CASE_ENUM2STR(SC_BIN_US);
+ CASE_ENUM2STR(SC_BIN_SM);
+
+ CASE_ENUM2STR(SC_OCT);
+ CASE_ENUM2STR(SC_OCT_US);
+ CASE_ENUM2STR(SC_OCT_SM);
+
+ CASE_ENUM2STR(SC_HEX);
+ CASE_ENUM2STR(SC_HEX_US);
+ CASE_ENUM2STR(SC_HEX_SM);
+
+ CASE_ENUM2STR(SC_CSD);
+
+#undef CASE_ENUM2STR
+
+ default:
+ return "unknown";
+ }
+}
+
+// ----------------------------------------------------------------------------
+// SECTION: General utility functions.
+// ----------------------------------------------------------------------------
+
+// Return the number of characters to advance the source of c. This
+// function implements one move of the FSM to parse the following
+// regular expressions. Error checking is done in the caller.
+
+small_type
+fsm_move(char c, small_type &b, small_type &s, small_type &state)
+{
+ // Possible regular expressions (REs):
+ // Let N = any digit depending on the base.
+ // 1. [0|1|..|9]N*
+ // 2. [+|-][0|1|..|9]N*
+ // 3. 0[b|B|d|D|o|O|x|X][0|1|..|F]N*
+ // 4. [+|-]?0[b|B|d|D|o|O|x|X][0|1|..|F]N*
+ //
+ // The finite state machine (FMS) to parse these regular expressions
+ // has 4 states, 0 to 3. 0 is the initial state and 3 is the final
+ // state.
+ //
+ // Default sign = SC_POS, default base = NB_DEFAULT_BASE.
+
+ switch (state) {
+ case 0: // The initial state.
+ switch (c) {
+ case '0': s = SC_POS; state = 1; return 0; // RE 1 or 3
+ case '+': s = SC_POS; state = 2; return 1; // RE 2
+ case '-': s = SC_NEG; state = 2; return 1; // RE 2
+ default:
+ s = SC_POS; b = NB_DEFAULT_BASE; state = 3; return 0; // RE 1
+ }
+ // break; //unreachable code
+ case 1: // 0...
+ switch (c) {
+ case 'x': case 'X': b = SC_HEX; state = 3; return 2; // RE 3 or 4
+ case 'd': case 'D': b = SC_DEC; state = 3; return 2; // RE 3 or 4
+ case 'o': case 'O': b = SC_OCT; state = 3; return 2; // RE 3 or 4
+ case 'b': case 'B': b = SC_BIN; state = 3; return 2; // RE 3 or 4
+ default: b = NB_DEFAULT_BASE; state = 3; return 0; // RE 1
+ }
+ // break; //unreachable code
+ case 2: // +... or -...
+ switch (c) {
+ case '0': state = 1; return 0; // RE 2 or 4
+ default: b = NB_DEFAULT_BASE; state = 3; return 0; // RE 2
+ }
+ // break; //unreachable code
+ case 3: // The final state.
+ break;
+ default:
+ // Any other state is not possible.
+ sc_assert((0 <= state) && (state <= 3));
+ } // switch
+ return 0;
+}
+
+
+// Get base b and sign s of the number in the char string v. Return a
+// pointer to the first char after the point where b and s are
+// determined or where the end of v is reached. The input string v has
+// to be null terminated.
+const char *
+get_base_and_sign(const char *v, small_type &b, small_type &s)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert(v != NULL);
+#endif
+ const small_type STATE_START = 0;
+ const small_type STATE_FINISH = 3;
+
+ // Default sign = SC_POS, default base = 10.
+ s = SC_POS;
+ b = NB_DEFAULT_BASE;
+
+ small_type state = STATE_START;
+ small_type nskip = 0; // Skip that many chars.
+ const char *u = v;
+
+ while (*u) {
+ if (isspace(*u)) { // Skip white space.
+ ++u;
+ } else {
+ nskip += fsm_move(*u, b, s, state);
+ if (state == STATE_FINISH)
+ break;
+ else
+ ++u;
+ }
+ }
+
+ // Test to see if the above loop executed more than it should
+ // have. The max number of skipped chars is equal to the length of
+ // the longest format specifier, e.g., "-0x".
+ sc_assert(nskip <= 3);
+
+ v += nskip;
+
+ // Handles empty strings or strings without any digits after the
+ // base or base and sign specifier.
+ if (*v == '\0') {
+ static const char msg[] =
+ "get_base_and_sign( const char* v, small_type&, small_type& ) : "
+ "v = \"\" is not valid";
+ SC_REPORT_ERROR("conversion failed", msg);
+ }
+ return v;
+}
+
+//-----------------------------------------------------------------------------
+//"parse_binary_bits"
+//
+// This function parses the supplied string into the supplied vector as a
+// right justified bit value.
+// src_p -> character string representing the bits to be parsed.
+// dst_n = number of words in data_p and ctrl_p.
+// data_p -> words w/BITS_PER_DIGIT bits to receive the value's data bits.
+// ctrl_p -> words w/BITS_PER_DIGIT bits to receive the value's control
+// bits, or zero.
+// Result is true if value was non-zero.
+//-----------------------------------------------------------------------------
+void
+parse_binary_bits(const char *src_p, int dst_n,
+ sc_digit *data_p, sc_digit *ctrl_p)
+{
+ int bit_i; // Number of bit now processing.
+ sc_digit ctrl; // Control word now assembling.
+ sc_digit data; // Data word now assembling.
+ int delta_n; // src_n - dst_n*BITS_PER_DIGIT.
+ int src_i; // Index in src_p now accessing (left to right).
+ int src_n; // Length of source that is left in bits.
+ int word_i; // Bit within word now accessing (left to right).
+
+ // MAKE SURE WE HAVE A STRING TO PARSE:
+ if (src_p == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is zero");
+ return;
+ }
+ if (*src_p == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is empty");
+ return;
+ }
+
+
+ // INDEX INTO THE SOURCE TO A DEPTH THAT WILL ACCOMODATE OUR SIZE:
+ //
+ // If the source is smaller than our value initialize our value to zero.
+
+ src_n = strlen(src_p);
+ delta_n = src_n - (dst_n*BITS_PER_DIGIT);
+ if (delta_n > 0) {
+ src_p = &src_p[delta_n];
+ src_n -= delta_n;
+ } else {
+ for (word_i = 0; word_i < dst_n; word_i++)
+ data_p[word_i] = 0;
+ if (ctrl_p)
+ for (word_i = 0; word_i < dst_n; word_i++)
+ ctrl_p[word_i] = 0;
+ }
+
+ // LOOP OVER THE SOURCE ASSEMBLING WORDS AND PLACING THEM IN OUR VALUE:
+ //
+ // We stride right to left through the source in BITS_PER_DIGIT chunks.
+ // Each of those chunks is processed from left to right a bit at a time.
+ // We process the high order word specially, since there are less bits.
+ src_n = src_n - BITS_PER_DIGIT;
+ for (word_i=0; word_i < dst_n; word_i++) {
+ src_i = src_n;
+
+ // PARTIAL LAST WORD TO ASSEMBLE:
+ if (src_i < 0) {
+ src_n += BITS_PER_DIGIT;
+ data = 0;
+ ctrl = 0;
+ for (src_i = 0; src_i < src_n; src_i++) {
+ ctrl = ctrl << 1;
+ data = data << 1;
+ switch (src_p[src_i]) {
+ case 'X':
+ case 'x': ctrl = ctrl | 1; data = data | 1; break;
+ case '1': data = data | 1; break;
+ case 'Z':
+ case 'z': ctrl = ctrl | 1; break;
+ case '0': break;
+ default:
+ {
+ std::stringstream msg;
+ msg << "character string '" << src_p <<
+ "' is not valid";
+ SC_REPORT_ERROR("conversion failed",
+ msg.str().c_str());
+ return;
+ }
+ break;
+ }
+ }
+ if (ctrl_p)
+ ctrl_p[word_i] = ctrl;
+ data_p[word_i] = data;
+ break;
+ }
+
+ // FULL WORD TO BE ASSEMBLED:
+ ctrl = 0;
+ data = 0;
+ for (bit_i = 0; bit_i < BITS_PER_DIGIT; bit_i++) {
+ ctrl = ctrl << 1;
+ data = data << 1;
+ switch (src_p[src_i++]) {
+ case 'X':
+ case 'x': ctrl = ctrl | 1; data = data | 1; break;
+ case '1': data = data | 1; break;
+ case 'Z':
+ case 'z': ctrl = ctrl | 1; break;
+ case '0': break;
+ default:
+ {
+ std::stringstream msg;
+ msg << "character string '" << src_p <<
+ "' is not valid";
+ SC_REPORT_ERROR("conversion failed",
+ msg.str().c_str());
+ return;
+ }
+ break;
+ }
+ }
+ if (ctrl_p)
+ ctrl_p[word_i] = ctrl;
+ data_p[word_i] = data;
+ src_n = src_n - BITS_PER_DIGIT;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//"parse_hex_bits"
+//
+// This function parses the supplied string into the supplied vector as a
+// right justified bit value.
+// src_p -> character string representing the bits to be parsed.
+// dst_n = number of words in data_p and ctrl_p.
+// data_p -> words w/32 bits to receive the value's data bits.
+// ctrl_p -> words w/32 bits to receive the value's control bits,
+// or zero.
+// Result is true if value was non-zero.
+//-----------------------------------------------------------------------------
+void
+parse_hex_bits(const char *src_p, int dst_n,
+ sc_digit *data_p, sc_digit *ctrl_p)
+{
+ sc_digit ctrl; // Control word now assembling.
+ sc_digit data; // Data word now assembling.
+ int delta_n; // src_n - dst_n*BITS_PER_DIGIT.
+ int digit_i; // Number of digit now processing.
+ int src_i; // Index in src_p now accessing (left to right).
+ int src_n; // Length of source that is left in bits.
+ int word_i; // Bit within word now accessing (left to right).
+
+ // MAKE SURE WE HAVE A STRING TO PARSE:
+ if (src_p == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is zero");
+ return;
+ }
+ if (*src_p == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is empty");
+ return;
+ }
+
+ // INDEX INTO THE SOURCE TO A DEPTH THAT WILL ACCOMODATE OUR SIZE:
+ //
+ // If the source is smaller than our value initialize our value to zero.
+ src_n = strlen(src_p);
+ delta_n = src_n - (dst_n*8);
+ if (delta_n > 0) {
+ src_p = &src_p[delta_n];
+ src_n -= delta_n;
+ } else {
+ for (word_i = 0; word_i < dst_n; word_i++)
+ data_p[word_i] = 0;
+ if (ctrl_p)
+ for (word_i = 0; word_i < dst_n; word_i++)
+ ctrl_p[word_i] = 0;
+ }
+
+ // LOOP OVER THE SOURCE ASSEMBLING WORDS AND PLACING THEM IN OUR VALUE:
+ //
+ // We stride right to left through the source in BITS_PER_DIGIT chunks.
+ // Each of those chunks is processed from left to right a bit at a time.
+ // We process the high order word specially, since there are less bits.
+ src_n = src_n - 8;
+ for (word_i = 0; word_i < dst_n; word_i++) {
+ src_i = src_n;
+
+ // PARTIAL LAST WORD TO ASSEMBLE:
+ if (src_i < 0) {
+ src_n += 8;
+ data = 0;
+ ctrl = 0;
+ for (src_i = 0; src_i < src_n; src_i++) {
+ ctrl = ctrl << 4;
+ data = data << 4;
+ switch (src_p[src_i]) {
+ case 'X':
+ case 'x': ctrl = ctrl | 15; data = data | 15; break;
+ case 'F':
+ case 'f': data = data | 15; break;
+ case 'E':
+ case 'e': data = data | 14; break;
+ case 'D':
+ case 'd': data = data | 13; break;
+ case 'C':
+ case 'c': data = data | 12; break;
+ case 'B':
+ case 'b': data = data | 11; break;
+ case 'A':
+ case 'a': data = data | 10; break;
+ case '9': data = data | 9; break;
+ case '8': data = data | 8; break;
+ case '7': data = data | 7; break;
+ case '6': data = data | 6; break;
+ case '5': data = data | 5; break;
+ case '4': data = data | 4; break;
+ case '3': data = data | 3; break;
+ case '2': data = data | 2; break;
+ case '1': data = data | 1; break;
+ case '0': break;
+ case 'Z':
+ case 'z': ctrl = ctrl | 15; break;
+ default:
+ {
+ std::stringstream msg;
+ msg << "character string '" << src_p <<
+ "' is not valid";
+ SC_REPORT_ERROR("conversion failed",
+ msg.str().c_str());
+ return;
+ }
+ break;
+ }
+ }
+ if (ctrl_p)
+ ctrl_p[word_i] = ctrl;
+ data_p[word_i] = data;
+ break;
+ }
+
+ // FULL WORD TO BE ASSEMBLED:
+ ctrl = 0;
+ data = 0;
+ for (digit_i = 0; digit_i < 8; digit_i++) {
+ ctrl = ctrl << 4;
+ data = data << 4;
+ switch (src_p[src_i++]) {
+ case 'X':
+ case 'x': ctrl = ctrl | 15; data = data | 15; break;
+ case 'F':
+ case 'f': data = data | 15; break;
+ case 'E':
+ case 'e': data = data | 14; break;
+ case 'D':
+ case 'd': data = data | 13; break;
+ case 'C':
+ case 'c': data = data | 12; break;
+ case 'B':
+ case 'b': data = data | 11; break;
+ case 'A':
+ case 'a': data = data | 10; break;
+ case '9': data = data | 9; break;
+ case '8': data = data | 8; break;
+ case '7': data = data | 7; break;
+ case '6': data = data | 6; break;
+ case '5': data = data | 5; break;
+ case '4': data = data | 4; break;
+ case '3': data = data | 3; break;
+ case '2': data = data | 2; break;
+ case '1': data = data | 1; break;
+ case '0': break;
+ case 'Z':
+ case 'z': ctrl = ctrl | 15; break;
+ default:
+ {
+ std::stringstream msg;
+ msg << "character string '" << src_p << "' is not valid";
+ SC_REPORT_ERROR("conversion failed",
+ msg.str().c_str() );
+ return;
+ }
+ break;
+ }
+ }
+ if (ctrl_p)
+ ctrl_p[word_i] = ctrl;
+ data_p[word_i] = data;
+ src_n = src_n - BITS_PER_DIGIT;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Utility functions involving unsigned vectors.
+// ----------------------------------------------------------------------------
+
+// Read u from a null terminated char string v. Note that operator>>
+// in sc_nbcommon.cpp is similar to this function.
+small_type
+vec_from_str(int unb, int und, sc_digit *u, const char *v, sc_numrep base)
+{
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert((unb > 0) && (und > 0) && (u != NULL));
+ sc_assert(v != NULL);
+#endif
+ is_valid_base(base);
+
+ small_type b, s; // base and sign.
+
+ v = get_base_and_sign(v, b, s);
+
+ if (base != SC_NOBASE) {
+ if (b == NB_DEFAULT_BASE) {
+ b = base;
+ } else {
+ std::stringstream msg;
+ msg << "vec_from_str( int, int, sc_digit*, const char*, " <<
+ "sc_numrep base ) : base = " << base <<
+ " does not match the default base";
+ SC_REPORT_ERROR("conversion failed",
+ msg.str().c_str());
+ return 0;
+ }
+ }
+
+ vec_zero(und, u);
+
+ char c;
+ for (; (c = *v); ++v) {
+ if (isalnum(c)) {
+ small_type val; // Numeric value of a char.
+
+ if (isalpha(c)) // Hex digit.
+ val = toupper(c) - 'A' + 10;
+ else
+ val = c - '0';
+
+ if (val >= b) {
+ std::stringstream msg;
+ msg << "vec_from_str( int, int, sc_digit*, const char*, " <<
+ "sc_numrep base ) : '" << *v << "' is not a valid " <<
+ "digit in base " << b;
+ SC_REPORT_ERROR("conversion failed",
+ msg.str().c_str());
+ return 0;
+ }
+
+ // digit = digit * b + val;
+ vec_mul_small_on(und, u, b);
+
+ if (val)
+ vec_add_small_on(und, u, val);
+ } else {
+ std::stringstream msg;
+ msg << "vec_from_str( int, int, sc_digit*, const char*, " <<
+ "sc_numrep base ) : '" << *v << "' is not a valid " <<
+ "digit in base " << b;
+ SC_REPORT_ERROR("conversion failed",
+ msg.str().c_str());
+ return 0;
+ }
+ }
+
+ return convert_signed_SM_to_2C_to_SM(s, unb, und, u);
+}
+
+
+// All vec_ functions assume that the vector to hold the result,
+// called w, has sufficient length to hold the result. For efficiency
+// reasons, we do not test whether or not we are out of bounds.
+
+// Compute w = u + v, where w, u, and v are vectors.
+// - ulen >= vlen
+// - wlen >= sc_max(ulen, vlen) + 1
+void
+vec_add(int ulen, const sc_digit *u, int vlen, const sc_digit *v, sc_digit *w)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+ sc_assert(w != NULL);
+ sc_assert(ulen >= vlen);
+#endif
+
+ const sc_digit *uend = (u + ulen);
+ const sc_digit *vend = (v + vlen);
+
+ sc_digit carry = 0; // Also used as sum to save space.
+
+ // Add along the shorter v.
+ while (v < vend) {
+ carry += (*u++) + (*v++);
+ (*w++) = carry & DIGIT_MASK;
+ carry >>= BITS_PER_DIGIT;
+ }
+
+ // Propagate the carry.
+ while (carry && (u < uend)) {
+ carry = (*u++) + 1;
+ (*w++) = carry & DIGIT_MASK;
+ carry >>= BITS_PER_DIGIT;
+ }
+
+ // Copy the rest of u to the result.
+ while (u < uend)
+ (*w++) = (*u++);
+
+ // Propagate the carry if it is still 1.
+ if (carry)
+ (*w) = 1;
+}
+
+
+// Compute u += v, where u and v are vectors.
+// - ulen >= vlen
+void
+vec_add_on(int ulen, sc_digit *ubegin, int vlen, const sc_digit *v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (ubegin != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+ sc_assert(ulen >= vlen);
+#endif
+
+ sc_digit *u = ubegin;
+ const sc_digit *uend = (u + ulen);
+ const sc_digit *vend = (v + vlen);
+
+ sc_digit carry = 0; // Also used as sum to save space.
+
+ // Add along the shorter v.
+ while (v < vend) {
+ carry += (*u) + (*v++);
+ (*u++) = carry & DIGIT_MASK;
+ carry >>= BITS_PER_DIGIT;
+ }
+
+ // Propagate the carry.
+ while (carry && (u < uend)) {
+ carry = (*u) + 1;
+ (*u++) = carry & DIGIT_MASK;
+ carry >>= BITS_PER_DIGIT;
+ }
+
+#ifdef DEBUG_SYSTEMC
+ if (carry != 0) {
+ SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_,
+ "vec_add_on( int, sc_digit*, int, const "
+ "sc_digit* ) : "
+ "result of addition is wrapped around");
+ }
+#endif
+}
+
+
+// Compute u += v, where u and v are vectors.
+// - ulen < vlen
+void
+vec_add_on2(int ulen, sc_digit *ubegin, int,
+#ifdef DEBUG_SYSTEMC
+ vlen,
+#endif
+ const sc_digit *v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (ubegin != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+ sc_assert(ulen < vlen);
+#endif
+
+ sc_digit *u = ubegin;
+ const sc_digit *uend = (u + ulen);
+
+ sc_digit carry = 0; // Also used as sum to save space.
+
+ // Add along the shorter u.
+ while (u < uend) {
+ carry += (*u) + (*v++);
+ (*u++) = carry & DIGIT_MASK;
+ carry >>= BITS_PER_DIGIT;
+ }
+
+#ifdef DEBUG_SYSTEMC
+ if (carry != 0) {
+ SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_,
+ "vec_add_on2( int, sc_digit*, int, const "
+ "sc_digit* ) : "
+ "result of addition is wrapped around");
+ }
+#endif
+}
+
+
+// Compute w = u + v, where w and u are vectors, and v is a scalar.
+void
+vec_add_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *w)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert(w != NULL);
+#endif
+
+ const sc_digit *uend = (u + ulen);
+
+ // Add along the shorter v.
+ sc_digit carry = (*u++) + v;
+ (*w++) = carry & DIGIT_MASK;
+ carry >>= BITS_PER_DIGIT;
+
+ // Propagate the carry.
+ while (carry && (u < uend)) {
+ carry = (*u++) + 1;
+ (*w++) = carry & DIGIT_MASK;
+ carry >>= BITS_PER_DIGIT;
+ }
+
+ // Copy the rest of u to the result.
+ while (u < uend)
+ (*w++) = (*u++);
+
+ // Propagate the carry if it is still 1.
+ if (carry)
+ (*w) = 1;
+}
+
+// Compute u += v, where u is vectors, and v is a scalar.
+void
+vec_add_small_on(int ulen, sc_digit *u, sc_digit v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+#endif
+
+ int i = 0;
+
+ while (v && (i < ulen)) {
+ v += u[i];
+ u[i++] = v & DIGIT_MASK;
+ v >>= BITS_PER_DIGIT;
+ }
+
+#ifdef DEBUG_SYSTEMC
+ if (v != 0) {
+ SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_,
+ "vec_add_small_on( int, sc_digit*, unsigned "
+ "long ) : "
+ "result of addition is wrapped around");
+ }
+#endif
+}
+
+// Compute w = u - v, where w, u, and v are vectors.
+// - ulen >= vlen
+// - wlen >= sc_max(ulen, vlen)
+void
+vec_sub(int ulen, const sc_digit *u, int vlen, const sc_digit *v, sc_digit *w)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+ sc_assert(w != NULL);
+ sc_assert(ulen >= vlen);
+#endif
+
+ const sc_digit *uend = (u + ulen);
+ const sc_digit *vend = (v + vlen);
+
+ sc_digit borrow = 0; // Also used as diff to save space.
+
+ // Subtract along the shorter v.
+ while (v < vend) {
+ borrow = ((*u++) + DIGIT_RADIX) - (*v++) - borrow;
+ (*w++) = borrow & DIGIT_MASK;
+ borrow = 1 - (borrow >> BITS_PER_DIGIT);
+ }
+
+ // Propagate the borrow.
+ while (borrow && (u < uend)) {
+ borrow = ((*u++) + DIGIT_RADIX) - 1;
+ (*w++) = borrow & DIGIT_MASK;
+ borrow = 1 - (borrow >> BITS_PER_DIGIT);
+ }
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert(borrow == 0);
+#endif
+
+ // Copy the rest of u to the result.
+ while (u < uend)
+ (*w++) = (*u++);
+}
+
+// Compute u = u - v, where u and v are vectors.
+// - u > v
+// - ulen >= vlen
+void
+vec_sub_on(int ulen, sc_digit *ubegin, int vlen, const sc_digit *v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (ubegin != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+ sc_assert(ulen >= vlen);
+#endif
+
+ sc_digit *u = ubegin;
+ const sc_digit *uend = (u + ulen);
+ const sc_digit *vend = (v + vlen);
+
+ sc_digit borrow = 0; // Also used as diff to save space.
+
+ // Subtract along the shorter v.
+ while (v < vend) {
+ borrow = ((*u) + DIGIT_RADIX) - (*v++) - borrow;
+ (*u++) = borrow & DIGIT_MASK;
+ borrow = 1 - (borrow >> BITS_PER_DIGIT);
+ }
+
+ // Propagate the borrow.
+ while (borrow && (u < uend)) {
+ borrow = ((*u) + DIGIT_RADIX) - 1;
+ (*u++) = borrow & DIGIT_MASK;
+ borrow = 1 - (borrow >> BITS_PER_DIGIT);
+ }
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert(borrow == 0);
+#endif
+}
+
+// Compute u = v - u, where u and v are vectors.
+// - v > u
+// - ulen <= vlen or ulen > ulen
+void
+vec_sub_on2(int ulen, sc_digit *ubegin, int vlen, const sc_digit *v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (ubegin != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+#endif
+
+ sc_digit *u = ubegin;
+ const sc_digit *uend = (u + sc_min(ulen, vlen));
+
+ sc_digit borrow = 0; // Also used as diff to save space.
+
+ // Subtract along the shorter u.
+ while (u < uend) {
+ borrow = ((*v++) + DIGIT_RADIX) - (*u) - borrow;
+ (*u++) = borrow & DIGIT_MASK;
+ borrow = 1 - (borrow >> BITS_PER_DIGIT);
+ }
+
+#ifdef DEBUG_SYSTEMC
+ if (borrow != 0) {
+ SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_,
+ "vec_sub_on2( int, sc_digit*, int, const "
+ "sc_digit* ) : "
+ "result of subtraction is wrapped around");
+ }
+#endif
+}
+
+// Compute w = u - v, where w and u are vectors, and v is a scalar.
+void
+vec_sub_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *w)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert(ulen > 0);
+ sc_assert(u != NULL);
+#endif
+
+ const sc_digit *uend = (u + ulen);
+
+ // Add along the shorter v.
+ sc_digit borrow = ((*u++) + DIGIT_RADIX) - v;
+ (*w++) = borrow & DIGIT_MASK;
+ borrow = 1 - (borrow >> BITS_PER_DIGIT);
+
+ // Propagate the borrow.
+ while (borrow && (u < uend)) {
+ borrow = ((*u++) + DIGIT_RADIX) - 1;
+ (*w++) = borrow & DIGIT_MASK;
+ borrow = 1 - (borrow >> BITS_PER_DIGIT);
+ }
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert(borrow == 0);
+#endif
+
+ // Copy the rest of u to the result.
+ while (u < uend)
+ (*w++) = (*u++);
+}
+
+
+// Compute u -= v, where u is vectors, and v is a scalar.
+void
+vec_sub_small_on(int ulen, sc_digit *u, sc_digit v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+#endif
+
+ for (int i = 0; i < ulen; ++i) {
+ v = (u[i] + DIGIT_RADIX) - v;
+ u[i] = v & DIGIT_MASK;
+ v = 1 - (v >> BITS_PER_DIGIT);
+ }
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert(v == 0);
+#endif
+}
+
+// Compute w = u * v, where w, u, and v are vectors.
+void
+vec_mul(int ulen, const sc_digit *u, int vlen, const sc_digit *vbegin,
+ sc_digit *wbegin)
+{
+
+ /* Consider u = Ax + B and v = Cx + D where x is equal to
+ HALF_DIGIT_RADIX. In other words, A is the higher half of u and
+ B is the lower half of u. The interpretation for v is
+ similar. Then, we have the following picture:
+
+ u_h u_l
+ u: -------- --------
+ A B
+
+ v_h v_l
+ v: -------- --------
+ C D
+
+ result (d):
+ carry_before: -------- --------
+ carry_h carry_l
+ result_before: -------- -------- -------- --------
+ R1_h R1_l R0_h R0_l
+ -------- --------
+ BD_h BD_l
+ -------- --------
+ AD_h AD_l
+ -------- --------
+ BC_h BC_l
+ -------- --------
+ AC_h AC_l
+ result_after: -------- -------- -------- --------
+ R1_h' R1_l' R0_h' R0_l'
+
+ prod_l = R0_h|R0_l + B * D + 0|carry_l
+ = R0_h|R0_l + BD_h|BD_l + 0|carry_l
+
+ prod_h = A * D + B * C + high_half(prod_l) + carry_h
+ = AD_h|AD_l + BC_h|BC_l + high_half(prod_l) + 0|carry_h
+
+ carry = A * C + high_half(prod_h)
+ = AC_h|AC_l + high_half(prod_h)
+
+ R0_l' = low_half(prod_l)
+
+ R0_h' = low_half(prod_h)
+
+ R0 = high_half(prod_h)|low_half(prod_l)
+
+ where '|' is the concatenation operation and the suffixes 0 and 1
+ show the iteration number, i.e., 0 is the current iteration and 1
+ is the next iteration.
+
+ NOTE: sc_max(prod_l, prod_h, carry) <= 2 * x^2 - 1, so any
+ of these numbers can be stored in a digit.
+
+ NOTE: low_half(u) returns the lower BITS_PER_HALF_DIGIT of u,
+ whereas high_half(u) returns the rest of the bits, which may
+ contain more bits than BITS_PER_HALF_DIGIT.
+ */
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((vlen > 0) && (vbegin != NULL));
+ sc_assert(wbegin != NULL);
+#endif
+
+#define prod_h carry
+ const sc_digit *uend = (u + ulen);
+ const sc_digit *vend = (vbegin + vlen);
+
+ while (u < uend) {
+ sc_digit u_h = (*u++); // A|B
+ sc_digit u_l = low_half(u_h); // B
+ u_h = high_half(u_h); // A
+
+#ifdef DEBUG_SYSTEMC
+ // The overflow bits must be zero.
+ sc_assert(u_h == (u_h & HALF_DIGIT_MASK));
+#endif
+ sc_digit carry = 0;
+ sc_digit *w = (wbegin++);
+ const sc_digit *v = vbegin;
+
+ while (v < vend) {
+ sc_digit v_h = (*v++); // C|D
+ sc_digit v_l = low_half(v_h); // D
+
+ v_h = high_half(v_h); // C
+
+#ifdef DEBUG_SYSTEMC
+ // The overflow bits must be zero.
+ sc_assert(v_h == (v_h & HALF_DIGIT_MASK));
+#endif
+
+ sc_digit prod_l = (*w) + u_l * v_l + low_half(carry);
+ prod_h = u_h * v_l + u_l * v_h +
+ high_half(prod_l) + high_half(carry);
+ (*w++) = concat(low_half(prod_h), low_half(prod_l));
+ carry = u_h * v_h + high_half(prod_h);
+ }
+ (*w) = carry;
+ }
+#undef prod_h
+}
+
+// Compute w = u * v, where w and u are vectors, and v is a scalar.
+// - 0 < v < HALF_DIGIT_RADIX.
+void
+vec_mul_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *w)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert(w != NULL);
+ sc_assert((0 < v) && (v < HALF_DIGIT_RADIX));
+#endif
+
+#define prod_h carry
+
+ const sc_digit *uend = (u + ulen);
+ sc_digit carry = 0;
+ while (u < uend) {
+ sc_digit u_AB = (*u++);
+#ifdef DEBUG_SYSTEMC
+ // The overflow bits must be zero.
+ sc_assert(high_half(u_AB) == high_half_masked(u_AB));
+#endif
+ sc_digit prod_l = v * low_half(u_AB) + low_half(carry);
+ prod_h = v * high_half(u_AB) + high_half(prod_l) + high_half(carry);
+ (*w++) = concat(low_half(prod_h), low_half(prod_l));
+ carry = high_half(prod_h);
+ }
+ (*w) = carry;
+#undef prod_h
+}
+
+// Compute u = u * v, where u is a vector, and v is a scalar.
+// - 0 < v < HALF_DIGIT_RADIX.
+void
+vec_mul_small_on(int ulen, sc_digit *u, sc_digit v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((0 < v) && (v < HALF_DIGIT_RADIX));
+#endif
+
+#define prod_h carry
+ sc_digit carry = 0;
+ for (int i = 0; i < ulen; ++i) {
+#ifdef DEBUG_SYSTEMC
+ // The overflow bits must be zero.
+ sc_assert(high_half(u[i]) == high_half_masked(u[i]));
+#endif
+ sc_digit prod_l = v * low_half(u[i]) + low_half(carry);
+ prod_h = v * high_half(u[i]) + high_half(prod_l) + high_half(carry);
+ u[i] = concat(low_half(prod_h), low_half(prod_l));
+ carry = high_half(prod_h);
+ }
+#undef prod_h
+
+#ifdef DEBUG_SYSTEMC
+ if (carry != 0) {
+ SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_,
+ "vec_mul_small_on( int, sc_digit*, unsigned "
+ "long ) : "
+ "result of multiplication is wrapped around");
+ }
+#endif
+}
+
+// Compute w = u / v, where w, u, and v are vectors.
+// - u and v are assumed to have at least two digits as uchars.
+void
+vec_div_large(int ulen, const sc_digit *u, int vlen, const sc_digit *v,
+ sc_digit *w)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+ sc_assert(w != NULL);
+ sc_assert(BITS_PER_DIGIT >= 3 * BITS_PER_BYTE);
+#endif
+
+ // We will compute q = x / y where x = u and y = v. The reason for
+ // using x and y is that x and y are BYTE_RADIX copies of u and v,
+ // respectively. The use of BYTE_RADIX radix greatly simplifies the
+ // complexity of the division operation. These copies are also
+ // needed even when we use DIGIT_RADIX representation.
+
+ int xlen = BYTES_PER_DIGIT * ulen + 1;
+ int ylen = BYTES_PER_DIGIT * vlen;
+
+#ifdef SC_MAX_NBITS
+ uchar x[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];
+ uchar y[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];
+ uchar q[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];
+#else
+ uchar *x = new uchar[xlen];
+ uchar *y = new uchar[ylen];
+ // valgrind complains about us accessing too far to so leave a buffer.
+ uchar *q = new uchar[(xlen - ylen) + 10];
+#endif
+
+ // q corresponds to w.
+
+ // Set (uchar) x = (sc_digit) u.
+ xlen = vec_to_char(ulen, u, xlen, x);
+
+ // Skip all the leading zeros in x.
+ while ((--xlen >= 0) && (! x[xlen]))
+ continue;
+ xlen++;
+
+ // Set (uchar) y = (sc_digit) v.
+ ylen = vec_to_char(vlen, v, ylen, y);
+
+ // Skip all the leading zeros in y.
+ while ((--ylen >= 0) && (! y[ylen]))
+ continue;
+ ylen++;
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert(xlen > 1);
+ sc_assert(ylen > 1);
+#endif
+
+ // At this point, all the leading zeros are eliminated from x and y.
+
+ // Zero the last digit of x.
+ x[xlen] = 0;
+
+ // The first two digits of y.
+ sc_digit y2 = (y[ylen - 1] << BITS_PER_BYTE) + y[ylen - 2];
+
+ const sc_digit DOUBLE_BITS_PER_BYTE = 2 * BITS_PER_BYTE;
+
+ // Find each q[k].
+ for (int k = (xlen - ylen); k >= 0; --k) {
+ // qk is a guess for q[k] such that q[k] = qk or qk - 1.
+ sc_digit qk;
+
+ // Find qk by just using 2 digits of y and 3 digits of x. The
+ // following code assumes that sizeof(sc_digit) >= 3 BYTEs.
+ int k2 = k + ylen;
+
+ qk = ((x[k2] << DOUBLE_BITS_PER_BYTE) +
+ (x[k2 - 1] << BITS_PER_BYTE) + x[k2 - 2]) / y2;
+
+ if (qk >= BYTE_RADIX) // qk cannot be larger than the largest
+ qk = BYTE_RADIX - 1; // digit in BYTE_RADIX.
+
+ // q[k] = qk or qk - 1. The following if-statement determines which:
+ if (qk) {
+ uchar *xk = (x + k); // A shortcut for x[k].
+
+ // x = x - y * qk :
+ sc_digit carry = 0;
+
+ for (int i = 0; i < ylen; ++i) {
+ carry += y[i] * qk;
+ sc_digit diff = (xk[i] + BYTE_RADIX) - (carry & BYTE_MASK);
+ xk[i] = (uchar)(diff & BYTE_MASK);
+ carry = (carry >> BITS_PER_BYTE) +
+ (1 - (diff >> BITS_PER_BYTE));
+ }
+
+ // If carry, qk may be one too large.
+ if (carry) {
+ // 2's complement the last digit.
+ carry = (xk[ylen] + BYTE_RADIX) - carry;
+ xk[ylen] = (uchar)(carry & BYTE_MASK);
+ carry = 1 - (carry >> BITS_PER_BYTE);
+
+ if (carry) {
+
+ // qk was one too large, so decrement it.
+ --qk;
+
+ // Since qk was decreased by one, y must be added to x:
+ // x = x - y * (qk - 1) = x - y * qk + y = x_above + y.
+ carry = 0;
+
+ for (int i = 0; i < ylen; ++i) {
+ carry += xk[i] + y[i];
+ xk[i] = (uchar)(carry & BYTE_MASK);
+ carry >>= BITS_PER_BYTE;
+ }
+
+ if (carry)
+ xk[ylen] = (uchar)((xk[ylen] + 1) & BYTE_MASK);
+
+ } // second if carry
+ } // first if carry
+ } // if qk
+ q[k] = (uchar)qk;
+ } // for k
+
+ // Set (sc_digit) w = (uchar) q.
+ vec_from_char(xlen - ylen + 1, q, ulen, w);
+
+#ifndef SC_MAX_NBITS
+ delete [] x;
+ delete [] y;
+ delete [] q;
+#endif
+
+}
+
+// Compute w = u / v, where u and w are vectors, and v is a scalar.
+// - 0 < v < HALF_DIGIT_RADIX. Below, we rename w to q.
+void
+vec_div_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *q)
+{
+ // Given (u = u_1u_2...u_n)_b = (q = q_1q_2...q_n) * v + r, where b
+ // is the base, and 0 <= r < v. Then, the algorithm is as follows:
+ //
+ // r = 0;
+ // for (j = 1; j <= n; j++) {
+ // q_j = (r * b + u_j) / v;
+ // r = (r * b + u_j) % v;
+ // }
+ //
+ // In our case, b = DIGIT_RADIX, and u = Ax + B and q = Cx + D where
+ // x = HALF_DIGIT_RADIX. Note that r < v < x and b = x^2. Then, a
+ // typical situation is as follows:
+ //
+ // ---- ----
+ // 0 r
+ // ---- ----
+ // A B
+ // ---- ---- ----
+ // r A B = r * b + u
+ //
+ // Hence, C = (r|A) / v.
+ // D = (((r|A) % v)|B) / v
+ // r = (((r|A) % v)|B) % v
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert(q != NULL);
+ sc_assert((0 < v) && (v < HALF_DIGIT_RADIX));
+#endif
+
+#define q_h r
+ sc_digit r = 0;
+ const sc_digit *ubegin = u;
+
+ u += ulen;
+ q += ulen;
+
+ while (ubegin < u) {
+ sc_digit u_AB = (*--u); // A|B
+
+#ifdef DEBUG_SYSTEMC
+ // The overflow bits must be zero.
+ sc_assert(high_half(u_AB) == high_half_masked(u_AB));
+#endif
+
+ sc_digit num = concat(r, high_half(u_AB)); // num = r|A
+ q_h = num / v; // C
+ num = concat((num % v), low_half(u_AB)); // num = (((r|A) % v)|B)
+ (*--q) = concat(q_h, num / v); // q = C|D
+ r = num % v;
+ }
+#undef q_h
+}
+
+// Compute w = u % v, where w, u, and v are vectors.
+// - u and v are assumed to have at least two digits as uchars.
+void
+vec_rem_large(int ulen, const sc_digit *u, int vlen, const sc_digit *v,
+ sc_digit *w)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+ sc_assert(w != NULL);
+ sc_assert(BITS_PER_DIGIT >= 3 * BITS_PER_BYTE);
+#endif
+
+ // This function is adapted from vec_div_large.
+ int xlen = BYTES_PER_DIGIT * ulen + 1;
+ int ylen = BYTES_PER_DIGIT * vlen;
+
+#ifdef SC_MAX_NBITS
+ uchar x[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];
+ uchar y[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];
+#else
+ uchar *x = new uchar[xlen];
+ uchar *y = new uchar[ylen];
+#endif
+
+ // r corresponds to w.
+
+ // Set (uchar) x = (sc_digit) u.
+ xlen = vec_to_char(ulen, u, xlen, x);
+
+ // Skip all the leading zeros in x.
+ while ((--xlen >= 0) && (!x[xlen]))
+ continue;
+ xlen++;
+
+ // Set (uchar) y = (sc_digit) v.
+ ylen = vec_to_char(vlen, v, ylen, y);
+
+ // Skip all the leading zeros in y.
+ while ((--ylen >= 0) && (!y[ylen]))
+ continue;
+ ylen++;
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert(xlen > 1);
+ sc_assert(ylen > 1);
+#endif
+
+ // At this point, all the leading zeros are eliminated from x and y.
+
+ // Zero the last digit of x.
+ x[xlen] = 0;
+
+ // The first two digits of y.
+ sc_digit y2 = (y[ylen - 1] << BITS_PER_BYTE) + y[ylen - 2];
+
+ const sc_digit DOUBLE_BITS_PER_BYTE = 2 * BITS_PER_BYTE;
+
+ // Find each q[k].
+ for (int k = xlen - ylen; k >= 0; --k) {
+ // qk is a guess for q[k] such that q[k] = qk or qk - 1.
+ sc_digit qk;
+
+ // Find qk by just using 2 digits of y and 3 digits of x. The
+ // following code assumes that sizeof(sc_digit) >= 3 BYTEs.
+ int k2 = k + ylen;
+
+ qk = ((x[k2] << DOUBLE_BITS_PER_BYTE) +
+ (x[k2 - 1] << BITS_PER_BYTE) + x[k2 - 2]) / y2;
+
+ if (qk >= BYTE_RADIX) // qk cannot be larger than the largest
+ qk = BYTE_RADIX - 1; // digit in BYTE_RADIX.
+
+ // q[k] = qk or qk - 1. The following if-statement determines which.
+ if (qk) {
+ uchar *xk = (x + k); // A shortcut for x[k].
+
+ // x = x - y * qk;
+ sc_digit carry = 0;
+
+ for (int i = 0; i < ylen; ++i) {
+ carry += y[i] * qk;
+ sc_digit diff = (xk[i] + BYTE_RADIX) - (carry & BYTE_MASK);
+ xk[i] = (uchar)(diff & BYTE_MASK);
+ carry = (carry >> BITS_PER_BYTE) +
+ (1 - (diff >> BITS_PER_BYTE));
+ }
+
+ if (carry) {
+ // 2's complement the last digit.
+ carry = (xk[ylen] + BYTE_RADIX) - carry;
+ xk[ylen] = (uchar)(carry & BYTE_MASK);
+ carry = 1 - (carry >> BITS_PER_BYTE);
+
+ if (carry) {
+ // qk was one too large, so decrement it.
+ // --qk;
+
+ // x = x - y * (qk - 1) = x - y * qk + y = x_above + y.
+ carry = 0;
+
+ for (int i = 0; i < ylen; ++i) {
+ carry += xk[i] + y[i];
+ xk[i] = (uchar)(carry & BYTE_MASK);
+ carry >>= BITS_PER_BYTE;
+ }
+
+ if (carry)
+ xk[ylen] = (uchar)((xk[ylen] + 1) & BYTE_MASK);
+ } // second if carry
+ } // first if carry
+ } // if qk
+ } // for k
+
+ // Set (sc_digit) w = (uchar) x for the remainder.
+ vec_from_char(ylen, x, ulen, w);
+
+#ifndef SC_MAX_NBITS
+ delete [] x;
+ delete [] y;
+#endif
+
+}
+
+// Compute r = u % v, where u is a vector, and r and v are scalars.
+// - 0 < v < HALF_DIGIT_RADIX.
+// - The remainder r is returned.
+sc_digit
+vec_rem_small(int ulen, const sc_digit *u, sc_digit v)
+{
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((0 < v) && (v < HALF_DIGIT_RADIX));
+#endif
+
+ // This function is adapted from vec_div_small().
+
+ sc_digit r = 0;
+ const sc_digit *ubegin = u;
+
+ u += ulen;
+
+ while (ubegin < u) {
+ sc_digit u_AB = (*--u); // A|B
+#ifdef DEBUG_SYSTEMC
+ // The overflow bits must be zero.
+ sc_assert(high_half(u_AB) == high_half_masked(u_AB));
+#endif
+ // r = (((r|A) % v)|B) % v
+ r = (concat(((concat(r, high_half(u_AB))) % v), low_half(u_AB))) % v;
+ }
+
+ return r;
+}
+
+// u = u / v, r = u % v.
+sc_digit
+vec_rem_on_small(int ulen, sc_digit *u, sc_digit v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert(v > 0);
+#endif
+
+#define q_h r
+ sc_digit r = 0;
+ const sc_digit *ubegin = u;
+
+ u += ulen;
+ while (ubegin < u) {
+ sc_digit u_AB = (*--u); // A|B
+#ifdef DEBUG_SYSTEMC
+ // The overflow bits must be zero.
+ sc_assert(high_half(u_AB) == high_half_masked(u_AB));
+#endif
+ sc_digit num = concat(r, high_half(u_AB)); // num = r|A
+ q_h = num / v; // C
+ num = concat((num % v), low_half(u_AB)); // num = (((r|A) % v)|B)
+ (*u) = concat(q_h, num / v); // q = C|D
+ r = num % v;
+ }
+#undef q_h
+ return r;
+}
+
+// Set (uchar) v = (sc_digit) u. Return the new vlen.
+int
+vec_to_char(int ulen, const sc_digit *u, int vlen, uchar *v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+#endif
+
+ int nbits = ulen * BITS_PER_DIGIT;
+ int right = 0;
+ int left = right + BITS_PER_BYTE - 1;
+
+ vlen = 0;
+ while (nbits > 0) {
+ int left_digit = left / BITS_PER_DIGIT;
+ int right_digit = right / BITS_PER_DIGIT;
+ int nsr = ((vlen << LOG2_BITS_PER_BYTE) % BITS_PER_DIGIT);
+ int d = u[right_digit] >> nsr;
+
+ if (left_digit != right_digit) {
+ if (left_digit < ulen)
+ d |= u[left_digit] << (BITS_PER_DIGIT - nsr);
+ }
+
+ v[vlen++] = (uchar)(d & BYTE_MASK);
+
+ left += BITS_PER_BYTE;
+ right += BITS_PER_BYTE;
+ nbits -= BITS_PER_BYTE;
+ }
+ return vlen;
+}
+
+// Set (sc_digit) v = (uchar) u.
+// - sizeof(uchar) <= sizeof(sc_digit),
+void
+vec_from_char(int ulen, const uchar *u, int vlen, sc_digit *v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+ sc_assert(sizeof(uchar) <= sizeof(sc_digit));
+#endif
+
+ sc_digit *vend = (v + vlen);
+
+ const int nsr = BITS_PER_DIGIT - BITS_PER_BYTE;
+ const sc_digit mask = one_and_ones(nsr);
+
+ (*v) = (sc_digit) u[ulen - 1];
+
+ for (int i = ulen - 2; i >= 0; --i) {
+ // Manual inlining of vec_shift_left().
+ sc_digit *viter = v;
+ sc_digit carry = 0;
+ while (viter < vend) {
+ sc_digit vval = (*viter);
+ (*viter++) = (((vval & mask) << BITS_PER_BYTE) | carry);
+ carry = vval >> nsr;
+ }
+
+ if (viter < vend)
+ (*viter) = carry;
+
+ (*v) |= (sc_digit)u[i];
+ }
+}
+
+// Set u <<= nsl.
+// If nsl is negative, it is ignored.
+void
+vec_shift_left(int ulen, sc_digit *u, int nsl)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+#endif
+
+ if (nsl <= 0)
+ return;
+
+ // Shift left whole digits if nsl is large enough.
+ if (nsl >= (int) BITS_PER_DIGIT) {
+ int nd;
+ if (nsl % BITS_PER_DIGIT == 0) {
+ nd = nsl / BITS_PER_DIGIT; // No need to use DIV_CEIL(nsl).
+ nsl = 0;
+ } else {
+ nd = DIV_CEIL(nsl) - 1;
+ nsl -= nd * BITS_PER_DIGIT;
+ }
+
+ if (nd) {
+ // Shift left for nd digits.
+ for (int j = ulen - 1; j >= nd; --j)
+ u[j] = u[j - nd];
+
+ vec_zero(sc_min(nd, ulen), u);
+ }
+ if (nsl == 0)
+ return;
+ }
+
+ // Shift left if nsl < BITS_PER_DIGIT.
+ sc_digit *uiter = u;
+ sc_digit *uend = uiter + ulen;
+
+ int nsr = BITS_PER_DIGIT - nsl;
+ sc_digit mask = one_and_ones(nsr);
+
+ sc_digit carry = 0;
+
+ while (uiter < uend) {
+ sc_digit uval = (*uiter);
+ (*uiter++) = (((uval & mask) << nsl) | carry);
+ carry = uval >> nsr;
+ }
+
+ if (uiter < uend)
+ (*uiter) = carry;
+}
+
+// Set u >>= nsr.
+// If nsr is negative, it is ignored.
+void
+vec_shift_right(int ulen, sc_digit *u, int nsr, sc_digit fill)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+#endif
+
+ // fill is usually either 0 or DIGIT_MASK; it can be any value.
+ if (nsr <= 0)
+ return;
+
+ // Shift right whole digits if nsr is large enough.
+ if (nsr >= (int) BITS_PER_DIGIT) {
+ int nd;
+ if (nsr % BITS_PER_DIGIT == 0) {
+ nd = nsr / BITS_PER_DIGIT;
+ nsr = 0;
+ } else {
+ nd = DIV_CEIL(nsr) - 1;
+ nsr -= nd * BITS_PER_DIGIT;
+ }
+
+ if (nd) {
+ // Shift right for nd digits.
+ for (int j = 0; j < (ulen - nd); ++j)
+ u[j] = u[j + nd];
+
+ if (fill) {
+ for (int j = ulen - sc_min( nd, ulen ); j < ulen; ++j)
+ u[j] = fill;
+ } else {
+ vec_zero(ulen - sc_min( nd, ulen ), ulen, u);
+ }
+ }
+ if (nsr == 0)
+ return;
+ }
+
+ // Shift right if nsr < BITS_PER_DIGIT.
+ sc_digit *ubegin = u;
+ sc_digit *uiter = (ubegin + ulen);
+
+ int nsl = BITS_PER_DIGIT - nsr;
+ sc_digit mask = one_and_ones(nsr);
+
+ sc_digit carry = (fill & mask) << nsl;
+
+ while (ubegin < uiter) {
+ sc_digit uval = (*--uiter);
+ (*uiter) = (uval >> nsr) | carry;
+ carry = (uval & mask) << nsl;
+ }
+}
+
+
+// Let u[l..r], where l and r are left and right bit positions
+// respectively, be equal to its mirror image.
+void
+vec_reverse(int unb, int und, sc_digit *ud, int l, int r)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((unb > 0) && (und > 0) && (ud != NULL));
+ sc_assert((0 <= r) && (r <= l) && (l < unb));
+#endif
+
+ if (l < r) {
+ std::stringstream msg;
+ msg << "vec_reverse( int, int, sc_digit*, int l, int r ) : " <<
+ "l = " << l << " < r = " << r << " is not valid",
+ SC_REPORT_ERROR("conversion failed", msg.str().c_str());
+ return;
+ }
+
+ // Make sure that l and r are within bounds.
+ r = sc_max(r, 0);
+ l = sc_min(l, unb - 1);
+
+ // Allocate memory for processing.
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[und];
+#endif
+
+ // d is a copy of ud.
+ vec_copy(und, d, ud);
+
+ // Based on the value of the ith in d, find the value of the jth bit
+ // in ud.
+ for (int i = l, j = r; i >= r; --i, ++j) {
+ if ((d[digit_ord(i)] & one_and_zeros(bit_ord(i))) != 0) // Test.
+ ud[digit_ord(j)] |= one_and_zeros(bit_ord(j)); // Set.
+ else
+ ud[digit_ord(j)] &= ~(one_and_zeros(bit_ord(j))); // Clear.
+ }
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+}
+
+#ifdef SC_MAX_NBITS
+void test_bound_failed(int nb)
+{
+ std::stringstream msg;
+ msg << "test_bound( int nb ) : "
+ "nb = " << nb << " > SC_MAX_NBITS = " << SC_MAX_NBITS <<
+ " is not valid";
+ SC_REPORT_ERROR(sc_core::SC_ID_OUT_OF_BOUNDS_, msg.str().c_str());
+}
+#endif // SC_MAX_NBITS
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_signed.cpp -- Arbitrary precision signed arithmetic.
+
+ This file includes the definitions of sc_signed_bitref,
+ sc_signed_subref, and sc_signed classes. The first two
+ classes are proxy classes to reference one bit and a range
+ of bits of a sc_signed number, respectively. This file also
+ includes sc_nbcommon.cpp and sc_nbfriends.cpp, which
+ contain the definitions shared by sc_unsigned.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_signed.cpp,v $
+// Revision 1.6 2011/02/18 20:19:15 acg
+// Andy Goodrich: updating Copyright notice.
+//
+// Revision 1.5 2008/12/10 20:38:45 acg
+// Andy Goodrich: fixed conversion of double values to the digits vector.
+// The bits above the radix were not being masked off.
+//
+// Revision 1.4 2008/06/19 17:47:56 acg
+// Andy Goodrich: fixes for bugs. See 2.2.1 RELEASENOTES.
+//
+// Revision 1.3 2008/04/29 21:20:41 acg
+// Andy Goodrich: added mask to first word transferred when processing
+// a negative sc_signed value in sc_signed::concat_get_data().
+//
+// Revision 1.2 2007/11/04 21:27:00 acg
+// Andy Goodrich: changes to make sure the proper value is returned from
+// concat_get_data().
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.5 2006/10/23 19:32:47 acg
+// Andy Goodrich: further fix for incorrect value being returned from
+// concat_get_data. This one is in the non-aligned value code.
+//
+// Revision 1.3 2006/01/13 18:49:32 acg
+// Added $Log command so that CVS check in comments are reproduced in the
+// source.
+//
+
+#include <cctype>
+#include <cmath>
+#include <sstream>
+
+#include "systemc/ext/dt/bit/sc_bv_base.hh"
+#include "systemc/ext/dt/bit/sc_lv_base.hh"
+#include "systemc/ext/dt/fx/sc_fix.hh"
+#include "systemc/ext/dt/fx/scfx_other_defs.hh"
+#include "systemc/ext/dt/int/sc_int_base.hh"
+#include "systemc/ext/dt/int/sc_signed.hh"
+#include "systemc/ext/dt/int/sc_uint_base.hh"
+#include "systemc/ext/dt/int/sc_unsigned.hh"
+#include "systemc/ext/dt/misc/sc_concatref.hh"
+
+// explicit template instantiations
+namespace sc_core
+{
+
+template class sc_vpool<sc_dt::sc_signed_bitref>;
+template class sc_vpool<sc_dt::sc_signed_subref>;
+
+} // namespace sc_core
+
+namespace sc_dt
+{
+
+// Pool of temporary instances:
+
+sc_core::sc_vpool<sc_signed_bitref> sc_signed_bitref::m_pool(9);
+sc_core::sc_vpool<sc_signed_subref> sc_signed_subref::m_pool(9);
+
+void
+sc_signed::invalid_init(const char *type_name, int nb) const
+{
+ std::stringstream msg;
+ msg << "sc_signed("<< type_name << ") : nb = " << nb << " is not valid";
+ SC_REPORT_ERROR("initialization failed", msg.str().c_str());
+}
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Invalid selections.
+// ----------------------------------------------------------------------------
+
+void
+sc_signed::invalid_index(int i) const
+{
+ std::stringstream msg;
+ msg << "sc_bigint bit selection: index = " << i << " violates "
+ "0 <= index <= " << (nbits - 1);
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+void
+sc_signed::invalid_range(int l, int r) const
+{
+ std::stringstream msg;
+ msg << "sc_bigint part selection: left = " <<
+ l << ", right = " << r << "\n"
+ " violates either (" << (nbits-1) << " >= left >= 0) or "
+ "(" << (nbits-1) << " >= right >= 0)";
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+
+// ----------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members.
+// ----------------------------------------------------------------------------
+
+// Most public members are included from sc_nbcommon.inc. However, some
+// concatenation support appears here to optimize between the signed and
+// unsigned cases.
+
+// Insert this object's value at the specified place in a vector of biguint
+// style values.
+
+bool
+sc_signed::concat_get_ctrl(sc_digit *dst_p, int low_i) const
+{
+ int dst_i; // Index to next word to set in dst_p.
+ int end_i; // Index of high order word to set.
+ int left_shift; // Amount to shift value left.
+ sc_digit mask; // Mask for partial word sets.
+
+ // CALCULATE METRICS FOR DATA MOVEMENT:
+ dst_i = low_i / BITS_PER_DIGIT;
+ end_i = (low_i + nbits - 1) / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+
+ // ALL DATA TO BE MOVED IS IN A SINGLE WORD:
+ mask = ~(~0U << left_shift);
+ dst_p[dst_i] = (dst_p[dst_i] & ~mask);
+ dst_i++;
+
+ for (; dst_i <= end_i; dst_i++)
+ dst_p[dst_i] = 0;
+
+ return false;
+}
+
+bool
+sc_signed::concat_get_data(sc_digit *dst_p, int low_i) const
+{
+ sc_digit carry; // Carry bit for complements.
+ int dst_i; // Index to next word to set in dst_p.
+ int end_i; // Index of high order word to set.
+ int high_i; // Index w/in word of high order bit.
+ int left_shift; // Amount to shift value left.
+ sc_digit left_word; // High word component for set.
+ sc_digit mask; // Mask for partial word sets.
+ bool result; // True if inserted non-zero data.
+ int right_shift; // Amount to shift value right.
+ sc_digit right_word; // Low word component for set.
+ int src_i; // Index to next word to get from digit.
+
+ // CALCULATE METRICS FOR DATA MOVEMENT:
+ dst_i = low_i / BITS_PER_DIGIT;
+ high_i = low_i + nbits - 1;
+ end_i = high_i / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+
+ switch (sgn) {
+ // POSITIVE SOURCE VALUE:
+ case SC_POS:
+ result = true;
+
+ // ALL DATA TO BE MOVED IS IN A SINGLE WORD:
+ if (dst_i == end_i) {
+ mask = ~(~0U << left_shift);
+ dst_p[dst_i] = ((dst_p[dst_i] & mask) |
+ (digit[0] << left_shift)) & DIGIT_MASK;
+
+ // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED:
+ } else if (left_shift == 0) {
+ for (src_i = 0; dst_i < end_i; dst_i++, src_i++) {
+ dst_p[dst_i] = digit[src_i];
+ }
+ high_i = high_i % BITS_PER_DIGIT;
+ mask = ~(~1U << high_i) & DIGIT_MASK;
+ dst_p[dst_i] = digit[src_i] & mask;
+
+ // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED:
+ } else {
+ high_i = high_i % BITS_PER_DIGIT;
+ right_shift = BITS_PER_DIGIT - left_shift;
+ mask = ~(~0U << left_shift);
+ right_word = digit[0];
+ dst_p[dst_i] = (dst_p[dst_i] & mask) |
+ ((right_word << left_shift) & DIGIT_MASK);
+ for (src_i = 1, dst_i++; dst_i < end_i; dst_i++, src_i++) {
+ left_word = digit[src_i];
+ dst_p[dst_i] = ((left_word << left_shift)&DIGIT_MASK) |
+ (right_word >> right_shift);
+ right_word = left_word;
+ }
+ left_word = (src_i < ndigits) ? digit[src_i] : 0;
+ mask = ~(~1U << high_i) & DIGIT_MASK;
+ dst_p[dst_i] = ((left_word << left_shift) |
+ (right_word >> right_shift)) & mask;
+ }
+ break;
+
+ // SOURCE VALUE IS NEGATIVE:
+ case SC_NEG:
+ // ALL DATA TO BE MOVED IS IN A SINGLE WORD:
+ result = true;
+ if (dst_i == end_i) {
+ mask = ~(~0U << nbits);
+ right_word = ((digit[0] ^ DIGIT_MASK) + 1) & mask;
+ mask = ~(~0U << left_shift);
+ dst_p[dst_i] = ((dst_p[dst_i] & mask) |
+ (right_word << left_shift)) & DIGIT_MASK;
+
+ // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED:
+ } else if (left_shift == 0) {
+ carry = 1;
+ for (src_i = 0; dst_i < end_i; dst_i++, src_i++) {
+ right_word = (digit[src_i] ^ DIGIT_MASK) + carry;
+ dst_p[dst_i] = right_word & DIGIT_MASK;
+ carry = right_word >> BITS_PER_DIGIT;
+ }
+ high_i = high_i % BITS_PER_DIGIT;
+ mask = (~(~1U << high_i)) & DIGIT_MASK;
+ right_word = (src_i < ndigits) ?
+ (digit[src_i] ^ DIGIT_MASK) + carry : DIGIT_MASK + carry;
+ dst_p[dst_i] = right_word & mask;
+
+ // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED:
+ } else {
+ high_i = high_i % BITS_PER_DIGIT;
+ right_shift = BITS_PER_DIGIT - left_shift;
+ mask = ~(~0U << left_shift);
+ carry = 1;
+ right_word = (digit[0] ^ DIGIT_MASK) + carry;
+ dst_p[dst_i] = (dst_p[dst_i] & mask) |
+ ((right_word << left_shift) & DIGIT_MASK);
+ carry = right_word >> BITS_PER_DIGIT;
+ right_word &= DIGIT_MASK;
+ for (src_i = 1, dst_i++; dst_i < end_i; dst_i++, src_i++) {
+ left_word = (digit[src_i] ^ DIGIT_MASK) + carry;
+ dst_p[dst_i] = ((left_word << left_shift)&DIGIT_MASK) |
+ (right_word >> right_shift);
+ carry = left_word >> BITS_PER_DIGIT;
+ right_word = left_word & DIGIT_MASK;
+ }
+ left_word = (src_i < ndigits) ?
+ (digit[src_i] ^ DIGIT_MASK) + carry : carry;
+ mask = ~(~1U << high_i) & DIGIT_MASK;
+ dst_p[dst_i] = ((left_word << left_shift) |
+ (right_word >> right_shift)) & mask;
+ }
+ break;
+
+ // VALUE IS ZERO:
+ default:
+ result = false;
+ // ALL DATA TO BE MOVED IS IN A SINGLE WORD:
+ if (dst_i == end_i) {
+ mask = ~(~0U << nbits) << left_shift;
+ dst_p[dst_i] = dst_p[dst_i] & ~mask;
+
+ // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED:
+ } else if (left_shift == 0) {
+ for (src_i = 0; dst_i < end_i; dst_i++, src_i++) {
+ dst_p[dst_i] = 0;
+ }
+ dst_p[dst_i] = 0;
+
+ // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED:
+ } else {
+ mask = ~(~0U << left_shift);
+ dst_p[dst_i] = (dst_p[dst_i] & mask);
+ for (dst_i++; dst_i <= end_i; dst_i++) {
+ dst_p[dst_i] = 0;
+ }
+ }
+ break;
+ }
+ return result;
+}
+
+// Return this object instance's bits as a uint64 without sign extension.
+
+uint64
+sc_signed::concat_get_uint64() const
+{
+ uint64 result;
+ switch (sgn) {
+ case SC_POS:
+ result = 0;
+ if (ndigits > 2)
+ result = digit[2];
+ if (ndigits > 1)
+ result = (result << BITS_PER_DIGIT) | digit[1];
+ result = (result << BITS_PER_DIGIT) | digit[0];
+ break;
+ case SC_NEG:
+ result = 0;
+ if (ndigits > 2)
+ result = digit[2];
+ if (ndigits > 1)
+ result = (result << BITS_PER_DIGIT) | digit[1];
+ result = (result << BITS_PER_DIGIT) | digit[0];
+ result = -result;
+ if (nbits < 64) {
+ uint64 mask = ~0;
+ result = result & ~(mask << nbits);
+ }
+ break;
+ default:
+ result = 0;
+ break;
+ }
+ return result;
+}
+
+// #### OPTIMIZE
+void
+sc_signed::concat_set(int64 src, int low_i)
+{
+ *this = (low_i < 64) ? src >> low_i : src >> 63;
+}
+
+void
+sc_signed::concat_set(const sc_signed &src, int low_i)
+{
+ if (low_i < src.length())
+ *this = src >> low_i;
+ else
+ *this = (src<0) ? (int_type)-1 : 0;
+}
+
+void
+sc_signed::concat_set(const sc_unsigned &src, int low_i)
+{
+ if (low_i < src.length())
+ *this = src >> low_i;
+ else
+ *this = 0;
+}
+
+void
+sc_signed::concat_set(uint64 src, int low_i)
+{
+ *this = (low_i < 64) ? src >> low_i : 0;
+}
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Reduction methods.
+// ----------------------------------------------------------------------------
+
+bool
+sc_signed::and_reduce() const
+{
+ sc_digit current; // Current digit examining.
+ int i; // Index of digit examining.
+
+ if (sgn == SC_NEG) {
+ current = (1 << BITS_PER_DIGIT);
+ for (i = 0; i < ndigits-1; i++) {
+ current = (current >> BITS_PER_DIGIT) + (digit[i]^DIGIT_MASK);
+ if ((current & DIGIT_MASK) != DIGIT_MASK) return false;
+ }
+ current = (current >> BITS_PER_DIGIT) + (digit[i]^DIGIT_MASK);
+ if ((current & ~(~0U << (nbits % BITS_PER_DIGIT))) ==
+ static_cast<sc_digit>(~(~0U << (nbits % BITS_PER_DIGIT)))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+sc_signed::or_reduce() const
+{
+ return sgn == SC_ZERO ? false : true;
+}
+
+bool
+sc_signed::xor_reduce() const
+{
+ int i; // Digit examining.
+ int odd; // Flag for odd number of digits.
+
+ odd = 0;
+ for (i = 0; i < nbits; i++)
+ if (test(i))
+ odd = ~odd;
+ return odd ? true : false;
+}
+
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Assignment operators.
+// ----------------------------------------------------------------------------
+
+// assignment operators
+
+const sc_signed &
+sc_signed::operator = (const char *a)
+{
+ if (a == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is zero");
+ } else if (*a == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is empty");
+ } else try {
+ int len = length();
+ sc_fix aa(a, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return this->operator = (aa);
+ } catch(const sc_core::sc_report &) {
+ std::stringstream msg;
+ msg << "character string '" << a << "' is not valid";
+ SC_REPORT_ERROR("conversion failed", msg.str().c_str());
+ }
+ return *this;
+}
+
+const sc_signed &
+sc_signed::operator=(int64 v)
+{
+ sgn = get_sign(v);
+ // v >= 0 now.
+ if (sgn == SC_ZERO) {
+ vec_zero(ndigits, digit);
+ } else {
+ from_uint(ndigits, digit, (uint64)v);
+ if (nbits <= (int)BITS_PER_INT64)
+ convert_SM_to_2C_to_SM();
+ }
+ return *this;
+}
+
+const sc_signed &
+sc_signed::operator=(uint64 v)
+{
+ sgn = get_sign(v);
+ if (sgn == SC_ZERO) {
+ vec_zero(ndigits, digit);
+ } else {
+ from_uint(ndigits, digit, v);
+ if (nbits <= (int)BITS_PER_INT64)
+ convert_SM_to_2C_to_SM();
+ }
+ return *this;
+}
+
+const sc_signed &
+sc_signed::operator=(long v)
+{
+ sgn = get_sign(v);
+ // v >= 0 now.
+ if (sgn == SC_ZERO) {
+ vec_zero(ndigits, digit);
+ } else {
+ from_uint(ndigits, digit, (unsigned long)v);
+ if (nbits <= (int)BITS_PER_LONG)
+ convert_SM_to_2C_to_SM();
+ }
+ return *this;
+}
+
+const sc_signed &
+sc_signed::operator=(unsigned long v)
+{
+ sgn = get_sign(v);
+ if (sgn == SC_ZERO) {
+ vec_zero(ndigits, digit);
+ } else {
+ from_uint(ndigits, digit, v);
+ if (nbits <= (int)BITS_PER_LONG)
+ convert_SM_to_2C_to_SM();
+ }
+ return *this;
+}
+
+const sc_signed &
+sc_signed::operator=(double v)
+{
+ is_bad_double(v);
+ if (v < 0) {
+ v = -v;
+ sgn = SC_NEG;
+ } else {
+ sgn = SC_POS;
+ }
+
+ int i = 0;
+ while (std::floor(v) && (i < ndigits)) {
+ digit[i++] = ((sc_digit)std::floor(remainder(v, DIGIT_RADIX))) &
+ DIGIT_MASK;
+ v /= DIGIT_RADIX;
+ }
+ vec_zero(i, ndigits, digit);
+ convert_SM_to_2C_to_SM();
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+
+const sc_signed &
+sc_signed::operator = (const sc_bv_base &v)
+{
+ int minlen = sc_min(nbits, v.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ safe_set(i, v.get_bit(i), digit);
+ }
+ for (; i < nbits; ++i) {
+ safe_set(i, 0, digit); // zero-extend
+ }
+ convert_2C_to_SM();
+ return *this;
+}
+
+const sc_signed &
+sc_signed::operator = (const sc_lv_base &v)
+{
+ int minlen = sc_min(nbits, v.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ safe_set(i, sc_logic(v.get_bit(i)).to_bool(), digit);
+ }
+ for (; i < nbits; ++i) {
+ safe_set(i, 0, digit); // zero-extend
+ }
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+// explicit conversion to character string
+const std::string
+sc_signed::to_string(sc_numrep numrep) const
+{
+ int len = length();
+ sc_fix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return aa.to_string(numrep);
+}
+
+const std::string
+sc_signed::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ int len = length();
+ sc_fix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return aa.to_string(numrep, w_prefix);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Interfacing with sc_int_base
+// ----------------------------------------------------------------------------
+
+const sc_signed &
+sc_signed::operator = (const sc_int_base &v)
+{
+ return operator = ((int64)v);
+}
+
+
+sc_signed
+operator + (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator + (u, static_cast<int64>(v));
+}
+
+sc_signed
+operator + (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator + (static_cast<int64>(u), v);
+}
+
+sc_signed
+operator + (const sc_signed &u, const sc_int_base &v)
+{
+ return operator + (u, (int64)v);
+}
+
+sc_signed
+operator + (const sc_int_base &u, const sc_signed &v)
+{
+ return operator + ((int64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator += (const sc_int_base &v)
+{
+ return operator += ((int64)v);
+}
+
+
+sc_signed
+operator - (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator - (u, (int64)v);
+}
+
+sc_signed
+operator - (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator - ((int64)u, v);
+}
+
+sc_signed
+operator - (const sc_signed &u, const sc_int_base &v)
+{
+ return operator - (u, (int64)v);
+}
+
+sc_signed
+operator - (const sc_int_base &u, const sc_signed &v)
+{
+ return operator - ((int64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator -= (const sc_int_base &v)
+{
+ return operator -= ((int64)v);
+}
+
+
+sc_signed
+operator * (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator * (u, static_cast<int64>(v));
+}
+
+sc_signed
+operator * (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator * (static_cast<int64>(u), v);
+}
+
+sc_signed
+operator * (const sc_signed &u, const sc_int_base &v)
+{
+ return operator * (u, (int64)v);
+}
+
+sc_signed
+operator * (const sc_int_base &u, const sc_signed &v)
+{
+ return operator * ((int64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator *= (const sc_int_base &v)
+{
+ return operator *= ((int64)v);
+}
+
+
+sc_signed
+operator / (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator / (u, static_cast<int64>(v));
+}
+
+sc_signed
+operator / (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator / (static_cast<int64>(u), v);
+}
+
+sc_signed
+operator / (const sc_signed &u, const sc_int_base &v)
+{
+ return operator / (u, (int64)v);
+}
+
+sc_signed
+operator / (const sc_int_base &u, const sc_signed &v)
+{
+ return operator / ((int64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator /= (const sc_int_base &v)
+{
+ return operator /= ((int64)v);
+}
+
+
+sc_signed
+operator % (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator % (u, static_cast<int64>(v));
+}
+
+sc_signed
+operator % (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator % (static_cast<int64>(u), v);
+}
+
+sc_signed
+operator % (const sc_signed &u, const sc_int_base &v)
+{
+ return operator % (u, (int64)v);
+}
+
+sc_signed
+operator % (const sc_int_base &u, const sc_signed &v)
+{
+ return operator % ((int64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator %= (const sc_int_base &v)
+{
+ return operator %= ((int64)v);
+}
+
+
+sc_signed
+operator & (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator & (u, static_cast<int64>(v));
+}
+
+sc_signed
+operator & (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator & (static_cast<int64>(u), v);
+}
+
+sc_signed
+operator & (const sc_signed &u, const sc_int_base &v)
+{
+ return operator & (u, (int64)v);
+}
+
+sc_signed
+operator & (const sc_int_base &u, const sc_signed &v)
+{
+ return operator & ((int64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator &= (const sc_int_base &v)
+{
+ return operator &= ((int64)v);
+}
+
+
+sc_signed
+operator | (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator | (u, static_cast<int64>(v));
+}
+
+sc_signed
+operator | (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator | (static_cast<int64>(u), v);
+}
+
+sc_signed
+operator | (const sc_signed& u, const sc_int_base &v)
+{
+ return operator|(u, (int64)v);
+}
+
+sc_signed
+operator | (const sc_int_base &u, const sc_signed &v)
+{
+ return operator | ((int64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator |= (const sc_int_base &v)
+{
+ return operator |= ((int64)v);
+}
+
+
+sc_signed
+operator ^ (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator ^ (u, static_cast<int64>(v));
+}
+
+sc_signed
+operator ^ (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator ^ (static_cast<int64>(u), v);
+}
+
+sc_signed
+operator ^ (const sc_signed &u, const sc_int_base &v)
+{
+ return operator ^ (u, (int64)v);
+}
+
+sc_signed
+operator ^ (const sc_int_base &u, const sc_signed &v)
+{
+ return operator ^ ((int64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator ^= (const sc_int_base &v)
+{
+ return operator ^= ((int64)v);
+}
+
+
+sc_signed
+operator << (const sc_signed &u, const sc_int_base &v)
+{
+ return operator << (u, (int64)v);
+}
+
+const sc_signed &
+sc_signed::operator <<= (const sc_int_base &v)
+{
+ return operator <<= ((int64)v);
+}
+
+
+sc_signed
+operator >> (const sc_signed &u, const sc_int_base &v)
+{
+ return operator >> (u, (int64)v);
+}
+
+const sc_signed &
+sc_signed::operator >>= (const sc_int_base &v)
+{
+ return operator >>= ((int64)v);
+}
+
+
+bool
+operator == (const sc_signed &u, const sc_int_base &v)
+{
+ return operator == (u, (int64)v);
+}
+
+bool
+operator == (const sc_int_base &u, const sc_signed &v)
+{
+ return operator == ((int64)u, v);
+}
+
+
+bool
+operator != (const sc_signed &u, const sc_int_base &v)
+{
+ return operator != (u, (int64)v);
+}
+
+bool
+operator != (const sc_int_base &u, const sc_signed &v)
+{
+ return operator != ((int64)u, v);
+}
+
+
+bool
+operator < (const sc_signed &u, const sc_int_base &v)
+{
+ return operator < (u, (int64)v);
+}
+
+bool
+operator < (const sc_int_base &u, const sc_signed &v)
+{
+ return operator < ((int64)u, v);
+}
+
+
+bool
+operator <= (const sc_signed &u, const sc_int_base &v)
+{
+ return operator <= (u, (int64)v);
+}
+
+bool
+operator <= (const sc_int_base &u, const sc_signed &v)
+{
+ return operator <= ((int64)u, v);
+}
+
+
+bool
+operator > (const sc_signed &u, const sc_int_base &v)
+{
+ return operator > (u, (int64)v);
+}
+
+bool
+operator > (const sc_int_base &u, const sc_signed &v)
+{
+ return operator > ((int64)u, v);
+}
+
+
+bool
+operator >= (const sc_signed &u, const sc_int_base &v)
+{
+ return operator >= (u, (int64)v);
+}
+
+bool
+operator >= (const sc_int_base &u, const sc_signed &v)
+{
+ return operator >= ((int64)u, v);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Interfacing with sc_uint_base
+// ----------------------------------------------------------------------------
+
+const sc_signed &
+sc_signed::operator = (const sc_uint_base &v)
+{
+ return operator = ((uint64)v);
+}
+
+
+sc_signed
+operator + (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator + (u, (uint64)v);
+}
+
+sc_signed
+operator + (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator + ((uint64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator += (const sc_uint_base &v)
+{
+ return operator += ((uint64)v);
+}
+
+
+sc_signed
+operator - (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator - (u, (uint64)v);
+}
+
+sc_signed
+operator - (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator - ((uint64)u, v);
+}
+
+sc_signed
+operator - (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator - (u, (uint64)v);
+}
+
+sc_signed
+operator - (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator - ((uint64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator -= (const sc_uint_base &v)
+{
+ return operator -= ((uint64)v);
+}
+
+
+sc_signed
+operator * (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator * (u, (uint64)v);
+}
+
+sc_signed
+operator * (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator * ((uint64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator *= (const sc_uint_base &v)
+{
+ return operator *= ((uint64)v);
+}
+
+
+sc_signed
+operator / (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator / (u, (uint64)v);
+}
+
+sc_signed
+operator / (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator / ((uint64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator /= (const sc_uint_base &v)
+{
+ return operator /= ((uint64)v);
+}
+
+
+sc_signed
+operator % (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator % (u, (uint64)v);
+}
+
+sc_signed
+operator % (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator % ((uint64)u, v);
+}
+
+const sc_signed&
+sc_signed::operator %= (const sc_uint_base &v)
+{
+ return operator %= ((uint64)v);
+}
+
+
+sc_signed
+operator & (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator & (u, (uint64)v);
+}
+
+sc_signed
+operator & (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator & ((uint64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator &= (const sc_uint_base &v)
+{
+ return operator &= ((uint64)v);
+}
+
+
+sc_signed
+operator | (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator | (u, (uint64)v);
+}
+
+sc_signed
+operator | (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator | ((uint64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator |= (const sc_uint_base &v)
+{
+ return operator |= ((uint64)v);
+}
+
+
+sc_signed
+operator ^ (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator ^ (u, (uint64)v);
+}
+
+sc_signed
+operator ^ (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator ^ ((uint64)u, v);
+}
+
+const sc_signed &
+sc_signed::operator ^= (const sc_uint_base &v)
+{
+ return operator ^= ((uint64)v);
+}
+
+
+sc_signed
+operator << (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator << (u, (uint64)v);
+}
+
+const sc_signed &
+sc_signed::operator <<= (const sc_uint_base &v)
+{
+ return operator <<= ((uint64)v);
+}
+
+
+sc_signed
+operator >> (const sc_signed& u, const sc_uint_base& v)
+{
+ return operator >> (u, (uint64)v);
+}
+
+const sc_signed &
+sc_signed::operator >>= (const sc_uint_base& v)
+{
+ return operator >>= ((uint64)v);
+}
+
+
+bool
+operator == (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator == (u, (uint64)v);
+}
+
+bool
+operator == (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator == ((uint64)u, v);
+}
+
+
+bool
+operator != (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator != (u, (uint64)v);
+}
+
+bool
+operator != (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator != ((uint64)u, v);
+}
+
+
+bool
+operator < (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator < (u, (uint64)v);
+}
+
+bool
+operator < (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator < ((uint64)u, v);
+}
+
+
+bool
+operator <= (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator <= (u, (uint64)v);
+}
+
+bool
+operator <= (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator <= ((uint64)u, v);
+}
+
+
+bool
+operator > (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator > (u, (uint64)v);
+}
+
+bool
+operator > (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator > ((uint64)u, v);
+}
+
+
+bool
+operator >= (const sc_signed &u, const sc_uint_base &v)
+{
+ return operator >= (u, (uint64)v);
+}
+
+bool
+operator >= (const sc_uint_base &u, const sc_signed &v)
+{
+ return operator >= ((uint64)u, v);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Input and output operators
+// ----------------------------------------------------------------------------
+
+// Operators in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Operator macros.
+// ----------------------------------------------------------------------------
+
+#define CONVERT_LONG(u) \
+small_type u ## s = get_sign(u); \
+sc_digit u ## d[DIGITS_PER_ULONG]; \
+from_uint(DIGITS_PER_ULONG, u ## d, (unsigned long) u);
+
+#define CONVERT_LONG_2(u) \
+sc_digit u ## d[DIGITS_PER_ULONG]; \
+from_uint(DIGITS_PER_ULONG, u ## d, (unsigned long) u);
+
+#define CONVERT_INT(u) \
+small_type u ## s = get_sign(u); \
+sc_digit u ## d[DIGITS_PER_UINT]; \
+from_uint(DIGITS_PER_UINT, u ## d, (unsigned int) u);
+
+#define CONVERT_INT_2(u) \
+sc_digit u ## d[DIGITS_PER_UINT]; \
+from_uint(DIGITS_PER_UINT, u ## d, (unsigned int) u);
+
+#define CONVERT_INT64(u) \
+small_type u ## s = get_sign(u); \
+sc_digit u ## d[DIGITS_PER_UINT64]; \
+from_uint(DIGITS_PER_UINT64, u ## d, (uint64) u);
+
+#define CONVERT_INT64_2(u) \
+sc_digit u ## d[DIGITS_PER_UINT64]; \
+from_uint(DIGITS_PER_UINT64, u ## d, (uint64) u);
+
+
+// ----------------------------------------------------------------------------
+// SECTION: PLUS operators: +, +=, ++
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u + v:
+// 1. 0 + v = v
+// 2. u + 0 = u
+// 3. if sgn(u) == sgn(v)
+// 3.1 u + v = +(u + v) = sgn(u) * (u + v)
+// 3.2 (-u) + (-v) = -(u + v) = sgn(u) * (u + v)
+// 4. if sgn(u) != sgn(v)
+// 4.1 u + (-v) = u - v = sgn(u) * (u - v)
+// 4.2 (-u) + v = -(u - v) ==> sgn(u) * (u - v)
+//
+// Specialization of above cases for computing ++u or u++:
+// 1. 0 + 1 = 1
+// 3. u + 1 = u + 1 = sgn(u) * (u + 1)
+// 4. (-u) + 1 = -(u - 1) = sgn(u) * (u - 1)
+
+sc_signed
+operator + (const sc_unsigned &u, const sc_signed &v)
+{
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_signed(v);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(u);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator + (const sc_signed &u, const sc_unsigned &v)
+{
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_signed(v);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(u);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator + (const sc_signed &u, const sc_signed &v)
+{
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_signed(v);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(u);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator + (const sc_signed &u, int64 v)
+{
+ if (v == 0) // case 2
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator + (int64 u, const sc_signed &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator + (const sc_unsigned &u, int64 v)
+{
+ if (v == 0) // case 2
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator + (int64 u, const sc_unsigned &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator + (const sc_signed &u, uint64 v)
+{
+ if (v == 0) // case 2
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator + (uint64 u, const sc_signed &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator + (const sc_signed &u, long v)
+{
+ if (v == 0) // case 2
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator + (long u, const sc_signed &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator + (const sc_unsigned &u, long v)
+{
+ if (v == 0) // case 2
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator + (long u, const sc_unsigned &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator + (const sc_signed &u, unsigned long v)
+{
+ if (v == 0) // case 2
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator + (unsigned long u, const sc_signed &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+// ----------------------------------------------------------------------------
+// SECTION: MINUS operators: -, -=, --
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u + v:
+// 1. u - 0 = u
+// 2. 0 - v = -v
+// 3. if sgn(u) != sgn(v)
+// 3.1 u - (-v) = u + v = sgn(u) * (u + v)
+// 3.2 (-u) - v = -(u + v) ==> sgn(u) * (u + v)
+// 4. if sgn(u) == sgn(v)
+// 4.1 u - v = +(u - v) = sgn(u) * (u - v)
+// 4.2 (-u) - (-v) = -(u - v) = sgn(u) * (u - v)
+//
+// Specialization of above cases for computing --u or u--:
+// 1. 0 - 1 = -1
+// 3. (-u) - 1 = -(u + 1) = sgn(u) * (u + 1)
+// 4. u - 1 = u - 1 = sgn(u) * (u - 1)
+
+sc_signed
+operator - (const sc_unsigned &u, const sc_unsigned &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_signed(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(v, -v.sgn);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_unsigned &u, const sc_signed &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_signed(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(v, -v.sgn);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_signed &u, const sc_unsigned &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_signed(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(v, -v.sgn);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_signed &u, const sc_signed &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_signed(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(v, -v.sgn);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_signed &u, int64 v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(-vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator - (int64 u, const sc_signed &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v, -v.sgn);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_unsigned &u, int64 v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(-vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator - (int64 u, const sc_unsigned &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v, -v.sgn);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_signed &u, uint64 v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(-vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // cases 3 and 4
+
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator - (uint64 u, const sc_signed &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v, -v.sgn);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_unsigned &u, uint64 v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(-vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator - (uint64 u, const sc_unsigned &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v, -v.sgn);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_signed &u, long v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(-vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator - (long u, const sc_signed &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v, -v.sgn);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_unsigned &u, long v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(-vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator - (long u, const sc_unsigned &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v, -v.sgn);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_signed &u, unsigned long v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(-vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator - (unsigned long u, const sc_signed &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v, -v.sgn);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator - (const sc_unsigned &u, unsigned long v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(-vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // cases 3 and 4
+ return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator - (unsigned long u, const sc_unsigned &v)
+{
+ if (u == 0) // case 1
+ return sc_signed(v, -v.sgn);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // cases 3 and 4
+ return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ -v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: MULTIPLICATION operators: *, *=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u * v:
+// 1. u * 0 = 0 * v = 0
+// 2. 1 * v = v and -1 * v = -v
+// 3. u * 1 = u and u * -1 = -u
+// 4. u * v = u * v
+
+sc_signed
+operator * (const sc_unsigned &u, const sc_signed &v)
+{
+ small_type s = mul_signs(u.sgn, v.sgn);
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ // cases 2-4
+ return mul_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator * (const sc_signed &u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(u.sgn, v.sgn);
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ // cases 2-4
+ return mul_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator * (const sc_signed &u, const sc_signed &v)
+{
+ small_type s = mul_signs(u.sgn, v.sgn);
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ // cases 2-4
+ return mul_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator * (const sc_signed &u, int64 v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_INT64_2(v);
+
+ // cases 2-4
+ return mul_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator * (int64 u, const sc_signed &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_INT64_2(u);
+
+ // cases 2-4
+ return mul_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator * (const sc_unsigned &u, int64 v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_INT64_2(v);
+
+ // cases 2-4
+ return mul_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator * (int64 u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_INT64_2(u);
+
+ // cases 2-4
+ return mul_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator * (const sc_signed &u, uint64 v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_INT64_2(v);
+
+ // cases 2-4
+ return mul_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator * (uint64 u, const sc_signed &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_INT64_2(u);
+
+ // cases 2-4
+ return mul_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator * (const sc_signed &u, long v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_LONG_2(v);
+
+ // cases 2-4
+ return mul_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator * (long u, const sc_signed &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_LONG_2(u);
+
+ // cases 2-4
+ return mul_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator * (const sc_unsigned &u, long v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_LONG_2(v);
+
+ // cases 2-4
+ return mul_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator * (long u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_LONG_2(u);
+
+ // cases 2-4
+ return mul_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator * (const sc_signed &u, unsigned long v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_LONG_2(v);
+
+ // else cases 2-4
+ return mul_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+sc_signed
+operator * (unsigned long u, const sc_signed &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) // case 1
+ return sc_signed();
+
+ CONVERT_LONG_2(u);
+
+ // cases 2-4
+ return mul_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: DIVISION operators: /, /=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when finding the quotient q = floor(u/v):
+// Note that u = q * v + r for r < q.
+// 1. 0 / 0 or u / 0 => error
+// 2. 0 / v => 0 = 0 * v + 0
+// 3. u / v & &u = v => u = 1 * u + 0 - u or v can be 1 or -1
+// 4. u / v & &u < v => u = 0 * v + u - u can be 1 or -1
+// 5. u / v & &u > v => u = q * v + r - v can be 1 or -1
+
+sc_signed
+operator / (const sc_unsigned &u, const sc_signed &v)
+{
+ small_type s = mul_signs(u.sgn, v.sgn);
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ // other cases
+ return div_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator / (const sc_signed &u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(u.sgn, v.sgn);
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ // other cases
+ return div_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator / (const sc_signed &u, const sc_signed &v)
+{
+ small_type s = mul_signs(u.sgn, v.sgn);
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ // other cases
+ return div_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator / (const sc_signed &u, int64 v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64_2(v);
+
+ // other cases
+ return div_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator / (int64 u, const sc_signed &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64_2(u);
+
+ // other cases
+ return div_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator / (const sc_unsigned &u, int64 v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64_2(v);
+
+ // other cases
+ return div_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator / (int64 u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64_2(u);
+
+ // other cases
+ return div_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator / (const sc_signed &u, uint64 v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64_2(v);
+
+ // other cases
+ return div_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator / (uint64 u, const sc_signed &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+
+ }
+
+ CONVERT_INT64_2(u);
+
+ // other cases
+ return div_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator / (const sc_signed &u, long v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG_2(v);
+
+ // other cases
+ return div_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator / (long u, const sc_signed &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG_2(u);
+
+ // other cases
+ return div_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator / (const sc_unsigned &u, long v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG_2(v);
+
+ // other cases
+ return div_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator / (long u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG_2(u);
+
+ // other cases
+ return div_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator / (const sc_signed &u, unsigned long v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG_2(v);
+
+ // other cases
+ return div_signed_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator / (unsigned long u, const sc_signed &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+
+ }
+
+ CONVERT_LONG_2(u);
+
+ // other cases
+ return div_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: MOD operators: %, %=.
+// ----------------------------------------------------------------------------
+
+// Cases to consider when finding the remainder r = u % v:
+// Note that u = q * v + r for r < q.
+// 1. 0 % 0 or u % 0 => error
+// 2. 0 % v => 0 = 0 * v + 0
+// 3. u % v & &u = v => u = 1 * u + 0 - u or v can be 1 or -1
+// 4. u % v & &u < v => u = 0 * v + u - u can be 1 or -1
+// 5. u % v & &u > v => u = q * v + r - v can be 1 or -1
+
+sc_signed
+operator % (const sc_unsigned &u, const sc_signed &v)
+{
+ if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ // other cases
+ return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator % (const sc_signed &u, const sc_unsigned &v)
+{
+ if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ // other cases
+ return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator % (const sc_signed &u, const sc_signed &v)
+{
+ if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ // other cases
+ return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator % (const sc_signed &u, int64 v)
+{
+ small_type vs = get_sign(v);
+
+ if ((u.sgn == SC_ZERO) || (vs == SC_ZERO)) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64_2(v);
+
+ // other cases
+ return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator % (int64 u, const sc_signed &v)
+{
+ small_type us = get_sign(u);
+
+ if ((us == SC_ZERO) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64_2(u);
+
+ // other cases
+ return mod_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator % (const sc_unsigned &u, int64 v)
+{
+ small_type vs = get_sign(v);
+
+ if ((u.sgn == SC_ZERO) || (vs == SC_ZERO)) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64_2(v);
+
+ // other cases
+ return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator % (int64 u, const sc_unsigned &v)
+{
+ small_type us = get_sign(u);
+
+ if ((us == SC_ZERO) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64_2(u);
+
+ // other cases
+ return mod_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator % (const sc_signed &u, uint64 v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64_2(v);
+
+ // other cases
+ return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator % (uint64 u, const sc_signed &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_INT64(u);
+
+ // other cases
+ return mod_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator % (const sc_signed &u, long v)
+{
+ small_type vs = get_sign(v);
+
+ if ((u.sgn == SC_ZERO) || (vs == SC_ZERO)) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG_2(v);
+
+ // other cases
+ return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator % (long u, const sc_signed &v)
+{
+ small_type us = get_sign(u);
+
+ if ((us == SC_ZERO) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG_2(u);
+
+ // other cases
+ return mod_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator % (const sc_unsigned &u, long v)
+{
+
+ small_type vs = get_sign(v);
+
+ if ((u.sgn == SC_ZERO) || (vs == SC_ZERO)) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG_2(v);
+
+ // other cases
+ return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator % (long u, const sc_unsigned &v)
+{
+ small_type us = get_sign(u);
+
+ if ((us == SC_ZERO) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG_2(u);
+
+ // other cases
+ return mod_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator % (const sc_signed &u, unsigned long v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) {
+ div_by_zero(v); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG_2(v);
+
+ // other cases
+ return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator % (unsigned long u, const sc_signed &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_signed(); // case 2
+ }
+
+ CONVERT_LONG(u);
+
+ // other cases
+ return mod_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise AND operators: &, &=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u &v:
+// 1. u & 0 = 0 &v = 0
+// 2. u &v => sgn = +
+// 3. (-u) & (-v) => sgn = -
+// 4. u & (-v) => sgn = +
+// 5. (-u) &v => sgn = +
+
+sc_signed
+operator & (const sc_unsigned &u, const sc_signed &v)
+{
+ if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) // case 1
+ return sc_signed();
+
+ // other cases
+ return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator & (const sc_signed &u, const sc_unsigned &v)
+{
+ if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) // case 1
+ return sc_signed();
+
+ // other cases
+ return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator & (const sc_signed &u, const sc_signed &v)
+{
+ if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) // case 1
+ return sc_signed();
+
+ // other cases
+ return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator & (const sc_signed &u, int64 v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) // case 1
+ return sc_signed();
+
+ CONVERT_INT64(v);
+
+ // other cases
+ return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator & (int64 u, const sc_signed &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) // case 1
+ return sc_signed();
+
+ CONVERT_INT64(u);
+
+ // other cases
+ return and_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator & (const sc_unsigned &u, int64 v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) // case 1
+ return sc_signed();
+
+ CONVERT_INT64(v);
+
+ // other cases
+ return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator & (int64 u, const sc_unsigned &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) // case 1
+ return sc_signed();
+
+ CONVERT_INT64(u);
+
+ // other cases
+ return and_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator & (const sc_signed &u, uint64 v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) // case 1
+ return sc_signed();
+
+ CONVERT_INT64(v);
+
+ // other cases
+ return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator & (uint64 u, const sc_signed &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) // case 1
+ return sc_signed();
+
+ CONVERT_INT64(u);
+
+ // other cases
+ return and_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator & (const sc_signed &u, long v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) // case 1
+ return sc_signed();
+
+ CONVERT_LONG(v);
+
+ // other cases
+ return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator & (long u, const sc_signed &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) // case 1
+ return sc_signed();
+
+ CONVERT_LONG(u);
+
+ // other cases
+ return and_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator & (const sc_unsigned &u, long v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) // case 1
+ return sc_signed();
+
+ CONVERT_LONG(v);
+
+ // other cases
+ return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator & (long u, const sc_unsigned &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) // case 1
+ return sc_signed();
+
+ CONVERT_LONG(u);
+
+ // other cases
+ return and_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator & (const sc_signed &u, unsigned long v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) // case 1
+ return sc_signed();
+
+ CONVERT_LONG(v);
+
+ // other cases
+ return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator & (unsigned long u, const sc_signed &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) // case 1
+ return sc_signed();
+
+ CONVERT_LONG(u);
+
+ // other cases
+ return and_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise OR operators: |, |=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u | v:
+// 1. u | 0 = u
+// 2. 0 | v = v
+// 3. u | v => sgn = +
+// 4. (-u) | (-v) => sgn = -
+// 5. u | (-v) => sgn = -
+// 6. (-u) | v => sgn = -
+
+sc_signed
+operator | (const sc_unsigned &u, const sc_signed &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_signed(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(v);
+
+ // other cases
+ return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator | (const sc_signed &u, const sc_unsigned &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_signed(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(v);
+
+ // other cases
+ return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator | (const sc_signed &u, const sc_signed &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_signed(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(v);
+
+ // other cases
+ return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator | (const sc_signed &u, int64 v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // other cases
+ return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator | (int64 u, const sc_signed &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // other cases
+ return or_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator | (const sc_unsigned &u, int64 v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // other cases
+ return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator | (int64 u, const sc_unsigned &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // other cases
+ return or_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator | (const sc_signed &u, uint64 v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // other cases
+ return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator | (uint64 u, const sc_signed &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // other cases
+ return or_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator | (const sc_signed &u, long v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // other cases
+ return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator | (long u, const sc_signed &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // other cases
+ return or_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator | (const sc_unsigned &u, long v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // other cases
+ return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator | (long u, const sc_unsigned &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // other cases
+ return or_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator | (const sc_signed &u, unsigned long v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // other cases
+ return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator | (unsigned long u, const sc_signed &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // other cases
+ return or_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise XOR operators: ^, ^=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u ^ v:
+// Note that u ^ v = (~u &v) | (u & ~v).
+// 1. u ^ 0 = u
+// 2. 0 ^ v = v
+// 3. u ^ v => sgn = +
+// 4. (-u) ^ (-v) => sgn = -
+// 5. u ^ (-v) => sgn = -
+// 6. (-u) ^ v => sgn = +
+
+sc_signed
+operator ^ (const sc_unsigned &u, const sc_signed &v)
+{
+
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_signed(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(v);
+
+ // other cases
+ return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+
+}
+
+
+sc_signed
+operator ^ (const sc_signed &u, const sc_unsigned &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_signed(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(v);
+
+ // other cases
+ return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator ^ (const sc_signed &u, const sc_signed &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_signed(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(v);
+
+ // other cases
+ return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator ^ (const sc_signed &u, int64 v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // other cases
+ return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator ^ (int64 u, const sc_signed &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // other cases
+ return xor_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator ^ (const sc_unsigned &u, int64 v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // other cases
+ return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_signed
+operator ^ (int64 u, const sc_unsigned &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // other cases
+ return xor_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator ^ (const sc_signed &u, uint64 v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // other cases
+ return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+sc_signed
+operator ^ (uint64 u, const sc_signed &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // other cases
+ return xor_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator ^ (const sc_signed &u, long v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // other cases
+ return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator ^ (long u, const sc_signed &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // other cases
+ return xor_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator ^ (const sc_unsigned &u, long v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // other cases
+ return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_signed
+operator ^ (long u, const sc_unsigned &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // other cases
+ return xor_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_signed
+operator ^ (const sc_signed &u, unsigned long v)
+{
+ if (v == 0) // case 1
+ return sc_signed(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // other cases
+ return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+sc_signed
+operator ^ (unsigned long u, const sc_signed &v)
+{
+ if (u == 0)
+ return sc_signed(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // other cases
+ return xor_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise NOT operator: ~
+// ----------------------------------------------------------------------------
+
+// Operators in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: LEFT SHIFT operators: <<, <<=
+// ----------------------------------------------------------------------------
+
+sc_signed
+operator << (const sc_signed &u, const sc_unsigned &v)
+{
+ if (v.sgn == SC_ZERO)
+ return sc_signed(u);
+
+ return operator << (u, v.to_ulong());
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: RIGHT SHIFT operators: >>, >>=
+// ----------------------------------------------------------------------------
+
+sc_signed
+operator >> (const sc_signed &u, const sc_unsigned &v)
+{
+ if (v.sgn == SC_ZERO)
+ return sc_signed(u);
+
+ return operator >> (u, v.to_ulong());
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Unary arithmetic operators.
+// ----------------------------------------------------------------------------
+
+sc_signed
+operator + (const sc_signed &u)
+{
+ return sc_signed(u);
+}
+
+sc_signed
+operator - (const sc_signed &u)
+{
+ return sc_signed(u, -u.sgn);
+}
+
+sc_signed
+operator - (const sc_unsigned &u)
+{
+ return sc_signed(u, -u.sgn);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: EQUAL operator: ==
+// ----------------------------------------------------------------------------
+
+bool
+operator == (const sc_signed &u, const sc_signed &v)
+{
+ if (u.sgn != v.sgn)
+ return false;
+
+ if (&u == &v)
+ return true;
+
+ if (vec_skip_and_cmp(u.ndigits, u.digit, v.ndigits, v.digit) != 0)
+ return false;
+
+ return true;
+}
+
+
+bool
+operator == (const sc_signed &u, int64 v)
+{
+ CONVERT_INT64(v);
+
+ if (u.sgn != vs)
+ return false;
+
+ if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_INT64, vd) != 0)
+ return false;
+
+ return true;
+}
+
+
+bool
+operator == (int64 u, const sc_signed &v)
+{
+ CONVERT_INT64(u);
+
+ if (us != v.sgn)
+ return false;
+
+ if (vec_skip_and_cmp(DIGITS_PER_INT64, ud, v.ndigits, v.digit) != 0)
+ return false;
+
+ return true;
+}
+
+
+bool
+operator == (const sc_signed &u, uint64 v)
+{
+ CONVERT_INT64(v);
+
+ if (u.sgn != vs)
+ return false;
+
+ if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_INT64, vd) != 0)
+ return false;
+
+ return true;
+}
+
+
+bool
+operator == (uint64 u, const sc_signed &v)
+{
+ CONVERT_INT64(u);
+
+ if (us != v.sgn)
+ return false;
+
+ if (vec_skip_and_cmp(DIGITS_PER_INT64, ud, v.ndigits, v.digit) != 0)
+ return false;
+
+ return true;
+}
+
+
+bool
+operator == (const sc_signed &u, long v)
+{
+ CONVERT_LONG(v);
+
+ if (u.sgn != vs)
+ return false;
+
+ if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_LONG, vd) != 0)
+ return false;
+
+ return true;
+}
+
+
+bool
+operator == (long u, const sc_signed &v)
+{
+ CONVERT_LONG(u);
+
+ if (us != v.sgn)
+ return false;
+
+ if (vec_skip_and_cmp(DIGITS_PER_LONG, ud, v.ndigits, v.digit) != 0)
+ return false;
+
+ return true;
+}
+
+
+bool
+operator == (const sc_signed &u, unsigned long v)
+{
+ CONVERT_LONG(v);
+
+ if (u.sgn != vs)
+ return false;
+
+ if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_LONG, vd) != 0)
+ return false;
+
+ return true;
+}
+
+
+bool
+operator == (unsigned long u, const sc_signed &v)
+{
+ CONVERT_LONG(u);
+
+ if (us != v.sgn)
+ return false;
+
+ if (vec_skip_and_cmp(DIGITS_PER_LONG, ud, v.ndigits, v.digit) != 0)
+ return false;
+
+ return true;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: NOT_EQUAL operator: !=
+// ----------------------------------------------------------------------------
+
+// Operators in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: LESS THAN operator: <
+// ----------------------------------------------------------------------------
+
+bool
+operator < (const sc_signed &u, const sc_signed &v)
+{
+ if (u.sgn < v.sgn)
+ return true;
+
+ if (u.sgn > v.sgn)
+ return false;
+
+ // u.sgn == v.sgn
+
+ if (&u == &v)
+ return false;
+
+ if (u.sgn == SC_POS) {
+ if (vec_skip_and_cmp(u.ndigits, u.digit, v.ndigits, v.digit) < 0)
+ return true;
+ } else if (u.sgn == SC_NEG) {
+ if (vec_skip_and_cmp(u.ndigits, u.digit, v.ndigits, v.digit) > 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+operator < (const sc_signed &u, int64 v)
+{
+ CONVERT_INT64(v);
+
+ if (u.sgn < vs)
+ return true;
+
+ if (u.sgn > vs)
+ return false;
+
+ // u.sgn == vs
+
+ if (vs == SC_POS) {
+ if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_INT64, vd) < 0)
+ return true;
+ } else if (vs == SC_NEG) {
+ if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_INT64, vd) > 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+operator < (int64 u, const sc_signed &v)
+{
+ CONVERT_INT64(u);
+
+ if (us < v.sgn)
+ return true;
+
+ if (us > v.sgn)
+ return false;
+
+ // us == v.sgn
+
+ if (us == SC_POS) {
+ if (vec_skip_and_cmp(DIGITS_PER_INT64, ud, v.ndigits, v.digit) < 0)
+ return true;
+ } else if (us == SC_NEG) {
+ if (vec_skip_and_cmp(DIGITS_PER_INT64, ud, v.ndigits, v.digit) > 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+operator < (const sc_signed &u, uint64 v)
+{
+ CONVERT_INT64(v);
+
+ if (u.sgn < vs)
+ return true;
+
+ if (u.sgn > vs)
+ return false;
+
+ // u.sgn == vs
+
+ if (vs == SC_POS) {
+ if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_INT64, vd) < 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+operator < (uint64 u, const sc_signed &v)
+{
+ CONVERT_INT64(u);
+
+ if (us < v.sgn)
+ return true;
+
+ if (us > v.sgn)
+ return false;
+
+ // us == v.sgn
+
+ if (us == SC_POS) {
+ if (vec_skip_and_cmp(DIGITS_PER_INT64, ud, v.ndigits, v.digit) < 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+operator < (const sc_signed &u, long v)
+{
+ CONVERT_LONG(v);
+
+ if (u.sgn < vs)
+ return true;
+
+ if (u.sgn > vs)
+ return false;
+
+ // u.sgn == vs
+
+ if (vs == SC_POS) {
+ if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_LONG, vd) < 0)
+ return true;
+
+ } else if (vs == SC_NEG) {
+ if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_LONG, vd) > 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+operator < (long u, const sc_signed &v)
+{
+ CONVERT_LONG(u);
+
+ if (us < v.sgn)
+ return true;
+
+ if (us > v.sgn)
+ return false;
+
+ // us == v.sgn
+
+ if (us == SC_POS) {
+ if (vec_skip_and_cmp(DIGITS_PER_LONG, ud, v.ndigits, v.digit) < 0)
+ return true;
+ } else if (us == SC_NEG) {
+ if (vec_skip_and_cmp(DIGITS_PER_LONG, ud, v.ndigits, v.digit) > 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+operator < (const sc_signed &u, unsigned long v)
+{
+ CONVERT_LONG(v);
+
+ if (u.sgn < vs)
+ return true;
+
+ if (u.sgn > vs)
+ return false;
+
+ // u.sgn == vs
+
+ if (vs == SC_POS) {
+ if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_LONG, vd) < 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+operator < (unsigned long u, const sc_signed &v)
+{
+ CONVERT_LONG(u);
+
+ if (us < v.sgn)
+ return true;
+
+ if (us > v.sgn)
+ return false;
+
+ // us == v.sgn
+
+ if (us == SC_POS) {
+ if (vec_skip_and_cmp(DIGITS_PER_LONG, ud, v.ndigits, v.digit) < 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// SECTION: LESS THAN or EQUAL operator: <=
+// ---------------------------------------------------------------------------
+
+// Operators in this section are included from sc_nbcommon.cpp.
+
+
+// ---------------------------------------------------------------------------
+// SECTION: GREATER THAN operator: >
+// ---------------------------------------------------------------------------
+
+// Operators in this section are included from sc_nbcommon.cpp.
+
+
+// ---------------------------------------------------------------------------
+// SECTION: GREATER THAN or EQUAL operator: >=
+// ---------------------------------------------------------------------------
+
+// Operators in this section are included from sc_nbcommon.cpp.
+
+
+// ---------------------------------------------------------------------------
+// SECTION: Public members - Other utils.
+// ---------------------------------------------------------------------------
+
+bool
+sc_signed::iszero() const
+{
+ if (sgn == SC_ZERO)
+ return true;
+ else if (sgn != SC_NOSIGN)
+ return false;
+ else
+ return check_for_zero(ndigits, digit);
+}
+
+
+bool
+sc_signed::sign() const
+{
+ if (sgn == SC_NEG)
+ return 1;
+ else if (sgn != SC_NOSIGN)
+ return 0;
+ else
+ return ((digit[ndigits - 1] & one_and_zeros(bit_ord(nbits - 1))) != 0);
+}
+
+// The rest of the utils in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Private members.
+// ----------------------------------------------------------------------------
+
+// The private members in this section are included from sc_nbcommon.cpp.
+
+#define CLASS_TYPE sc_signed
+#define CLASS_TYPE_STR "sc_signed"
+
+#define ADD_HELPER add_signed_friend
+#define SUB_HELPER sub_signed_friend
+#define MUL_HELPER mul_signed_friend
+#define DIV_HELPER div_signed_friend
+#define MOD_HELPER mod_signed_friend
+#define AND_HELPER and_signed_friend
+#define OR_HELPER or_signed_friend
+#define XOR_HELPER xor_signed_friend
+
+#include "sc_nbfriends.inc"
+
+#undef SC_UNSIGNED
+#define SC_SIGNED
+#define IF_SC_SIGNED 1 // 1 = sc_signed
+#define CLASS_TYPE_SUBREF sc_signed_subref_r
+#define OTHER_CLASS_TYPE sc_unsigned
+#define OTHER_CLASS_TYPE_SUBREF sc_unsigned_subref_r
+
+#define MUL_ON_HELPER mul_on_help_signed
+#define DIV_ON_HELPER div_on_help_signed
+#define MOD_ON_HELPER mod_on_help_signed
+
+#include "sc_nbcommon.inc"
+
+#undef MOD_ON_HELPER
+#undef DIV_ON_HELPER
+#undef MUL_ON_HELPER
+
+#undef OTHER_CLASS_TYPE_SUBREF
+#undef OTHER_CLASS_TYPE
+#undef CLASS_TYPE_SUBREF
+#undef IF_SC_SIGNED
+#undef SC_SIGNED
+
+#undef XOR_HELPER
+#undef OR_HELPER
+#undef AND_HELPER
+#undef MOD_HELPER
+#undef DIV_HELPER
+#undef MUL_HELPER
+#undef SUB_HELPER
+#undef ADD_HELPER
+
+#undef CLASS_TYPE
+#undef CLASS_TYPE_STR
+
+#include "sc_signed_bitref.inc"
+#include "sc_signed_subref.inc"
+
+#undef CONVERT_LONG
+#undef CONVERT_LONG_2
+#undef CONVERT_INT64
+#undef CONVERT_INT64_2
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_signed_bitref.h -- Proxy class that is declared in sc_signed.h.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_signed_bitref_r
+//
+// Proxy class for sc_signed bit selection (r-value only).
+// ----------------------------------------------------------------------------
+
+// implicit conversion to uint64
+
+sc_signed_bitref_r::operator uint64 () const
+{
+ return m_obj_p->test(m_index);
+}
+
+bool
+sc_signed_bitref_r::operator ! () const
+{
+ return (!m_obj_p->test(m_index));
+}
+
+bool
+sc_signed_bitref_r::operator ~ () const
+{
+ return (!m_obj_p->test(m_index));
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_signed_bitref
+//
+// Proxy class for sc_signed bit selection (r-value and l-value).
+// ----------------------------------------------------------------------------
+
+// assignment operators
+
+const sc_signed_bitref &
+sc_signed_bitref::operator = (const sc_signed_bitref_r &b)
+{
+ m_obj_p->set(m_index, (bool)b);
+ return *this;
+}
+
+const sc_signed_bitref &
+sc_signed_bitref::operator = (const sc_signed_bitref &b)
+{
+ m_obj_p->set(m_index, (bool)b);
+ return *this;
+}
+
+const sc_signed_bitref &
+sc_signed_bitref::operator = (bool b)
+{
+ m_obj_p->set(m_index, b);
+ return *this;
+}
+
+
+const sc_signed_bitref &
+sc_signed_bitref::operator &= (bool b)
+{
+ if (!b) {
+ m_obj_p->clear(m_index);
+ }
+ return *this;
+}
+
+const sc_signed_bitref &
+sc_signed_bitref::operator |= (bool b)
+{
+ if (b) {
+ m_obj_p->set(m_index);
+ }
+ return *this;
+}
+
+const sc_signed_bitref &
+sc_signed_bitref::operator ^= (bool b)
+{
+ if (b) {
+ m_obj_p->invert(m_index);
+ }
+ return *this;
+}
+
+// #### OPTIMIZE
+void
+sc_signed_bitref::concat_set(int64 src, int low_i)
+{
+ bool value = 1 & ((low_i < 64) ? (src >> low_i) : (src >> 63));
+ m_obj_p->set(low_i, value);
+}
+
+void
+sc_signed_bitref::concat_set(const sc_signed &src, int low_i)
+{
+ if (low_i < src.length())
+ m_obj_p->set(low_i, src.test(low_i));
+ else
+ m_obj_p->set(low_i, src < 0);
+}
+
+void
+sc_signed_bitref::concat_set(const sc_unsigned &src, int low_i)
+{
+ if (low_i < src.length())
+ m_obj_p->set(low_i, src.test(low_i));
+ else
+ m_obj_p->set(low_i, 0);
+}
+
+void
+sc_signed_bitref::concat_set(uint64 src, int low_i)
+{
+ bool value = 1 & ((low_i < 64) ? (src >> low_i) : 0);
+ m_obj_p->set(low_i, value);
+}
+
+
+// other methods
+void
+sc_signed_bitref::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_signed_subref.h -- Proxy class that is declared in sc_signed.h.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_signed_subref_r
+//
+// Proxy class for sc_signed part selection (r-value only).
+// ----------------------------------------------------------------------------
+
+// concatenation support
+
+uint64
+sc_signed_subref_r::concat_get_uint64() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_uint64();
+}
+
+
+bool
+sc_signed_subref_r::concat_get_ctrl(sc_digit *dst_p, int low_i) const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.concat_get_ctrl(dst_p, low_i);
+}
+
+
+bool
+sc_signed_subref_r::concat_get_data(sc_digit *dst_p, int low_i) const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.concat_get_data(dst_p, low_i);
+}
+
+
+// implicit conversion to sc_signed
+sc_signed_subref_r::operator sc_unsigned () const
+{
+ return sc_unsigned(m_obj_p, m_left, m_right);
+}
+
+
+// explicit conversions
+int
+sc_signed_subref_r::to_int() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_int();
+}
+
+unsigned int
+sc_signed_subref_r::to_uint() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_uint();
+}
+
+long
+sc_signed_subref_r::to_long() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_long();
+}
+
+unsigned long
+sc_signed_subref_r::to_ulong() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_ulong();
+}
+
+int64
+sc_signed_subref_r::to_int64() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_int64();
+}
+
+uint64
+sc_signed_subref_r::to_uint64() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_uint64();
+}
+
+double
+sc_signed_subref_r::to_double() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_double();
+}
+
+
+// explicit conversion to character string
+const std::string
+sc_signed_subref_r::to_string(sc_numrep numrep) const
+{
+ sc_unsigned a(length());
+ a = *this;
+ return a.to_string(numrep);
+}
+
+const std::string
+sc_signed_subref_r::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ sc_unsigned a(length());
+ a = *this;
+ return a.to_string(numrep, w_prefix);
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_signed_subref
+//
+// Proxy class for sc_signed part selection (r-value and l-value).
+// ----------------------------------------------------------------------------
+
+// assignment operators
+
+const sc_signed_subref &
+sc_signed_subref::operator = (const sc_signed_subref_r &a)
+{
+ return operator = ((sc_unsigned)(a));
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (const sc_signed_subref &v)
+{
+ if (this == &v) {
+ return *this;
+ }
+ return operator = ((sc_unsigned)(v));
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (const sc_signed &v)
+{
+ int i;
+ int l = sc_min(m_left, v.nbits - 1 + m_right);
+
+ for (i = m_right; i <= l; ++i)
+ m_obj_p->set(i, v.test(i - m_right));
+ for (; i <= m_left; i++)
+ m_obj_p->set(i, v.test(l));
+
+ return *this;
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (const sc_unsigned_subref_r &v)
+{
+ return operator = ((sc_unsigned)(v));
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (const sc_unsigned &v)
+{
+ int i;
+ int l = sc_min(m_left, v.nbits - 1 + m_right);
+
+ for (i = m_right; i <= l; ++i)
+ m_obj_p->set(i, v.test(i - m_right));
+ for (; i <= m_left; i++)
+ m_obj_p->set(i, 0);
+ return *this;
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (unsigned long v)
+{
+ for (int i = m_right; i <= m_left; ++i) {
+ m_obj_p->set(i, static_cast<bool>(v & 1));
+ v >>= 1;
+ }
+ return *this;
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (long v)
+{
+ unsigned long v2 = (unsigned long)v;
+ for (int i = m_right; i <= m_left; ++i) {
+ m_obj_p->set(i, static_cast<bool>(v2 & 1));
+ v2 >>= 1;
+ }
+ return *this;
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (uint64 v)
+{
+ for (int i = m_right; i <= m_left; ++i) {
+ m_obj_p->set(i, static_cast<bool>(v & 1));
+ v >>= 1;
+ }
+ return *this;
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (int64 v)
+{
+ uint64 v2 = (uint64)v;
+ for (int i = m_right; i <= m_left; ++i) {
+ m_obj_p->set(i, static_cast<bool>(v2 & 1));
+ v2 >>= 1;
+ }
+ return *this;
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (double v)
+{
+ is_bad_double(v);
+
+ int nb = m_left - m_right + 1;
+ int nd = DIV_CEIL(nb);
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ if (v < 0)
+ v = -v;
+
+ int i = 0;
+
+ while (std::floor(v) && (i < nd)) {
+#ifndef _WIN32
+ d[i++] = (sc_digit) std::floor(remainder(v, DIGIT_RADIX));
+#else
+ d[i++] = (sc_digit) std::floor(std::fmod(v, DIGIT_RADIX));
+#endif
+ v /= DIGIT_RADIX;
+ }
+
+ vec_zero(i, nd, d);
+ sc_digit val = 1; // Bit value.
+ int j = 0; // Current digit in d.
+ i = 0; // Current bit in d.
+ while (i < nb) {
+ m_obj_p->set(i + m_right, (bool)(d[j] & val));
+ ++i;
+ if (i % BITS_PER_DIGIT == 0) {
+ val = 1;
+ ++j;
+ } else {
+ val <<= 1;
+ }
+ }
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ return *this;
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (const sc_int_base &a)
+{
+ return operator = ((int64)a);
+}
+
+const sc_signed_subref &
+sc_signed_subref::operator = (const sc_uint_base &a)
+{
+ return operator = ((uint64)a);
+}
+
+// concatenation methods
+
+
+void
+sc_signed_subref::concat_set(int64 src, int low_i)
+{
+ int i;
+ int l;
+ bool sign = src < 0;
+
+ if (low_i < 64) {
+ src = src >> low_i;
+ l = sc_min(m_left, (63 - low_i) + m_right);
+ for (i = m_right; i <= l; ++i) {
+ m_obj_p->set(i, src & 1);
+ src = src >> 1;
+ }
+ for (; i <= m_left; i++)
+ m_obj_p->set(i, sign);
+ } else {
+ for (i = m_right; i <= m_left; ++i)
+ m_obj_p->set(i, sign);
+ }
+}
+
+void
+sc_signed_subref::concat_set(const sc_signed &src, int low_i)
+{
+ int i;
+ int l;
+ int src_i;
+ bool sign = src.test(src.nbits - 1);
+ l = src.nbits - (low_i + 1);
+ if (l >= 0) {
+ l = sc_min(m_left, l + m_right);
+ src_i = low_i;
+ for (i = m_right; i <= l; ++i, src_i++) {
+ m_obj_p->set(i, src.test(src_i));
+ }
+ for (; i <= m_left; i++)
+ m_obj_p->set(i, sign);
+ } else {
+ for (i = m_right; i <= m_left; ++i)
+ m_obj_p->set(i, sign);
+ }
+}
+
+void
+sc_signed_subref::concat_set(const sc_unsigned &src, int low_i)
+{
+ int i;
+ int l;
+ int src_i;
+ l = src.nbits - (low_i + 2);
+ if (l >= 0) {
+ l = sc_min(m_left, l + m_right);
+ src_i = low_i;
+ for (i = m_right; i <= l; ++i, src_i++) {
+ m_obj_p->set(i, src.test(src_i));
+ }
+ for (; i <= m_left; i++)
+ m_obj_p->set(false);
+ } else {
+ for (i = m_right; i <= m_left; ++i)
+ m_obj_p->set(false);
+ }
+}
+
+void
+sc_signed_subref::concat_set(uint64 src, int low_i)
+{
+ int i;
+ int l;
+
+ if (low_i < 64) {
+ src = src >> low_i;
+ l = sc_min(m_left, (63 - low_i) + m_right);
+ for (i = m_right; i <= l; ++i) {
+ m_obj_p->set(i, src & 1);
+ src = src >> 1;
+ }
+ for (; i <= m_left; i++)
+ m_obj_p->set(false);
+ } else {
+ for (i = m_right; i <= m_left; ++i)
+ m_obj_p->set(false);
+ }
+}
+
+// other methods
+void
+sc_signed_subref::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_uint_base.cpp -- contains interface definitions between sc_uint and
+ sc_signed, sc_unsigned, and definitions for sc_uint_subref.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_uint_base.cpp,v $
+// Revision 1.5 2011/02/18 20:19:15 acg
+// Andy Goodrich: updating Copyright notice.
+//
+// Revision 1.4 2010/02/04 22:23:29 acg
+// Andy Goodrich: fixed bug in concatenation reads for part selections,
+// the mask being used was 32 bits and should have been 64 bits.
+//
+// Revision 1.3 2008/06/19 17:47:57 acg
+// Andy Goodrich: fixes for bugs. See 2.2.1 RELEASENOTES.
+//
+// Revision 1.2 2007/11/04 21:27:00 acg
+// Andy Goodrich: changes to make sure the proper value is returned from
+// concat_get_data().
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:49:32 acg
+// Added $Log command so that CVS check in comments are reproduced in the
+// source.
+//
+
+#include <sstream>
+
+#include "systemc/ext/dt/bit/sc_bv_base.hh"
+#include "systemc/ext/dt/bit/sc_lv_base.hh"
+#include "systemc/ext/dt/fx/sc_ufix.hh"
+#include "systemc/ext/dt/fx/scfx_other_defs.hh"
+#include "systemc/ext/dt/int/sc_signed.hh"
+#include "systemc/ext/dt/int/sc_uint_base.hh"
+#include "systemc/ext/dt/int/sc_unsigned.hh"
+#include "systemc/ext/dt/misc/sc_concatref.hh"
+
+// explicit template instantiations
+namespace sc_core
+{
+
+template class sc_vpool<sc_dt::sc_uint_bitref>;
+template class sc_vpool<sc_dt::sc_uint_subref>;
+
+} // namespace sc_core
+
+namespace sc_dt
+{
+
+// to avoid code bloat in sc_uint_concat<T1,T2>
+
+void
+sc_uint_concref_invalid_length(int length)
+{
+ std::stringstream msg;
+ msg << "sc_uint_concref<T1,T2> initialization: length = " << length <<
+ "violates 1 <= length <= " << SC_INTWIDTH;
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_uint_bitref
+//
+// Proxy class for sc_uint bit selection (r-value and l-value).
+// ----------------------------------------------------------------------------
+
+sc_core::sc_vpool<sc_uint_bitref> sc_uint_bitref::m_pool(9);
+
+// concatenation methods:
+
+// #### OPTIMIZE
+void
+sc_uint_bitref::concat_set(int64 src, int low_i)
+{
+ sc_uint_base aa(1);
+ *this = aa = (low_i < 64) ? src >> low_i : src >> 63;
+}
+
+void
+sc_uint_bitref::concat_set(const sc_signed &src, int low_i)
+{
+ sc_uint_base aa(1);
+ if (low_i < src.length())
+ *this = aa = 1 & (src >> low_i);
+ else
+ *this = aa = (src < 0) ? (int_type)-1 : 0;
+}
+
+void
+sc_uint_bitref::concat_set(const sc_unsigned &src, int low_i)
+{
+ sc_uint_base aa(1);
+ if (low_i < src.length())
+ *this = aa = 1 & (src >> low_i);
+ else
+ *this = aa = 0;
+}
+
+void
+sc_uint_bitref::concat_set(uint64 src, int low_i)
+{
+ sc_uint_base aa(1);
+ *this = aa = (low_i < 64) ? src >> low_i : 0;
+}
+
+
+// other methods
+void
+sc_uint_bitref::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_uint_subref_r
+//
+// Proxy class for sc_uint part selection (l-value).
+// ----------------------------------------------------------------------------
+
+bool
+sc_uint_subref_r::concat_get_ctrl(sc_digit *dst_p, int low_i) const
+{
+ int dst_i; // Word in dst_p now processing.
+ int end_i; // Highest order word in dst_p to process.
+ int left_shift; // Left shift for val.
+ uint_type mask; // Mask for bits to extract or keep.
+
+ dst_i = low_i / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+ end_i = (low_i + (m_left-m_right)) / BITS_PER_DIGIT;
+
+ mask = ~(~UINT_ZERO << left_shift);
+ dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask));
+
+ dst_i++;
+ for (; dst_i <= end_i; dst_i++)
+ dst_p[dst_i] = 0;
+
+ return false;
+}
+
+bool
+sc_uint_subref_r::concat_get_data(sc_digit *dst_p, int low_i) const
+{
+ int dst_i; // Word in dst_p now processing.
+ int end_i; // Highest order word in dst_p to process.
+ int high_i; // Index of high order bit in dst_p to set.
+ int left_shift; // Left shift for val.
+ uint_type mask; // Mask for bits to extract or keep.
+ bool result; // True if inserting non-zero value.
+ uint_type val; // Selection value extracted from m_obj_p.
+
+ dst_i = low_i / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+ high_i = low_i + (m_left-m_right);
+ end_i = high_i / BITS_PER_DIGIT;
+ mask = ~mask_int[m_left][m_right];
+ val = (m_obj_p->m_val & mask) >> m_right;
+ result = val != 0;
+
+ // PROCESS THE FIRST WORD:
+ mask = ~(~UINT_ZERO << left_shift);
+ dst_p[dst_i] = (sc_digit)(((dst_p[dst_i] & mask)) |
+ ((val << left_shift) & DIGIT_MASK));
+
+ switch (end_i - dst_i) {
+ // BITS ARE ACROSS TWO WORDS:
+ case 1:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT-left_shift);
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+
+ // BITS ARE ACROSS THREE WORDS:
+ case 2:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT-left_shift);
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+
+ // BITS ARE ACROSS THREE WORDS:
+ case 3:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT-left_shift);
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+ }
+ return result;
+}
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_uint_subref
+//
+// Proxy class for sc_uint part selection (r-value and l-value).
+// ----------------------------------------------------------------------------
+
+sc_core::sc_vpool<sc_uint_subref> sc_uint_subref::m_pool(9);
+
+// assignment operators
+
+sc_uint_subref &
+sc_uint_subref::operator = (uint_type v)
+{
+ uint_type val = m_obj_p->m_val;
+ uint_type mask = mask_int[m_left][m_right];
+ val &= mask;
+ val |= (v << m_right) & ~mask;
+ m_obj_p->m_val = val;
+ m_obj_p->extend_sign();
+ return *this;
+}
+
+sc_uint_subref &
+sc_uint_subref::operator = (const sc_signed &a)
+{
+ sc_uint_base aa(length());
+ return (*this = aa = a);
+}
+
+sc_uint_subref &
+sc_uint_subref::operator = (const sc_unsigned &a)
+{
+ sc_uint_base aa(length());
+ return (*this = aa = a);
+}
+
+sc_uint_subref &
+sc_uint_subref::operator = (const sc_bv_base &a)
+{
+ sc_uint_base aa(length());
+ return (*this = aa = a);
+}
+
+sc_uint_subref &
+sc_uint_subref::operator = (const sc_lv_base &a)
+{
+ sc_uint_base aa(length());
+ return (*this = aa = a);
+}
+
+// concatenation methods:
+
+// #### OPTIMIZE
+void
+sc_uint_subref::concat_set(int64 src, int low_i)
+{
+ sc_uint_base aa(length());
+ *this = aa = (low_i < 64) ? src >> low_i : src >> 63;
+}
+
+void
+sc_uint_subref::concat_set(const sc_signed &src, int low_i)
+{
+ sc_uint_base aa(length());
+ if (low_i < src.length())
+ *this = aa = src >> low_i;
+ else
+ *this = aa = (src < 0) ? (int_type)-1 : 0;
+}
+
+void
+sc_uint_subref::concat_set(const sc_unsigned &src, int low_i)
+{
+ sc_uint_base aa(length());
+ if (low_i < src.length())
+ *this = aa = src >> low_i;
+ else
+ *this = aa = 0;
+}
+
+void
+sc_uint_subref::concat_set(uint64 src, int low_i)
+{
+ sc_uint_base aa(length());
+ *this = aa = (low_i < 64) ? src >> low_i : 0;
+}
+
+// other methods
+void
+sc_uint_subref::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_uint_base
+//
+// Base class for sc_uint.
+// ----------------------------------------------------------------------------
+
+// support methods
+
+void
+sc_uint_base::invalid_length() const
+{
+ std::stringstream msg;
+ msg << "sc_uint[_base] initialization: length = " << m_len <<
+ " violates 1 <= length <= " << SC_INTWIDTH;
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here}
+}
+
+void
+sc_uint_base::invalid_index(int i) const
+{
+ std::stringstream msg;
+ msg << "sc_uint[_base] bit selection: index = " << i <<
+ " violates 0 <= index <= " << (m_len - 1);
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+void
+sc_uint_base::invalid_range(int l, int r) const
+{
+ std::stringstream msg;
+ msg << "sc_uint[_base] part selection: " <<
+ "left = " << l << ", right = " << r << " violates " <<
+ (m_len - 1) << " >= left >= right >= 0";
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+
+void
+sc_uint_base::check_value() const
+{
+ uint_type limit = (~UINT_ZERO >> m_ulen);
+ if (m_val > limit) {
+ std::stringstream msg;
+ msg << "sc_uint[_base]: value does not fit into a length of " << m_len;
+ SC_REPORT_WARNING("out of bounds", msg.str().c_str());
+ }
+}
+
+
+// constructors
+sc_uint_base::sc_uint_base(const sc_bv_base &v) :
+ m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = v;
+}
+sc_uint_base::sc_uint_base(const sc_lv_base &v) :
+ m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = v;
+}
+sc_uint_base::sc_uint_base(const sc_int_subref_r &v) :
+ m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = v.to_uint64();
+}
+sc_uint_base::sc_uint_base(const sc_signed_subref_r &v) :
+ m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = v.to_uint64();
+}
+sc_uint_base::sc_uint_base(const sc_unsigned_subref_r &v) :
+ m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = v.to_uint64();
+}
+
+sc_uint_base::sc_uint_base(const sc_signed &a) :
+ m_val(0), m_len(a.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = a.to_uint64();
+}
+
+sc_uint_base::sc_uint_base(const sc_unsigned &a) :
+ m_val(0), m_len(a.length()), m_ulen(SC_INTWIDTH - m_len)
+{
+ check_length();
+ *this = a.to_uint64();
+}
+
+// assignment operators
+
+sc_uint_base &
+sc_uint_base::operator = (const sc_signed &a)
+{
+ int minlen = sc_min(m_len, a.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ set(i, a.test(i));
+ }
+ bool sgn = a.sign();
+ for (; i < m_len; ++i) {
+ // sign extension
+ set(i, sgn);
+ }
+ extend_sign();
+ return *this;
+}
+
+sc_uint_base &
+sc_uint_base::operator = (const sc_unsigned &a)
+{
+ int minlen = sc_min(m_len, a.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ set(i, a.test(i));
+ }
+ for (; i < m_len; ++i) {
+ // zero extension
+ set(i, 0);
+ }
+ extend_sign();
+ return *this;
+}
+
+
+sc_uint_base &
+sc_uint_base::operator = (const sc_bv_base &a)
+{
+ int minlen = sc_min(m_len, a.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ set(i, a.get_bit(i));
+ }
+ for (; i < m_len; ++i) {
+ // zero extension
+ set(i, 0);
+ }
+ extend_sign();
+ return *this;
+}
+
+sc_uint_base &
+sc_uint_base::operator = (const sc_lv_base &a)
+{
+ int minlen = sc_min(m_len, a.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ set(i, sc_logic(a.get_bit(i)).to_bool());
+ }
+ for (; i < m_len; ++i) {
+ // zero extension
+ set(i, 0);
+ }
+ extend_sign();
+ return *this;
+}
+
+sc_uint_base &
+sc_uint_base::operator = (const char *a)
+{
+ if (a == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is zero");
+ } else if (*a == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is empty");
+ } else try {
+ int len = m_len;
+ sc_ufix aa(a, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return this->operator = (aa);
+ } catch(const sc_core::sc_report &) {
+ std::stringstream msg;
+ msg << "character string '" << a << "' is not valid";
+ SC_REPORT_ERROR("conversion failed", msg.str().c_str());
+ }
+ return *this;
+}
+
+
+// explicit conversion to character string
+const std::string
+sc_uint_base::to_string(sc_numrep numrep) const
+{
+ int len = m_len;
+ sc_ufix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return aa.to_string(numrep);
+}
+
+const std::string
+sc_uint_base::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ int len = m_len;
+ sc_ufix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return aa.to_string(numrep, w_prefix);
+}
+
+
+// reduce methods
+bool
+sc_uint_base::and_reduce() const
+{
+ return (m_val == (~UINT_ZERO >> m_ulen));
+}
+
+bool
+sc_uint_base::or_reduce() const
+{
+ return (m_val != uint_type(0));
+}
+
+bool
+sc_uint_base::xor_reduce() const
+{
+ uint_type mask = ~UINT_ZERO;
+ uint_type val = m_val;
+ int n = SC_INTWIDTH;
+ do {
+ n >>= 1;
+ mask >>= n;
+ val = ((val & (mask << n)) >> n) ^ (val & mask);
+ } while (n != 1);
+ return (val != uint_type(0));
+}
+
+
+bool
+sc_uint_base::concat_get_ctrl(sc_digit *dst_p, int low_i) const
+{
+ int dst_i; // Word in dst_p now processing.
+ int end_i; // Highest order word in dst_p to process.
+ int left_shift; // Left shift for val.
+ uint_type mask; // Mask for bits to extract or keep.
+
+ dst_i = low_i / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+ end_i = (low_i + (m_len - 1)) / BITS_PER_DIGIT;
+
+ // PROCESS THE FIRST WORD:
+ mask = ~(~UINT_ZERO << left_shift);
+ dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask));
+
+ dst_i++;
+ for (; dst_i <= end_i; dst_i++)
+ dst_p[dst_i] = 0;
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+//"sc_uint_base::concat_get_data"
+//
+// This method transfers the value of this object instance to the supplied
+// array of sc_unsigned digits starting with the bit specified by low_i within
+// the array of digits.
+//
+// Notes:
+// (1) we don't worry about masking the high order data we transfer since
+// concat_get_data() is called from low order bit to high order bit. So
+// the bits above where we place ours will be filled in by someone else.
+//
+// dst_p -> array of sc_unsigned digits to be filled in.
+// low_i = first bit within dst_p to be set.
+//-----------------------------------------------------------------------------
+bool
+sc_uint_base::concat_get_data(sc_digit *dst_p, int low_i) const
+{
+ int dst_i; // Word in dst_p now processing.
+ int end_i; // Highest order word in dst_p to process.
+ int high_i; // Index of high order bit in dst_p to set.
+ int left_shift; // Left shift for val.
+ uint_type mask; // Mask for bits to extract or keep.
+ bool result; // True if inserting non-zero value.
+ uint_type val; // Value for this object.
+
+ dst_i = low_i / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+ high_i = low_i + (m_len - 1);
+ end_i = high_i / BITS_PER_DIGIT;
+ val = m_val;
+ result = val != 0;
+
+ // MASK OFF DATA TO BE TRANSFERRED BASE ON WIDTH:
+ if (m_len < 64) {
+ mask = ~(~UINT_ZERO << m_len);
+ val &= mask;
+ }
+
+ // PROCESS THE FIRST WORD:
+ mask = ~(~UINT_ZERO << left_shift);
+ dst_p[dst_i] = (sc_digit)(((dst_p[dst_i] & mask)) |
+ ((val << left_shift) & DIGIT_MASK));
+
+ switch (end_i - dst_i) {
+ // BITS ARE ACROSS TWO WORDS:
+ case 1:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT - left_shift);
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+
+ // BITS ARE ACROSS THREE WORDS:
+ case 2:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT - left_shift);
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+
+ // BITS ARE ACROSS FOUR WORDS:
+ case 3:
+ dst_i++;
+ val >>= (BITS_PER_DIGIT - left_shift);
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
+ val >>= BITS_PER_DIGIT;
+ dst_p[dst_i] = (sc_digit)val;
+ break;
+ }
+ return result;
+}
+
+// #### OPTIMIZE
+void
+sc_uint_base::concat_set(int64 src, int low_i)
+{
+ *this = (low_i < 64) ? src >> low_i : src >> 63;
+}
+
+void
+sc_uint_base::concat_set(const sc_signed &src, int low_i)
+{
+ if (low_i < src.length())
+ *this = src >> low_i;
+ else
+ *this = (src < 0) ? (int_type)-1 : 0;
+}
+
+void
+sc_uint_base::concat_set(const sc_unsigned &src, int low_i)
+{
+ if (low_i < src.length())
+ *this = src >> low_i;
+ else
+ *this = 0;
+}
+
+void
+sc_uint_base::concat_set(uint64 src, int low_i)
+{
+ *this = (low_i < 64) ? src >> low_i : 0;
+}
+
+
+// other methods
+void
+sc_uint_base::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_unsigned.cpp -- Arbitrary precision signed arithmetic.
+
+ This file includes the definitions of sc_unsigned_bitref,
+ sc_unsigned_subref, and sc_unsigned classes. The first two classes
+ are proxy classes to reference one bit and a range of bits of a
+ sc_unsigned number, respectively. This file also includes
+ sc_nbcommon.cpp and sc_nbfriends.cpp, which contain the
+ definitions shared by sc_unsigned.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_unsigned.cpp,v $
+// Revision 1.7 2011/02/18 20:19:15 acg
+// Andy Goodrich: updating Copyright notice.
+//
+// Revision 1.6 2008/12/10 20:38:45 acg
+// Andy Goodrich: fixed conversion of double values to the digits vector.
+// The bits above the radix were not being masked off.
+//
+// Revision 1.5 2008/06/19 17:47:57 acg
+// Andy Goodrich: fixes for bugs. See 2.2.1 RELEASENOTES.
+//
+// Revision 1.4 2008/06/19 16:57:57 acg
+// Andy Goodrich: added case for negative unsigned values to the support in
+// concate_get_data().
+//
+// Revision 1.3 2007/11/04 21:27:00 acg
+// Andy Goodrich: changes to make sure the proper value is returned from
+// concat_get_data().
+//
+// Revision 1.2 2007/02/22 21:35:05 acg
+// Andy Goodrich: cleaned up comments in concat_get_ctrl and concat_get_data.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.4 2006/08/29 23:36:54 acg
+// Andy Goodrich: fixed and_reduce and optimized or_reduce.
+//
+// Revision 1.3 2006/01/13 18:49:32 acg
+// Added $Log command so that CVS check in comments are reproduced in the
+// source.
+//
+
+#include <cctype>
+#include <cmath>
+#include <sstream>
+
+#include "systemc/ext/dt/bit/sc_bv_base.hh"
+#include "systemc/ext/dt/bit/sc_lv_base.hh"
+#include "systemc/ext/dt/fx/sc_ufix.hh"
+#include "systemc/ext/dt/fx/scfx_other_defs.hh"
+#include "systemc/ext/dt/int/sc_int_base.hh"
+#include "systemc/ext/dt/int/sc_signed.hh"
+#include "systemc/ext/dt/int/sc_uint_base.hh"
+#include "systemc/ext/dt/int/sc_unsigned.hh"
+#include "systemc/ext/dt/misc/sc_concatref.hh"
+
+// explicit template instantiations
+namespace sc_core
+{
+
+template class sc_vpool<sc_dt::sc_unsigned_bitref>;
+template class sc_vpool<sc_dt::sc_unsigned_subref>;
+template class sc_vpool<sc_dt::sc_unsigned>;
+
+} // namespace sc_core
+
+namespace sc_dt
+{
+
+// Pool of temporary instances:
+// The sc_unsigned pool is used by the concatenation support.
+// The bit and part reference pools allow references to be returned.
+
+sc_core::sc_vpool<sc_unsigned> sc_unsigned::m_pool(8);
+sc_core::sc_vpool<sc_unsigned_bitref> sc_unsigned_bitref::m_pool(9);
+sc_core::sc_vpool<sc_unsigned_subref> sc_unsigned_subref::m_pool(9);
+
+
+void
+sc_unsigned::invalid_init(const char *type_name, int nb) const
+{
+ std::stringstream msg;
+ msg << "sc_unsigned("<< type_name << ") : nb = " << nb << " is not valid";
+ SC_REPORT_ERROR("initialization failed", msg.str().c_str());
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Invalid selections.
+// ----------------------------------------------------------------------------
+
+void
+sc_unsigned::invalid_index(int i) const
+{
+ std::stringstream msg;
+ msg << "sc_biguint bit selection: index = " << i << " violates "
+ "0 <= index <= " << (nbits-2);
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+void
+sc_unsigned::invalid_range(int l, int r) const
+{
+ std::stringstream msg;
+ msg << "sc_biguint part selection: left = " <<
+ l << ", right = " << r << "\n"
+ " violates either (" << (nbits - 2) << " >= left >= 0) or "
+ "(" << (nbits-2) << " >= right >= 0)";
+ SC_REPORT_ERROR("out of bounds", msg.str().c_str());
+ sc_core::sc_abort(); // can't recover from here
+}
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Concatenation support.
+// ----------------------------------------------------------------------------
+
+// Most public members are included from sc_nbcommon.inc. However, some
+// concatenation support appears here to optimize between the signed and
+// unsigned cases.
+
+
+
+// Insert this object's value at the specified place in a vector of big style
+// values.
+
+bool
+sc_unsigned::concat_get_ctrl(sc_digit *dst_p, int low_i) const
+{
+ int dst_i; // Index to next word to set in dst_p.
+ int end_i; // Index of high order word to set.
+ int left_shift; // Amount to shift value left.
+ sc_digit mask; // Mask for partial word sets.
+
+
+ // CALCULATE METRICS FOR DATA MOVEMENT:
+ dst_i = low_i / BITS_PER_DIGIT;
+ end_i = (low_i + nbits - 2) / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+
+ // MOVE FIRST WORD (IT MAY BE PARTIAL) AND THEN ANY OTHERS:
+ //
+ // We may "clobber" upper bits, but they will be written at some point
+ // anyway.
+
+ mask = ~(~0U << left_shift);
+ dst_p[dst_i] = (dst_p[dst_i] & ~mask);
+ dst_i++;
+
+ for (; dst_i <= end_i; dst_i++)
+ dst_p[dst_i] = 0;
+
+ return false;
+}
+
+bool
+sc_unsigned::concat_get_data(sc_digit *dst_p, int low_i) const
+{
+ sc_digit carry; // Carry for negating value.
+ int dst_i; // Index to next word to set in dst_p.
+ int end_i; // Index of high order word to set.
+ int high_i; // Index w/in word of high order bit.
+ int left_shift; // Amount to shift value left.
+ sc_digit left_word; // High word component for set.
+ sc_digit mask; // Mask for partial word sets.
+ bool result; // True if inserting non-zero data.
+ int right_shift; // Amount to shift value right.
+ sc_digit right_word; // Low word component for set.
+ int real_bits; // nbits - 1.
+ int src_i; // Index to next word to get from digit.
+
+ // CALCULATE METRICS FOR DATA MOVEMENT:
+ real_bits = nbits - 1; // Remove that extra sign bit.
+ dst_i = low_i / BITS_PER_DIGIT;
+ high_i = low_i + real_bits - 1;
+ end_i = high_i / BITS_PER_DIGIT;
+ left_shift = low_i % BITS_PER_DIGIT;
+
+ switch (sgn) {
+ // POSITIVE SOURCE VALUE:
+ case SC_POS:
+ result = true;
+
+ // ALL DATA TO BE MOVED IS IN A SINGLE WORD:
+ if (dst_i == end_i) {
+ mask = ~(~0U << left_shift);
+ dst_p[dst_i] = ((dst_p[dst_i] & mask) |
+ (digit[0] << left_shift)) & DIGIT_MASK;
+
+ // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED:
+ } else if (left_shift == 0) {
+ for (src_i = 0; dst_i < end_i; dst_i++, src_i++) {
+ dst_p[dst_i] = digit[src_i];
+ }
+ high_i = high_i % BITS_PER_DIGIT;
+ mask = ~(~1U << high_i) & DIGIT_MASK;
+ dst_p[dst_i] = digit[src_i] & mask;
+
+ // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED:
+ } else {
+ high_i = high_i % BITS_PER_DIGIT;
+ right_shift = BITS_PER_DIGIT - left_shift;
+ mask = ~(~0U << left_shift);
+ right_word = digit[0];
+ dst_p[dst_i] = (dst_p[dst_i] & mask) |
+ ((right_word << left_shift) & DIGIT_MASK);
+ for (src_i = 1, dst_i++; dst_i < end_i; dst_i++, src_i++) {
+ left_word = digit[src_i];
+ dst_p[dst_i] = ((left_word << left_shift) & DIGIT_MASK) |
+ (right_word >> right_shift);
+ right_word = left_word;
+ }
+ left_word = (src_i < ndigits) ? digit[src_i] : 0;
+ mask = ~(~1U << high_i) & DIGIT_MASK;
+ dst_p[dst_i] = ((left_word << left_shift) |
+ (right_word >> right_shift)) & mask;
+ }
+ break;
+
+ // SOURCE VALUE IS NEGATIVE:
+ case SC_NEG:
+ // ALL DATA TO BE MOVED IS IN A SINGLE WORD:
+ result = true;
+ if (dst_i == end_i) {
+ mask = ~(~0U << nbits);
+ right_word = ((digit[0] ^ DIGIT_MASK) + 1) & mask;
+ mask = ~(~0U << left_shift);
+ dst_p[dst_i] = ((dst_p[dst_i] & mask) |
+ (right_word << left_shift)) & DIGIT_MASK;
+
+ // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED:
+
+ } else if (left_shift == 0) {
+ carry = 1;
+ for (src_i = 0; dst_i < end_i; dst_i++, src_i++) {
+ right_word = (digit[src_i] ^ DIGIT_MASK) + carry;
+ dst_p[dst_i] = right_word & DIGIT_MASK;
+ carry = right_word >> BITS_PER_DIGIT;
+ }
+ high_i = high_i % BITS_PER_DIGIT;
+ mask = (~(~1U << high_i)) & DIGIT_MASK;
+ right_word = (src_i < ndigits) ?
+ (digit[src_i] ^ DIGIT_MASK) + carry : DIGIT_MASK + carry;
+ dst_p[dst_i] = right_word & mask;
+
+ // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED:
+ } else {
+ high_i = high_i % BITS_PER_DIGIT;
+ right_shift = BITS_PER_DIGIT - left_shift;
+ mask = ~(~0U << left_shift);
+ carry = 1;
+ right_word = (digit[0] ^ DIGIT_MASK) + carry;
+ dst_p[dst_i] = (dst_p[dst_i] & mask) |
+ ((right_word << left_shift) & DIGIT_MASK);
+ carry = right_word >> BITS_PER_DIGIT;
+ right_word &= DIGIT_MASK;
+ for (src_i = 1, dst_i++; dst_i < end_i; dst_i++, src_i++) {
+ left_word = (digit[src_i] ^ DIGIT_MASK) + carry;
+ dst_p[dst_i] = ((left_word << left_shift)&DIGIT_MASK) |
+ (right_word >> right_shift);
+ carry = left_word >> BITS_PER_DIGIT;
+ right_word = left_word & DIGIT_MASK;
+ }
+ left_word = (src_i < ndigits) ?
+ (digit[src_i] ^ DIGIT_MASK) + carry : carry;
+ mask = ~(~1U << high_i) & DIGIT_MASK;
+ dst_p[dst_i] = ((left_word << left_shift) |
+ (right_word >> right_shift)) & mask;
+ }
+ break;
+ // VALUE IS ZERO:
+ default:
+ result = false;
+ // ALL DATA TO BE MOVED IS IN A SINGLE WORD:
+ if (dst_i == end_i) {
+ mask = ~(~0U << real_bits) << left_shift;
+ dst_p[dst_i] = dst_p[dst_i] & ~mask;
+
+ // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED:
+
+ } else if (left_shift == 0) {
+ for (src_i = 0; dst_i < end_i; dst_i++, src_i++) {
+ dst_p[dst_i] = 0;
+ }
+ dst_p[dst_i] = 0;
+
+ // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED:
+ } else {
+ mask = ~(~0U << left_shift);
+ dst_p[dst_i] = (dst_p[dst_i] & mask);
+ for (dst_i++; dst_i <= end_i; dst_i++) {
+ dst_p[dst_i] = 0;
+ }
+ }
+ break;
+ }
+ return result;
+}
+
+// Return this object instance's bits as a uint64 without sign extension.
+uint64
+sc_unsigned::concat_get_uint64() const
+{
+ uint64 result;
+
+ switch (sgn) {
+ case SC_POS:
+ result = 0;
+ if (ndigits > 2)
+ result = digit[2];
+ if (ndigits > 1)
+ result = (result << BITS_PER_DIGIT) | digit[1];
+ result = (result << BITS_PER_DIGIT) | digit[0];
+ break;
+ default:
+ result = 0;
+ break;
+ }
+ return result;
+}
+
+// #### OPTIMIZE
+void
+sc_unsigned::concat_set(int64 src, int low_i)
+{
+ *this = (low_i < 64) ? src >> low_i : src >> 63;
+}
+
+void
+sc_unsigned::concat_set(const sc_signed &src, int low_i)
+{
+ if (low_i < src.length())
+ *this = src >> low_i;
+ else
+ *this = (src < 0) ? (int_type)-1 : 0;
+}
+
+void
+sc_unsigned::concat_set(const sc_unsigned &src, int low_i)
+{
+ if (low_i < src.length())
+ *this = src >> low_i;
+ else
+ *this = 0;
+}
+
+void
+sc_unsigned::concat_set(uint64 src, int low_i)
+{
+ *this = (low_i < 64) ? src >> low_i : 0;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Reduction methods.
+// ----------------------------------------------------------------------------
+
+bool
+sc_unsigned::and_reduce() const
+{
+ int i; // Digit examining.
+
+ if (sgn == SC_ZERO)
+ return false;
+ for (i = 0; i < ndigits - 1; i++)
+ if ((digit[i] & DIGIT_MASK) != DIGIT_MASK)
+ return false;
+ if ((digit[i] & ~(~0U << ((nbits - 1) % BITS_PER_DIGIT))) ==
+ static_cast<sc_digit>(~(~0U << ((nbits - 1) % BITS_PER_DIGIT)))) {
+ return true;
+ }
+ return false;
+}
+
+bool
+sc_unsigned::or_reduce() const
+{
+ return (sgn == SC_ZERO) ? false : true;
+}
+
+bool
+sc_unsigned::xor_reduce() const
+{
+ int i; // Digit examining.
+ int odd; // Flag for odd number of digits.
+
+ odd = 0;
+ for (i = 0; i < nbits - 1; i++)
+ if (test(i))
+ odd = ~odd;
+ return odd ? true : false;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Assignment operators.
+// ----------------------------------------------------------------------------
+
+// assignment operators
+const sc_unsigned &
+sc_unsigned::operator = (const char *a)
+{
+ if (a == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is zero");
+ } else if (*a == 0) {
+ SC_REPORT_ERROR("conversion failed",
+ "character string is empty");
+ } else try {
+ int len = length();
+ sc_ufix aa(a, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return this->operator = (aa);
+ } catch(const sc_core::sc_report &) {
+ std::stringstream msg;
+ msg << "character string '" << a << "' is not valid";
+ SC_REPORT_ERROR("conversion failed", msg.str().c_str());
+ }
+ return *this;
+}
+
+const sc_unsigned &
+sc_unsigned::operator = (int64 v)
+{
+ sgn = get_sign(v);
+ if (sgn == SC_ZERO) {
+ vec_zero(ndigits, digit);
+ } else {
+ from_uint(ndigits, digit, (uint64) v);
+ convert_SM_to_2C_to_SM();
+ }
+ return *this;
+}
+
+const sc_unsigned &
+sc_unsigned::operator = (uint64 v)
+{
+ if (v == 0) {
+ sgn = SC_ZERO;
+ vec_zero(ndigits, digit);
+ } else {
+ sgn = SC_POS;
+ from_uint(ndigits, digit, v);
+ convert_SM_to_2C_to_SM();
+ }
+ return *this;
+}
+
+const sc_unsigned &
+sc_unsigned::operator = (long v)
+{
+ sgn = get_sign(v);
+ if (sgn == SC_ZERO) {
+ vec_zero(ndigits, digit);
+ } else {
+ from_uint(ndigits, digit, (unsigned long)v);
+ convert_SM_to_2C_to_SM();
+ }
+ return *this;
+}
+
+const sc_unsigned &
+sc_unsigned::operator = (unsigned long v)
+{
+ if (v == 0) {
+ sgn = SC_ZERO;
+ vec_zero(ndigits, digit);
+ } else {
+ sgn = SC_POS;
+ from_uint(ndigits, digit, v);
+ convert_SM_to_2C_to_SM();
+ }
+ return *this;
+}
+
+const sc_unsigned &
+sc_unsigned::operator = (double v)
+{
+ is_bad_double(v);
+ sgn = SC_POS;
+ int i = 0;
+ while (std::floor(v) && (i < ndigits)) {
+ digit[i++] = ((sc_digit)std::floor(remainder(v, DIGIT_RADIX))) &
+ DIGIT_MASK;
+ v /= DIGIT_RADIX;
+ }
+ vec_zero(i, ndigits, digit);
+ convert_SM_to_2C_to_SM();
+ return *this;
+}
+
+
+// ----------------------------------------------------------------------------
+
+const sc_unsigned &
+sc_unsigned::operator = (const sc_bv_base &v)
+{
+ int minlen = sc_min(nbits, v.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ safe_set(i, v.get_bit(i), digit);
+ }
+ for (; i < nbits; ++i) {
+ safe_set(i, 0, digit); // zero-extend
+ }
+ convert_2C_to_SM();
+ return *this;
+}
+
+const sc_unsigned &
+sc_unsigned::operator = (const sc_lv_base &v)
+{
+ int minlen = sc_min(nbits, v.length());
+ int i = 0;
+ for (; i < minlen; ++i) {
+ safe_set(i, sc_logic(v.get_bit(i)).to_bool(), digit);
+ }
+ for (; i < nbits; ++i) {
+ safe_set(i, 0, digit); // zero-extend
+ }
+ convert_2C_to_SM();
+ return *this;
+}
+
+
+// explicit conversion to character string
+const std::string
+sc_unsigned::to_string(sc_numrep numrep) const
+{
+ int len = length();
+ sc_ufix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return aa.to_string(numrep);
+}
+
+const std::string
+sc_unsigned::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ int len = length();
+ sc_ufix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
+ return aa.to_string(numrep, w_prefix);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Interfacing with sc_int_base
+// ----------------------------------------------------------------------------
+
+const sc_unsigned &
+sc_unsigned::operator = (const sc_int_base &v)
+{
+ return operator = ((int64)v);
+}
+
+const sc_unsigned &
+sc_unsigned::operator += (const sc_int_base &v)
+{
+ return operator += ((int64)v);
+}
+
+const sc_unsigned &
+sc_unsigned::operator -= (const sc_int_base &v)
+{
+ return operator -= ((int64)v);
+}
+
+const sc_unsigned &
+sc_unsigned::operator *= (const sc_int_base &v)
+{
+ return operator *= ((int64)v);
+}
+
+const sc_unsigned &
+sc_unsigned::operator /= (const sc_int_base &v)
+{
+ return operator /= ((int64)v);
+}
+
+const sc_unsigned &
+sc_unsigned::operator %= (const sc_int_base &v)
+{
+ return operator %= ((int64)v);
+}
+
+const sc_unsigned &
+sc_unsigned::operator &= (const sc_int_base &v)
+{
+ return operator &= ((int64)v);
+}
+
+const sc_unsigned &
+sc_unsigned::operator |= (const sc_int_base &v)
+{
+ return operator |= ((int64)v);
+}
+
+const sc_unsigned &
+sc_unsigned::operator ^= (const sc_int_base &v)
+{
+ return operator ^= ((int64)v);
+}
+
+sc_unsigned
+operator << (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator << (u, (int64)v);
+}
+const sc_unsigned &
+sc_unsigned::operator <<= (const sc_int_base &v)
+{
+ return operator <<= ((int64)v);
+}
+
+sc_unsigned
+operator >> (const sc_unsigned& u, const sc_int_base& v)
+{
+ return operator >> (u, (int64)v);
+}
+const sc_unsigned &
+sc_unsigned::operator >>= (const sc_int_base& v)
+{
+ return operator >>= ((int64)v);
+}
+
+bool
+operator == (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator == (u, (int64)v);
+}
+bool
+operator == (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator == ((int64)u, v);
+}
+
+bool
+operator != (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator != (u, (int64)v);
+}
+bool
+operator != (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator != ((int64)u, v);
+}
+
+bool
+operator < (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator < (u, (int64)v);
+}
+bool
+operator < (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator < ((int64)u, v);
+}
+
+bool
+operator <= (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator <= (u, (int64)v);
+}
+bool
+operator <= (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator <= ((int64)u, v);
+}
+
+bool
+operator > (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator > (u, (int64)v);
+}
+bool
+operator > (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator > ((int64)u, v);
+}
+
+bool
+operator >= (const sc_unsigned &u, const sc_int_base &v)
+{
+ return operator >= (u, (int64)v);
+}
+bool
+operator >= (const sc_int_base &u, const sc_unsigned &v)
+{
+ return operator >= ((int64)u, v);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Interfacing with sc_uint_base
+// ----------------------------------------------------------------------------
+
+const sc_unsigned &
+sc_unsigned::operator = (const sc_uint_base &v)
+{
+ return operator = ((uint64)v);
+}
+
+sc_unsigned
+operator + (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator + (u, (uint64)v);
+}
+sc_unsigned
+operator + (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator + ((uint64)u, v);
+}
+const sc_unsigned &
+sc_unsigned::operator += (const sc_uint_base &v)
+{
+ return operator += ((uint64)v);
+}
+
+const sc_unsigned &
+sc_unsigned::operator -= (const sc_uint_base &v)
+{
+ return operator -= ((uint64)v);
+}
+
+sc_unsigned
+operator * (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator * (u, (uint64)v);
+}
+sc_unsigned
+operator * (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator * ((uint64)u, v);
+}
+const sc_unsigned &
+sc_unsigned::operator *= (const sc_uint_base &v)
+{
+ return operator *= ((uint64)v);
+}
+
+sc_unsigned
+operator / (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator / (u, (uint64)v);
+}
+sc_unsigned
+operator / (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator / ((uint64)u, v);
+}
+const sc_unsigned &
+sc_unsigned::operator /= (const sc_uint_base &v)
+{
+ return operator /= ((uint64)v);
+}
+
+sc_unsigned
+operator % (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator % (u, (uint64)v);
+}
+sc_unsigned
+operator % (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator % ((uint64)u, v);
+}
+const sc_unsigned &
+sc_unsigned::operator %= (const sc_uint_base &v)
+{
+ return operator %= ((uint64)v);
+}
+
+sc_unsigned
+operator & (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator & (u, (uint64)v);
+}
+sc_unsigned
+operator & (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator & ((uint64)u, v);
+}
+const sc_unsigned &
+sc_unsigned::operator &= (const sc_uint_base &v)
+{
+ return operator &= ((uint64)v);
+}
+
+sc_unsigned
+operator | (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator | (u, (uint64)v);
+}
+sc_unsigned
+operator | (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator | ((uint64)u, v);
+}
+const sc_unsigned &
+sc_unsigned::operator |= (const sc_uint_base &v)
+{
+ return operator |= ((uint64)v);
+}
+
+sc_unsigned
+operator ^ (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator ^ (u, (uint64)v);
+}
+sc_unsigned
+operator ^ (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator ^ ((uint64)u, v);
+}
+const sc_unsigned &
+sc_unsigned::operator ^= (const sc_uint_base &v)
+{
+ return operator ^= ((uint64)v);
+}
+
+sc_unsigned
+operator << (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator << (u, (uint64)v);
+}
+const sc_unsigned &
+sc_unsigned::operator <<= (const sc_uint_base &v)
+{
+ return operator <<= ((uint64)v);
+}
+
+sc_unsigned
+operator >> (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator >> (u, (uint64)v);
+}
+const sc_unsigned &
+sc_unsigned::operator >>= (const sc_uint_base &v)
+{
+ return operator >>= ((uint64)v);
+}
+
+bool
+operator == (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator == (u, (uint64)v);
+}
+bool
+operator == (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator == ((uint64)u, v);
+}
+
+bool
+operator != (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator != (u, (uint64)v);
+}
+bool
+operator != (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator != ((uint64)u, v);
+}
+
+bool
+operator < (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator < (u, (uint64)v);
+}
+bool
+operator < (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator < ((uint64)u, v);
+}
+
+bool
+operator <= (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator <= (u, (uint64)v);
+}
+bool
+operator <= (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator <= ((uint64)u, v);
+}
+
+bool
+operator > (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator > (u, (uint64)v);
+}
+bool
+operator > (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator > ((uint64)u, v);
+}
+
+bool
+operator >= (const sc_unsigned &u, const sc_uint_base &v)
+{
+ return operator >= (u, (uint64)v);
+}
+bool
+operator >= (const sc_uint_base &u, const sc_unsigned &v)
+{
+ return operator >= ((uint64)u, v);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Input and output operators
+// ----------------------------------------------------------------------------
+
+// The operators in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Operator macros.
+// ----------------------------------------------------------------------------
+
+#define CONVERT_LONG(u) \
+small_type u ## s = get_sign(u); \
+sc_digit u ## d[DIGITS_PER_ULONG]; \
+from_uint(DIGITS_PER_ULONG, u ## d, (unsigned long) u);
+
+#define CONVERT_LONG_2(u) \
+sc_digit u ## d[DIGITS_PER_ULONG]; \
+from_uint(DIGITS_PER_ULONG, u ## d, (unsigned long) u);
+
+#define CONVERT_INT(u) \
+small_type u ## s = get_sign(u); \
+sc_digit u ## d[DIGITS_PER_UINT]; \
+from_uint(DIGITS_PER_UINT, u ## d, (unsigned int) u);
+
+#define CONVERT_INT_2(u) \
+sc_digit u ## d[DIGITS_PER_UINT]; \
+from_uint(DIGITS_PER_UINT, u ## d, (unsigned int) u);
+
+#define CONVERT_INT64(u) \
+small_type u ## s = get_sign(u); \
+sc_digit u ## d[DIGITS_PER_UINT64]; \
+from_uint(DIGITS_PER_UINT64, u ## d, (uint64) u);
+
+#define CONVERT_INT64_2(u) \
+sc_digit u ## d[DIGITS_PER_UINT64]; \
+from_uint(DIGITS_PER_UINT64, u ## d, (uint64) u);
+
+
+// ----------------------------------------------------------------------------
+// SECTION: PLUS operators: +, +=, ++
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u + v:
+// 1. 0 + v = v
+// 2. u + 0 = u
+// 3. if sgn(u) == sgn(v)
+// 3.1 u + v = +(u + v) = sgn(u) * (u + v)
+// 3.2 (-u) + (-v) = -(u + v) = sgn(u) * (u + v)
+// 4. if sgn(u) != sgn(v)
+// 4.1 u + (-v) = u - v = sgn(u) * (u - v)
+// 4.2 (-u) + v = -(u - v) ==> sgn(u) * (u - v)
+//
+// Specialization of above cases for computing ++u or u++:
+// 1. 0 + 1 = 1
+// 3. u + 1 = u + 1 = sgn(u) * (u + 1)
+// 4. (-u) + 1 = -(u - 1) = sgn(u) * (u - 1)
+
+sc_unsigned
+operator + (const sc_unsigned &u, const sc_unsigned &v)
+{
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_unsigned(v);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_unsigned(u);
+
+ // cases 3 and 4
+ return add_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator + (const sc_unsigned &u, uint64 v)
+{
+ if (v == 0) // case 2
+ return sc_unsigned(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_unsigned(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // cases 3 and 4
+ return add_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_unsigned
+operator + (uint64 u, const sc_unsigned &v)
+{
+ if (u == 0) // case 1
+ return sc_unsigned(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // cases 3 and 4
+ return add_unsigned_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator + (const sc_unsigned &u, unsigned long v)
+{
+ if (v == 0) // case 2
+ return sc_unsigned(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 1
+ return sc_unsigned(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // cases 3 and 4
+ return add_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_unsigned
+operator + (unsigned long u, const sc_unsigned &v)
+{
+ if (u == 0) // case 1
+ return sc_unsigned(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO) // case 2
+ return sc_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // cases 3 and 4
+ return add_unsigned_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: MINUS operators: -, -=, --
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u + v:
+// 1. u - 0 = u
+// 2. 0 - v = -v
+// 3. if sgn(u) != sgn(v)
+// 3.1 u - (-v) = u + v = sgn(u) * (u + v)
+// 3.2 (-u) - v = -(u + v) ==> sgn(u) * (u + v)
+// 4. if sgn(u) == sgn(v)
+// 4.1 u - v = +(u - v) = sgn(u) * (u - v)
+// 4.2 (-u) - (-v) = -(u - v) = sgn(u) * (u - v)
+//
+// Specialization of above cases for computing --u or u--:
+// 1. 0 - 1 = -1
+// 3. (-u) - 1 = -(u + 1) = sgn(u) * (u + 1)
+// 4. u - 1 = u - 1 = sgn(u) * (u - 1)
+
+// The operators in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: MULTIPLICATION operators: *, *=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u * v:
+// 1. u * 0 = 0 * v = 0
+// 2. 1 * v = v and -1 * v = -v
+// 3. u * 1 = u and u * -1 = -u
+// 4. u * v = u * v
+
+sc_unsigned
+operator * (const sc_unsigned &u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(u.sgn, v.sgn);
+
+ if (s == SC_ZERO) // case 1
+ return sc_unsigned();
+
+ // cases 2-4
+ return mul_unsigned_friend(s, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator * (const sc_unsigned &u, uint64 v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) // case 1
+ return sc_unsigned();
+
+ CONVERT_INT64_2(v);
+
+ // cases 2-4
+ return mul_unsigned_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_unsigned
+operator * (uint64 u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) // case 1
+ return sc_unsigned();
+
+ CONVERT_INT64_2(u);
+
+ // cases 2-4
+ return mul_unsigned_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator * (const sc_unsigned &u, unsigned long v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) // case 1
+ return sc_unsigned();
+
+ CONVERT_LONG_2(v);
+
+ // else cases 2-4
+ return mul_unsigned_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+sc_unsigned
+operator * (unsigned long u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) // case 1
+ return sc_unsigned();
+
+ CONVERT_LONG_2(u);
+
+ // cases 2-4
+ return mul_unsigned_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: DIVISION operators: /, /=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when finding the quotient q = floor(u/v):
+// Note that u = q * v + r for r < q.
+// 1. 0 / 0 or u / 0 => error
+// 2. 0 / v => 0 = 0 * v + 0
+// 3. u / v & &u = v => u = 1 * u + 0 - u or v can be 1 or -1
+// 4. u / v & &u < v => u = 0 * v + u - u can be 1 or -1
+// 5. u / v & &u > v => u = q * v + r - v can be 1 or -1
+
+sc_unsigned
+operator / (const sc_unsigned &u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(u.sgn, v.sgn);
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_unsigned(); // case 2
+ }
+
+ // other cases
+ return div_unsigned_friend(s, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator / (const sc_unsigned &u, uint64 v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v); // case 1
+ return sc_unsigned(); // case 2
+ }
+
+ CONVERT_INT64_2(v);
+
+ // other cases
+ return div_unsigned_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_unsigned
+operator / (uint64 u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_unsigned(); // case 2
+
+ }
+
+ CONVERT_INT64_2(u);
+
+ // other cases
+ return div_unsigned_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator / (const sc_unsigned &u, unsigned long v)
+{
+ small_type s = mul_signs(u.sgn, get_sign(v));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v); // case 1
+ return sc_unsigned(); // case 2
+ }
+
+ CONVERT_LONG_2(v);
+
+ // other cases
+ return div_unsigned_friend(s, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_unsigned
+operator / (unsigned long u, const sc_unsigned &v)
+{
+ small_type s = mul_signs(v.sgn, get_sign(u));
+
+ if (s == SC_ZERO) {
+ div_by_zero(v.sgn); // case 1
+ return sc_unsigned(); // case 2
+
+ }
+
+ CONVERT_LONG_2(u);
+
+ // other cases
+ return div_unsigned_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: MOD operators: %, %=.
+// ----------------------------------------------------------------------------
+
+// Cases to consider when finding the remainder r = u % v:
+// Note that u = q * v + r for r < q.
+// 1. 0 % 0 or u % 0 => error
+// 2. 0 % v => 0 = 0 * v + 0
+// 3. u % v & &u = v => u = 1 * u + 0 - u or v can be 1 or -1
+// 4. u % v & &u < v => u = 0 * v + u - u can be 1 or -1
+// 5. u % v & &u > v => u = q * v + r - v can be 1 or -1
+
+sc_unsigned
+operator % (const sc_unsigned &u, const sc_unsigned &v)
+{
+ if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_unsigned(); // case 2
+ }
+
+ // other cases
+ return mod_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator % (const sc_unsigned &u, uint64 v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) {
+ div_by_zero(v); // case 1
+ return sc_unsigned(); // case 2
+ }
+
+ CONVERT_INT64_2(v);
+
+ // other cases
+ return mod_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+
+}
+
+
+sc_unsigned
+operator % (uint64 u, const sc_unsigned &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_unsigned(); // case 2
+ }
+
+ CONVERT_INT64(u);
+
+ // other cases
+ return mod_unsigned_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator % (const sc_unsigned &u, unsigned long v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) {
+ div_by_zero(v); // case 1
+ return sc_unsigned(); // case 2
+ }
+
+ CONVERT_LONG_2(v);
+
+ // other cases
+ return mod_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_unsigned
+operator % (unsigned long u, const sc_unsigned &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) {
+ div_by_zero(v.sgn); // case 1
+ return sc_unsigned(); // case 2
+ }
+
+ CONVERT_LONG(u);
+
+ // other cases
+ return mod_unsigned_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise AND operators: &, &=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u &v:
+// 1. u & 0 = 0 &v = 0
+// 2. u &v => sgn = +
+// 3. (-u) & (-v) => sgn = -
+// 4. u & (-v) => sgn = +
+// 5. (-u) &v => sgn = +
+
+sc_unsigned
+operator & (const sc_unsigned &u, const sc_unsigned &v)
+{
+ if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) // case 1
+ return sc_unsigned();
+
+ // other cases
+ return and_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator & (const sc_unsigned &u, uint64 v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) // case 1
+ return sc_unsigned();
+
+ CONVERT_INT64(v);
+
+ // other cases
+ return and_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_unsigned
+operator & (uint64 u, const sc_unsigned &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) // case 1
+ return sc_unsigned();
+
+ CONVERT_INT64(u);
+
+ // other cases
+ return and_unsigned_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator & (const sc_unsigned &u, unsigned long v)
+{
+ if ((u.sgn == SC_ZERO) || (v == 0)) // case 1
+ return sc_unsigned();
+
+ CONVERT_LONG(v);
+
+ // other cases
+ return and_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_unsigned
+operator & (unsigned long u, const sc_unsigned &v)
+{
+ if ((u == 0) || (v.sgn == SC_ZERO)) // case 1
+ return sc_unsigned();
+
+ CONVERT_LONG(u);
+
+ // other cases
+ return and_unsigned_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise OR operators: |, |=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u | v:
+// 1. u | 0 = u
+// 2. 0 | v = v
+// 3. u | v => sgn = +
+// 4. (-u) | (-v) => sgn = -
+// 5. u | (-v) => sgn = -
+// 6. (-u) | v => sgn = -
+
+sc_unsigned
+operator | (const sc_unsigned &u, const sc_unsigned &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_unsigned(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_unsigned(v);
+
+ // other cases
+ return or_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator | (const sc_unsigned &u, uint64 v)
+{
+ if (v == 0) // case 1
+ return sc_unsigned(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_unsigned(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // other cases
+ return or_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+
+sc_unsigned
+operator | (uint64 u, const sc_unsigned &v)
+{
+ if (u == 0)
+ return sc_unsigned(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // other cases
+ return or_unsigned_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator | (const sc_unsigned &u, unsigned long v)
+{
+ if (v == 0) // case 1
+ return sc_unsigned(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_unsigned(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // other cases
+ return or_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+
+sc_unsigned
+operator | (unsigned long u, const sc_unsigned &v)
+{
+ if (u == 0)
+ return sc_unsigned(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // other cases
+ return or_unsigned_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise XOR operators: ^, ^=
+// ----------------------------------------------------------------------------
+
+// Cases to consider when computing u ^ v:
+// Note that u ^ v = (~u &v) | (u & ~v).
+// 1. u ^ 0 = u
+// 2. 0 ^ v = v
+// 3. u ^ v => sgn = +
+// 4. (-u) ^ (-v) => sgn = -
+// 5. u ^ (-v) => sgn = -
+// 6. (-u) ^ v => sgn = +
+
+sc_unsigned
+operator ^ (const sc_unsigned &u, const sc_unsigned &v)
+{
+ if (v.sgn == SC_ZERO) // case 1
+ return sc_unsigned(u);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_unsigned(v);
+
+ // other cases
+ return xor_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator ^ (const sc_unsigned &u, uint64 v)
+{
+ if (v == 0) // case 1
+ return sc_unsigned(u);
+
+ CONVERT_INT64(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_unsigned(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false);
+
+ // other cases
+ return xor_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
+}
+
+sc_unsigned
+operator ^ (uint64 u, const sc_unsigned &v)
+{
+ if (u == 0)
+ return sc_unsigned(v);
+
+ CONVERT_INT64(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false);
+
+ // other cases
+ return xor_unsigned_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+
+sc_unsigned
+operator ^ (const sc_unsigned &u, unsigned long v)
+{
+ if (v == 0) // case 1
+ return sc_unsigned(u);
+
+ CONVERT_LONG(v);
+
+ if (u.sgn == SC_ZERO) // case 2
+ return sc_unsigned(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false);
+
+ // other cases
+ return xor_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
+}
+
+sc_unsigned
+operator ^ (unsigned long u, const sc_unsigned &v)
+{
+ if (u == 0)
+ return sc_unsigned(v);
+
+ CONVERT_LONG(u);
+
+ if (v.sgn == SC_ZERO)
+ return sc_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false);
+
+ // other cases
+ return xor_unsigned_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit);
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Bitwise NOT operator: ~
+// ----------------------------------------------------------------------------
+
+// Operators in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: LEFT SHIFT operators: <<, <<=
+// ----------------------------------------------------------------------------
+
+sc_unsigned
+operator << (const sc_unsigned &u, const sc_signed &v)
+{
+ if ((v.sgn == SC_ZERO) || (v.sgn == SC_NEG))
+ return sc_unsigned(u);
+
+ return operator << (u, v.to_ulong());
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: RIGHT SHIFT operators: >>, >>=
+// ----------------------------------------------------------------------------
+
+sc_unsigned
+operator >> (const sc_unsigned &u, const sc_signed &v)
+{
+
+ if ((v.sgn == SC_ZERO) || (v.sgn == SC_NEG))
+ return sc_unsigned(u);
+
+ return operator >> (u, v.to_long());
+
+}
+
+// The rest of the operators in this section are included from
+// sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Unary arithmetic operators.
+// ----------------------------------------------------------------------------
+
+sc_unsigned
+operator + (const sc_unsigned &u)
+{
+ return sc_unsigned(u);
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: EQUAL operator: ==
+// ----------------------------------------------------------------------------
+
+bool
+operator == (const sc_unsigned &u, const sc_unsigned &v)
+{
+ if (&u == &v)
+ return true;
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit) != 0) {
+ return false;
+ }
+ return true;
+}
+
+
+bool
+operator == (const sc_unsigned &u, const sc_signed &v)
+{
+ if (v.sgn == SC_NEG)
+ return false;
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit, 0, 1) != 0) {
+ return false;
+ }
+ return true;
+}
+
+
+bool
+operator == (const sc_signed &u, const sc_unsigned &v)
+{
+ if (u.sgn == SC_NEG)
+ return false;
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit, 1, 0) != 0) {
+ return false;
+ }
+ return true;
+}
+
+
+bool
+operator == (const sc_unsigned &u, int64 v)
+{
+ if (v < 0)
+ return false;
+ CONVERT_INT64(v);
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd) != 0) {
+ return false;
+ }
+ return true;
+}
+
+
+bool
+operator == (int64 u, const sc_unsigned &v)
+{
+ if (u < 0)
+ return false;
+ CONVERT_INT64(u);
+ if (compare_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit) != 0) {
+ return false;
+ }
+ return true;
+}
+
+
+bool
+operator == (const sc_unsigned &u, uint64 v)
+{
+ CONVERT_INT64(v);
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd) != 0)
+ return false;
+ return true;
+}
+
+
+bool
+operator == (uint64 u, const sc_unsigned &v)
+{
+ CONVERT_INT64(u);
+ if (compare_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit) != 0)
+ return false;
+ return true;
+}
+
+
+bool
+operator == (const sc_unsigned &u, long v)
+{
+ if (v < 0)
+ return false;
+ CONVERT_LONG(v);
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd) != 0)
+ return false;
+ return true;
+}
+
+
+bool
+operator == (long u, const sc_unsigned &v)
+{
+ if (u < 0)
+ return false;
+ CONVERT_LONG(u);
+ if (compare_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit) != 0)
+ return false;
+ return true;
+}
+
+
+bool
+operator == (const sc_unsigned &u, unsigned long v)
+{
+ CONVERT_LONG(v);
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd) != 0)
+ return false;
+ return true;
+}
+
+
+bool
+operator == (unsigned long u, const sc_unsigned &v)
+{
+ CONVERT_LONG(u);
+ if (compare_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit) != 0)
+ return false;
+ return true;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: NOT_EQUAL operator: !=
+// ----------------------------------------------------------------------------
+
+bool
+operator != (const sc_unsigned &u, const sc_signed &v)
+{
+ return (!operator == (u, v));
+}
+
+
+bool
+operator != (const sc_signed &u, const sc_unsigned &v)
+{
+ return (!operator == (u, v));
+}
+
+// The rest of the operators in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: LESS THAN operator: <
+// ----------------------------------------------------------------------------
+
+bool
+operator < (const sc_unsigned &u, const sc_unsigned &v)
+{
+ if (&u == &v)
+ return false;
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit) < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+bool
+operator < (const sc_unsigned &u, const sc_signed &v)
+{
+ if (v.sgn == SC_NEG)
+ return false;
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit, 0, 1) < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+bool
+operator < (const sc_signed &u, const sc_unsigned &v)
+{
+ if (u.sgn == SC_NEG)
+ return true;
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ v.sgn, v.nbits, v.ndigits, v.digit, 1, 0) < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+bool
+operator < (const sc_unsigned &u, int64 v)
+{
+ if (v < 0)
+ return false;
+ CONVERT_INT64(v);
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd) < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+bool
+operator < (int64 u, const sc_unsigned &v)
+{
+ if (u < 0)
+ return true;
+ CONVERT_INT64(u);
+ if (compare_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit) < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+bool
+operator < (const sc_unsigned &u, uint64 v)
+{
+ CONVERT_INT64(v);
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd) < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+bool
+operator < (uint64 u, const sc_unsigned &v)
+{
+ CONVERT_INT64(u);
+ if (compare_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit) < 0){
+ return true;
+ }
+ return false;
+}
+
+
+bool
+operator < (const sc_unsigned &u, long v)
+{
+ if (v < 0)
+ return false;
+ CONVERT_LONG(v);
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd) < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+bool
+operator < (long u, const sc_unsigned &v)
+{
+ if (u < 0)
+ return true;
+ CONVERT_LONG(u);
+ if (compare_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit) < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+bool
+operator < (const sc_unsigned &u, unsigned long v)
+{
+ CONVERT_LONG(v);
+ if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit,
+ vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd) < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+bool
+operator < (unsigned long u, const sc_unsigned &v)
+{
+ CONVERT_LONG(u);
+ if (compare_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud,
+ v.sgn, v.nbits, v.ndigits, v.digit) < 0) {
+ return true;
+ }
+ return false;
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: LESS THAN or EQUAL operator: <=
+// ----------------------------------------------------------------------------
+
+bool
+operator <= (const sc_unsigned &u, const sc_signed &v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+
+bool
+operator <= (const sc_signed &u, const sc_unsigned &v)
+{
+ return (operator < (u, v) || operator == (u, v));
+}
+
+// The rest of the operators in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: GREATER THAN operator: >
+// ----------------------------------------------------------------------------
+
+bool
+operator > (const sc_unsigned &u, const sc_signed &v)
+{
+ return (!(operator <= (u, v)));
+}
+
+
+bool
+operator > (const sc_signed &u, const sc_unsigned &v)
+{
+ return (!(operator <= (u, v)));
+}
+
+// The rest of the operators in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: GREATER THAN or EQUAL operator: >=
+// ----------------------------------------------------------------------------
+
+bool
+operator >= (const sc_unsigned &u, const sc_signed &v)
+{
+ return (!(operator < (u, v)));
+}
+
+
+bool
+operator >= (const sc_signed &u, const sc_unsigned &v)
+{
+ return (!(operator < (u, v)));
+}
+
+// The rest of the operators in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Friends
+// ----------------------------------------------------------------------------
+
+// Compare u and v as unsigned and return r
+// r = 0 if u == v
+// r < 0 if u < v
+// r > 0 if u > v
+
+int
+compare_unsigned(small_type us, int unb, int und, const sc_digit *ud,
+ small_type vs, int vnb, int vnd, const sc_digit *vd,
+ small_type if_u_signed, small_type if_v_signed)
+{
+ if (us == vs) {
+ if (us == SC_ZERO) {
+ return 0;
+ } else {
+ int cmp_res = vec_skip_and_cmp(und, ud, vnd, vd);
+ if (us == SC_POS)
+ return cmp_res;
+ else
+ return -cmp_res;
+ }
+ } else {
+ if (us == SC_ZERO)
+ return -vs;
+ if (vs == SC_ZERO)
+ return us;
+
+ int cmp_res;
+ int nd = (us == SC_NEG ? und : vnd);
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ if (us == SC_NEG) {
+ vec_copy(nd, d, ud);
+ vec_complement(nd, d);
+ trim(if_u_signed, unb, nd, d);
+ cmp_res = vec_skip_and_cmp(nd, d, vnd, vd);
+ } else {
+ vec_copy(nd, d, vd);
+ vec_complement(nd, d);
+ trim(if_v_signed, vnb, nd, d);
+ cmp_res = vec_skip_and_cmp(und, ud, nd, d);
+ }
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+
+ return cmp_res;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Public members - Other utils.
+// ----------------------------------------------------------------------------
+
+bool
+sc_unsigned::iszero() const
+{
+ if (sgn == SC_ZERO) {
+ return true;
+ } else if (sgn == SC_NEG) {
+ // A negative unsigned number can be zero, e.g., -16 in 4 bits, so
+ // check that.
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[ndigits];
+#endif
+
+ vec_copy(ndigits, d, digit);
+ vec_complement(ndigits, d);
+ trim_unsigned(nbits, ndigits, d);
+
+ bool res = check_for_zero(ndigits, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+
+ return res;
+ } else {
+ return false;
+ }
+}
+
+// The rest of the utils in this section are included from sc_nbcommon.cpp.
+
+
+// ----------------------------------------------------------------------------
+// SECTION: Private members.
+// ----------------------------------------------------------------------------
+
+// The private members in this section are included from
+// sc_nbcommon.cpp.
+
+#define CLASS_TYPE sc_unsigned
+#define CLASS_TYPE_STR "sc_unsigned"
+
+#define ADD_HELPER add_unsigned_friend
+#define SUB_HELPER sub_unsigned_friend
+#define MUL_HELPER mul_unsigned_friend
+#define DIV_HELPER div_unsigned_friend
+#define MOD_HELPER mod_unsigned_friend
+#define AND_HELPER and_unsigned_friend
+#define OR_HELPER or_unsigned_friend
+#define XOR_HELPER xor_unsigned_friend
+
+#include "sc_nbfriends.inc"
+
+#undef SC_SIGNED
+#define SC_UNSIGNED
+#define IF_SC_SIGNED 0 // 0 = sc_unsigned
+#define CLASS_TYPE_SUBREF sc_unsigned_subref_r
+#define OTHER_CLASS_TYPE sc_signed
+#define OTHER_CLASS_TYPE_SUBREF sc_signed_subref_r
+
+#define MUL_ON_HELPER mul_on_help_unsigned
+#define DIV_ON_HELPER div_on_help_unsigned
+#define MOD_ON_HELPER mod_on_help_unsigned
+
+#include "sc_nbcommon.inc"
+
+#undef MOD_ON_HELPER
+#undef DIV_ON_HELPER
+#undef MUL_ON_HELPER
+
+#undef OTHER_CLASS_TYPE_SUBREF
+#undef OTHER_CLASS_TYPE
+#undef CLASS_TYPE_SUBREF
+#undef IF_SC_SIGNED
+#undef SC_UNSIGNED
+
+#undef XOR_HELPER
+#undef OR_HELPER
+#undef AND_HELPER
+#undef MOD_HELPER
+#undef DIV_HELPER
+#undef MUL_HELPER
+#undef SUB_HELPER
+#undef ADD_HELPER
+
+#undef CLASS_TYPE
+#undef CLASS_TYPE_STR
+
+#include "sc_unsigned_bitref.inc"
+#include "sc_unsigned_subref.inc"
+
+#undef CONVERT_LONG
+#undef CONVERT_LONG_2
+#undef CONVERT_INT64
+#undef CONVERT_INT64_2
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_unsigned_bitref.h -- Proxy class that is declared in sc_unsigned.h.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_unsigned_bitref_r
+//
+// Proxy class for sc_unsigned bit selection (r-value only).
+// ----------------------------------------------------------------------------
+
+// implicit conversion to uint64
+
+sc_unsigned_bitref_r::operator uint64 () const
+{
+ return m_obj_p->test(m_index);
+}
+
+bool
+sc_unsigned_bitref_r::operator ! () const
+{
+ return (!m_obj_p->test(m_index));
+}
+
+bool
+sc_unsigned_bitref_r::operator ~ () const
+{
+ return (!m_obj_p->test(m_index));
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_unsigned_bitref
+//
+// Proxy class for sc_unsigned bit selection (r-value and l-value).
+// ----------------------------------------------------------------------------
+
+// assignment operators
+
+const sc_unsigned_bitref &
+sc_unsigned_bitref::operator = (const sc_unsigned_bitref_r &b)
+{
+ m_obj_p->set(m_index, (bool)b);
+ return *this;
+}
+
+const sc_unsigned_bitref &
+sc_unsigned_bitref::operator = (const sc_unsigned_bitref &b)
+{
+ m_obj_p->set(m_index, (bool)b);
+ return *this;
+}
+
+const sc_unsigned_bitref &
+sc_unsigned_bitref::operator = (bool b)
+{
+ m_obj_p->set(m_index, b);
+ return *this;
+}
+
+
+const sc_unsigned_bitref &
+sc_unsigned_bitref::operator &= (bool b)
+{
+ if (!b) {
+ m_obj_p->clear(m_index);
+ }
+ return *this;
+}
+
+const sc_unsigned_bitref &
+sc_unsigned_bitref::operator |= (bool b)
+{
+ if (b) {
+ m_obj_p->set(m_index);
+ }
+ return *this;
+}
+
+const sc_unsigned_bitref &
+sc_unsigned_bitref::operator ^= (bool b)
+{
+ if (b) {
+ m_obj_p->invert(m_index);
+ }
+ return *this;
+}
+
+// #### OPTIMIZE
+void
+sc_unsigned_bitref::concat_set(int64 src, int low_i)
+{
+ bool value = 1 & ((low_i < 64) ? (src >> low_i) : (src >> 63));
+ m_obj_p->set(low_i, value);
+}
+
+void
+sc_unsigned_bitref::concat_set(const sc_signed &src, int low_i)
+{
+ if (low_i < src.length())
+ m_obj_p->set(low_i, src.test(low_i));
+ else
+ m_obj_p->set(low_i, src < 0);
+}
+
+void
+sc_unsigned_bitref::concat_set(const sc_unsigned &src, int low_i)
+{
+ if (low_i < src.nbits)
+ m_obj_p->set(low_i, src.test(low_i));
+ else
+ m_obj_p->set(low_i, 0);
+}
+
+void
+sc_unsigned_bitref::concat_set(uint64 src, int low_i)
+{
+ bool value = ((low_i < 64) ? (src >> low_i) & 1 : 0);
+ m_obj_p->set(low_i, value);
+}
+
+// other methods
+void
+sc_unsigned_bitref::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_unsigned_subref.h -- Proxy class that is declared in sc_unsigned.h.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_unsigned_subref_r
+//
+// Proxy class for sc_unsigned part selection (r-value only).
+// ----------------------------------------------------------------------------
+
+// concatenation support
+
+uint64
+sc_unsigned_subref_r::concat_get_uint64() const // #### Speed up!
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_uint64();
+}
+
+
+bool
+sc_unsigned_subref_r::concat_get_ctrl(sc_digit *dst_p, int low_i) const
+// #### Speed up!
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.concat_get_ctrl(dst_p, low_i);
+}
+
+bool
+sc_unsigned_subref_r::concat_get_data(sc_digit *dst_p, int low_i) const
+// #### Speed up!
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.concat_get_data(dst_p, low_i);
+}
+
+// implicit conversion to sc_unsigned
+sc_unsigned_subref_r::operator sc_unsigned () const
+{
+ return sc_unsigned(m_obj_p, m_left, m_right);
+}
+
+
+// explicit conversions
+int
+sc_unsigned_subref_r::to_int() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_int();
+}
+
+unsigned int
+sc_unsigned_subref_r::to_uint() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_uint();
+}
+
+long
+sc_unsigned_subref_r::to_long() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_long();
+}
+
+unsigned long
+sc_unsigned_subref_r::to_ulong() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_ulong();
+}
+
+int64
+sc_unsigned_subref_r::to_int64() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_int64();
+}
+
+uint64
+sc_unsigned_subref_r::to_uint64() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_uint64();
+}
+
+double
+sc_unsigned_subref_r::to_double() const
+{
+ sc_unsigned a(m_obj_p, m_left, m_right);
+ return a.to_double();
+}
+
+
+// explicit conversion to character string
+const std::string
+sc_unsigned_subref_r::to_string(sc_numrep numrep) const
+{
+ sc_unsigned a(length());
+ a = *this;
+ return a.to_string(numrep);
+}
+
+const std::string
+sc_unsigned_subref_r::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ sc_unsigned a(length());
+ a = *this;
+ return a.to_string(numrep, w_prefix);
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_unsigned_subref
+//
+// Proxy class for sc_unsigned part selection (r-value and l-value).
+// ----------------------------------------------------------------------------
+
+// assignment operators
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (const sc_unsigned_subref_r &a)
+{
+ return operator = ((sc_unsigned)(a));
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (const sc_unsigned_subref &a)
+{
+ if (this == &a) {
+ return *this;
+ }
+ return operator = ((sc_unsigned)(a));
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (const sc_unsigned &v)
+{
+ int i;
+ int l = sc_min(m_left, v.nbits - 1 + m_right);
+
+ for (i = m_right; i <= l; ++i)
+ m_obj_p->set(i, v.test(i - m_right));
+ for (; i <= m_left; i++)
+ m_obj_p->set(i, v.test(l));
+ return *this;
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (const sc_signed_subref_r &v)
+{
+ return operator = ((sc_unsigned)(v));
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (const sc_signed &v)
+{
+ int i;
+ int l = sc_min(m_left, v.nbits - 1 + m_right);
+
+ for (i = m_right; i <= l; ++i)
+ m_obj_p->set(i, v.test(i - m_right));
+ for (; i <= m_left; i++)
+ m_obj_p->set(i, 0);
+ return *this;
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (unsigned long v)
+{
+ for (int i = m_right; i <= m_left; ++i) {
+ m_obj_p->set(i, static_cast<bool>(v & 1));
+ v >>= 1;
+ }
+ return *this;
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (long v)
+{
+ unsigned long v2 = (unsigned long)v;
+ for (int i = m_right; i <= m_left; ++i) {
+ m_obj_p->set(i, static_cast<bool>(v2 & 1));
+ v2 >>= 1;
+ }
+ return *this;
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (uint64 v)
+{
+ for (int i = m_right; i <= m_left; ++i) {
+ m_obj_p->set(i, static_cast<bool>(v & 1));
+ v >>= 1;
+ }
+ return *this;
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (int64 v)
+{
+ uint64 v2 = (uint64)v;
+ for (int i = m_right; i <= m_left; ++i) {
+ m_obj_p->set(i, static_cast<bool>(v2 & 1));
+ v2 >>= 1;
+ }
+ return *this;
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (double v)
+{
+ is_bad_double(v);
+
+ int nb = m_left - m_right + 1;
+ int nd = DIV_CEIL(nb);
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ if (v < 0)
+ v = -v;
+
+ int i = 0;
+ while (std::floor(v) && (i < nd)) {
+ d[i++] = (sc_digit) std::floor(remainder(v, DIGIT_RADIX));
+ v /= DIGIT_RADIX;
+ }
+ vec_zero(i, nd, d);
+
+ sc_digit val = 1; // Bit value.
+ int j = 0; // Current digit in d.
+
+ i = 0; // Current bit in d.
+ while (i < nb) {
+ m_obj_p->set(i + m_right, (bool)(d[j] & val));
+ ++i;
+ if (i % BITS_PER_DIGIT == 0) {
+ val = 1;
+ ++j;
+ } else {
+ val <<= 1;
+ }
+ }
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ return *this;
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (const sc_int_base &a)
+{
+ return operator = ((int64)a);
+}
+
+const sc_unsigned_subref &
+sc_unsigned_subref::operator = (const sc_uint_base &a)
+{
+ return operator = ((uint64)a);
+}
+
+// concatenation methods
+void
+sc_unsigned_subref::concat_set(int64 src, int low_i)
+{
+ int i;
+ int l;
+ bool sign = src < 0;
+
+ if (low_i < 64) {
+ src = src >> low_i;
+ l = sc_min(m_left, (63 - low_i) + m_right);
+ for (i = m_right; i <= l; ++i) {
+ m_obj_p->set(i, src & 1);
+ src = src >> 1;
+ }
+ for (; i <= m_left; i++)
+ m_obj_p->set(sign);
+ } else {
+ for (i = m_right; i <= m_left; ++i)
+ m_obj_p->set(sign);
+ }
+}
+
+void
+sc_unsigned_subref::concat_set(const sc_signed &src, int low_i)
+{
+ int i;
+ int l;
+ int src_i;
+ bool sign = src.test(src.nbits - 1);
+ l = src.nbits - (low_i + 1);
+ if (l >= 0) {
+ src_i = low_i;
+ l = sc_min(m_left, l + m_right);
+ for (i = m_right; i <= l; ++i, src_i++) {
+ m_obj_p->set(i, src.test(src_i));
+ }
+ for (; i <= m_left; i++)
+ m_obj_p->set(i, sign);
+ } else {
+ for (i = m_right; i <= m_left; ++i)
+ m_obj_p->set(i, sign);
+ }
+}
+
+void
+sc_unsigned_subref::concat_set(const sc_unsigned &src, int low_i)
+{
+ int i;
+ int l;
+ int src_i;
+ l = src.nbits - (low_i + 2);
+ if (l >= 0) {
+ src_i = low_i;
+ l = sc_min(m_left, l + m_right);
+ for (i = m_right; i <= l; ++i, src_i++) {
+ m_obj_p->set(i, src.test(src_i));
+ }
+ for (; i <= m_left; i++)
+ m_obj_p->set(i, false);
+ } else {
+ for (i = m_right; i <= m_left; ++i)
+ m_obj_p->set(i, false);
+ }
+}
+
+void
+sc_unsigned_subref::concat_set(uint64 src, int low_i)
+{
+ int i;
+ int l;
+
+ if (low_i < 64) {
+ src = src >> low_i;
+ l = sc_min(m_left, (63 - low_i) + m_right);
+ for (i = m_right; i <= l; ++i) {
+ m_obj_p->set(i, src & 1);
+ src = src >> 1;
+ }
+ for (; i <= m_left; i++)
+ m_obj_p->set(false);
+ } else {
+ for (i = m_right; i <= m_left; ++i)
+ m_obj_p->set(false);
+ }
+}
+
+// other methods
+void
+sc_unsigned_subref::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
--- /dev/null
+# Copyright 2018 Google, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+Import('*')
+
+if env['USE_SYSTEMC']:
+ Source('sc_concatref.cc')
+ Source('sc_value_base.cc')
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_concatref.cpp -- Concatenation support.
+
+ Original Author: Andy Goodrich, Forte Design Systems, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+// $Log: sc_concatref.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:54:01 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/misc/sc_concatref.hh"
+#include "systemc/ext/dt/sc_temporary.hh"
+
+// STORAGE POOLS USED BY sc_concatref:
+namespace sc_core
+{
+
+template class sc_vpool<sc_dt::sc_concatref>;
+template class sc_vpool<sc_dt::sc_concat_bool>;
+sc_byte_heap sc_temp_heap(0x300000);
+
+} // namespace sc_core
+
+namespace sc_dt
+{
+
+sc_core::sc_vpool<sc_concat_bool> sc_concat_bool::m_pool(9);
+sc_core::sc_vpool<sc_concatref> sc_concatref::m_pool(9);
+
+} // namespace sc_dt
--- /dev/null
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_value_base.cpp -- Base class for all SystemC data values.
+
+ Original Author: Andy Goodrich, Forte Design Systems
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_value_base.cpp,v $
+// Revision 1.2 2011/08/15 16:43:24 acg
+// Torsten Maehne: changes to remove unused argument warnings.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:54:01 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+
+#include "systemc/ext/dt/misc/sc_value_base.hh"
+#include "systemc/ext/utils/sc_report_handler.hh"
+
+namespace sc_dt
+{
+
+void
+sc_value_base::concat_clear_data(bool /* to_ones */)
+{
+ static const char error_message[] =
+ "concat_clear_data method not supported by this type";
+ SC_REPORT_ERROR("operation failed", error_message);
+}
+
+bool
+sc_value_base::concat_get_ctrl(sc_digit * /*dst_p*/, int /*low_i*/) const
+{
+ static const char error_message[] =
+ "concat_get_ctrl method not supported by this type";
+ SC_REPORT_ERROR("operation failed", error_message);
+ return false;
+}
+
+bool
+sc_value_base::concat_get_data(sc_digit * /*dst_p*/, int /*low_i*/) const
+{
+ static const char error_message[] =
+ "concat_get_data method not supported by this type";
+ SC_REPORT_ERROR("operation failed", error_message);
+ return false;
+}
+
+sc_dt::uint64
+sc_value_base::concat_get_uint64() const
+{
+ static const char error_message[] =
+ "concat_get_uint64 method not supported by this type";
+ SC_REPORT_ERROR("operation failed", error_message);
+ return 0;
+}
+
+int
+sc_value_base::concat_length(bool * /*xz_present_p*/) const
+{
+ static const char error_message[] =
+ "concat_length method not supported by this type";
+ SC_REPORT_ERROR("operation failed", error_message);
+ return 0;
+}
+
+void
+sc_value_base::concat_set(int64 /*src*/, int /*low_i*/)
+{
+ static const char error_message[] =
+ "concat_set(int64) method not supported by this type";
+ SC_REPORT_ERROR("operation failed", error_message);
+}
+
+void
+sc_value_base::concat_set(const sc_signed &/*src*/, int /*low_i*/)
+{
+ static const char error_message[] =
+ "concat_set(sc_signed) method not supported by this type";
+ SC_REPORT_ERROR("operation failed", error_message);
+}
+
+void
+sc_value_base::concat_set(const sc_unsigned &/*src*/, int /*low_i*/)
+{
+ static const char error_message[] =
+ "concat_set(sc_unsigned) method not supported by this type";
+ SC_REPORT_ERROR("operation failed", error_message);
+}
+
+void
+sc_value_base::concat_set(uint64 /*src*/, int /*low_i*/)
+{
+ static const char error_message[] =
+ "concat_set(uint64) method not supported by this type";
+ SC_REPORT_ERROR("operation failed", error_message);
+}
+
+} // namespace sc_dt