diff options
Diffstat (limited to 'src/systemc/dt/int/sc_nbcommon.inc')
-rw-r--r-- | src/systemc/dt/int/sc_nbcommon.inc | 2617 |
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; +} |