diff options
author | Gabe Black <gabeblack@google.com> | 2018-05-24 01:29:36 -0700 |
---|---|---|
committer | Gabe Black <gabeblack@google.com> | 2018-08-08 10:09:06 +0000 |
commit | 7235d3b5211d0ba8f528d930a4c1e7ad62eec51a (patch) | |
tree | c2827b177216f929c502c770ab577f1c73e61318 | |
parent | 5ee040a534d422ee08918ef49d55620184df7120 (diff) | |
download | gem5-7235d3b5211d0ba8f528d930a4c1e7ad62eec51a.tar.xz |
systemc: Add the Accellera implementation for the data type classes.
These files have been cleaned up style wise, and some macros have been
resolved like they were for the header files.
Change-Id: I447e5311961036847e7da0c5a86c0da25a633010
Reviewed-on: https://gem5-review.googlesource.com/10844
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
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 |