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