diff options
35 files changed, 23101 insertions, 0 deletions
diff --git a/src/systemc/dt/bit/SConscript b/src/systemc/dt/bit/SConscript new file mode 100644 index 000000000..ed6eb35a0 --- /dev/null +++ b/src/systemc/dt/bit/SConscript @@ -0,0 +1,34 @@ +# 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') diff --git a/src/systemc/dt/bit/sc_bit.cc b/src/systemc/dt/bit/sc_bit.cc new file mode 100644 index 000000000..7300b0d0b --- /dev/null +++ b/src/systemc/dt/bit/sc_bit.cc @@ -0,0 +1,127 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/bit/sc_bv_base.cc b/src/systemc/dt/bit/sc_bv_base.cc new file mode 100644 index 000000000..84265af8d --- /dev/null +++ b/src/systemc/dt/bit/sc_bv_base.cc @@ -0,0 +1,231 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/bit/sc_logic.cc b/src/systemc/dt/bit/sc_logic.cc new file mode 100644 index 000000000..81663fcee --- /dev/null +++ b/src/systemc/dt/bit/sc_logic.cc @@ -0,0 +1,166 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/bit/sc_lv_base.cc b/src/systemc/dt/bit/sc_lv_base.cc new file mode 100644 index 000000000..9ffa50597 --- /dev/null +++ b/src/systemc/dt/bit/sc_lv_base.cc @@ -0,0 +1,180 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/SConscript b/src/systemc/dt/fx/SConscript new file mode 100644 index 000000000..698496cf4 --- /dev/null +++ b/src/systemc/dt/fx/SConscript @@ -0,0 +1,41 @@ +# 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') diff --git a/src/systemc/dt/fx/sc_fxcast_switch.cc b/src/systemc/dt/fx/sc_fxcast_switch.cc new file mode 100644 index 000000000..9aabe14ae --- /dev/null +++ b/src/systemc/dt/fx/sc_fxcast_switch.cc @@ -0,0 +1,86 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/sc_fxdefs.cc b/src/systemc/dt/fx/sc_fxdefs.cc new file mode 100644 index 000000000..4a9e7458f --- /dev/null +++ b/src/systemc/dt/fx/sc_fxdefs.cc @@ -0,0 +1,166 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/sc_fxnum.cc b/src/systemc/dt/fx/sc_fxnum.cc new file mode 100644 index 000000000..f47b4d342 --- /dev/null +++ b/src/systemc/dt/fx/sc_fxnum.cc @@ -0,0 +1,867 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/sc_fxnum_observer.cc b/src/systemc/dt/fx/sc_fxnum_observer.cc new file mode 100644 index 000000000..1ee3c9b8b --- /dev/null +++ b/src/systemc/dt/fx/sc_fxnum_observer.cc @@ -0,0 +1,70 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/sc_fxtype_params.cc b/src/systemc/dt/fx/sc_fxtype_params.cc new file mode 100644 index 000000000..54af8a7ee --- /dev/null +++ b/src/systemc/dt/fx/sc_fxtype_params.cc @@ -0,0 +1,97 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/sc_fxval.cc b/src/systemc/dt/fx/sc_fxval.cc new file mode 100644 index 000000000..45d7d5735 --- /dev/null +++ b/src/systemc/dt/fx/sc_fxval.cc @@ -0,0 +1,810 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/sc_fxval_observer.cc b/src/systemc/dt/fx/sc_fxval_observer.cc new file mode 100644 index 000000000..7b143ad04 --- /dev/null +++ b/src/systemc/dt/fx/sc_fxval_observer.cc @@ -0,0 +1,72 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/scfx_mant.cc b/src/systemc/dt/fx/scfx_mant.cc new file mode 100644 index 000000000..41f3aedcb --- /dev/null +++ b/src/systemc/dt/fx/scfx_mant.cc @@ -0,0 +1,117 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/scfx_pow10.cc b/src/systemc/dt/fx/scfx_pow10.cc new file mode 100644 index 000000000..fd940f94e --- /dev/null +++ b/src/systemc/dt/fx/scfx_pow10.cc @@ -0,0 +1,129 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/scfx_rep.cc b/src/systemc/dt/fx/scfx_rep.cc new file mode 100644 index 000000000..3d10fb3f6 --- /dev/null +++ b/src/systemc/dt/fx/scfx_rep.cc @@ -0,0 +1,2651 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/fx/scfx_utils.cc b/src/systemc/dt/fx/scfx_utils.cc new file mode 100644 index 000000000..844e15df6 --- /dev/null +++ b/src/systemc/dt/fx/scfx_utils.cc @@ -0,0 +1,162 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/int/SConscript b/src/systemc/dt/int/SConscript new file mode 100644 index 000000000..93e01b243 --- /dev/null +++ b/src/systemc/dt/int/SConscript @@ -0,0 +1,38 @@ +# 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') diff --git a/src/systemc/dt/int/sc_int_base.cc b/src/systemc/dt/int/sc_int_base.cc new file mode 100644 index 000000000..d5b005b93 --- /dev/null +++ b/src/systemc/dt/int/sc_int_base.cc @@ -0,0 +1,706 @@ +/***************************************************************************** + + 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; diff --git a/src/systemc/dt/int/sc_int_mask.cc b/src/systemc/dt/int/sc_int_mask.cc new file mode 100644 index 000000000..85473bbea --- /dev/null +++ b/src/systemc/dt/int/sc_int_mask.cc @@ -0,0 +1,2268 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/int/sc_length_param.cc b/src/systemc/dt/int/sc_length_param.cc new file mode 100644 index 000000000..920da13b5 --- /dev/null +++ b/src/systemc/dt/int/sc_length_param.cc @@ -0,0 +1,91 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/int/sc_nbcommon.inc b/src/systemc/dt/int/sc_nbcommon.inc new file mode 100644 index 000000000..90507ff91 --- /dev/null +++ b/src/systemc/dt/int/sc_nbcommon.inc @@ -0,0 +1,2617 @@ +/***************************************************************************** + + 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; +} diff --git a/src/systemc/dt/int/sc_nbexterns.cc b/src/systemc/dt/int/sc_nbexterns.cc new file mode 100644 index 000000000..479e68e85 --- /dev/null +++ b/src/systemc/dt/int/sc_nbexterns.cc @@ -0,0 +1,739 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/int/sc_nbfriends.inc b/src/systemc/dt/int/sc_nbfriends.inc new file mode 100644 index 000000000..9161692f0 --- /dev/null +++ b/src/systemc/dt/int/sc_nbfriends.inc @@ -0,0 +1,582 @@ +/***************************************************************************** + + 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); +} diff --git a/src/systemc/dt/int/sc_nbutils.cc b/src/systemc/dt/int/sc_nbutils.cc new file mode 100644 index 000000000..df7cc554d --- /dev/null +++ b/src/systemc/dt/int/sc_nbutils.cc @@ -0,0 +1,1749 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/int/sc_signed.cc b/src/systemc/dt/int/sc_signed.cc new file mode 100644 index 000000000..63a2d0330 --- /dev/null +++ b/src/systemc/dt/int/sc_signed.cc @@ -0,0 +1,3982 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/int/sc_signed_bitref.inc b/src/systemc/dt/int/sc_signed_bitref.inc new file mode 100644 index 000000000..c20301c68 --- /dev/null +++ b/src/systemc/dt/int/sc_signed_bitref.inc @@ -0,0 +1,163 @@ +/***************************************************************************** + + 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; +} diff --git a/src/systemc/dt/int/sc_signed_subref.inc b/src/systemc/dt/int/sc_signed_subref.inc new file mode 100644 index 000000000..476c81500 --- /dev/null +++ b/src/systemc/dt/int/sc_signed_subref.inc @@ -0,0 +1,402 @@ +/***************************************************************************** + + 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(); +} diff --git a/src/systemc/dt/int/sc_uint_base.cc b/src/systemc/dt/int/sc_uint_base.cc new file mode 100644 index 000000000..58e4605c3 --- /dev/null +++ b/src/systemc/dt/int/sc_uint_base.cc @@ -0,0 +1,708 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/int/sc_unsigned.cc b/src/systemc/dt/int/sc_unsigned.cc new file mode 100644 index 000000000..d2535b6b1 --- /dev/null +++ b/src/systemc/dt/int/sc_unsigned.cc @@ -0,0 +1,2259 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/int/sc_unsigned_bitref.inc b/src/systemc/dt/int/sc_unsigned_bitref.inc new file mode 100644 index 000000000..09eccd03c --- /dev/null +++ b/src/systemc/dt/int/sc_unsigned_bitref.inc @@ -0,0 +1,162 @@ +/***************************************************************************** + + 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; +} diff --git a/src/systemc/dt/int/sc_unsigned_subref.inc b/src/systemc/dt/int/sc_unsigned_subref.inc new file mode 100644 index 000000000..f76f65ca8 --- /dev/null +++ b/src/systemc/dt/int/sc_unsigned_subref.inc @@ -0,0 +1,394 @@ +/***************************************************************************** + + 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(); +} diff --git a/src/systemc/dt/misc/SConscript b/src/systemc/dt/misc/SConscript new file mode 100644 index 000000000..6f6d8191e --- /dev/null +++ b/src/systemc/dt/misc/SConscript @@ -0,0 +1,32 @@ +# 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') diff --git a/src/systemc/dt/misc/sc_concatref.cc b/src/systemc/dt/misc/sc_concatref.cc new file mode 100644 index 000000000..cb31efbaa --- /dev/null +++ b/src/systemc/dt/misc/sc_concatref.cc @@ -0,0 +1,66 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/dt/misc/sc_value_base.cc b/src/systemc/dt/misc/sc_value_base.cc new file mode 100644 index 000000000..774f58391 --- /dev/null +++ b/src/systemc/dt/misc/sc_value_base.cc @@ -0,0 +1,137 @@ +/***************************************************************************** + + 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 |