| /***************************************************************************** |
| |
| 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; |
| } |