summaryrefslogtreecommitdiff
path: root/src/systemc/dt/int/sc_nbcommon.inc
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/dt/int/sc_nbcommon.inc')
-rw-r--r--src/systemc/dt/int/sc_nbcommon.inc2617
1 files changed, 2617 insertions, 0 deletions
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;
+}