diff options
Diffstat (limited to 'src/systemc/dt/int')
-rw-r--r-- | src/systemc/dt/int/SConscript | 38 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_int_base.cc | 706 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_int_mask.cc | 2268 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_length_param.cc | 91 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_nbcommon.inc | 2617 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_nbexterns.cc | 739 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_nbfriends.inc | 582 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_nbutils.cc | 1749 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_signed.cc | 3982 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_signed_bitref.inc | 163 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_signed_subref.inc | 402 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_uint_base.cc | 708 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_unsigned.cc | 2259 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_unsigned_bitref.inc | 162 | ||||
-rw-r--r-- | src/systemc/dt/int/sc_unsigned_subref.inc | 394 |
15 files changed, 16860 insertions, 0 deletions
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(); +} |