112854Sgabeblack@google.com/*****************************************************************************
212854Sgabeblack@google.com
312854Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412854Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
512854Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
612854Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
712854Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
812854Sgabeblack@google.com  License.  You may obtain a copy of the License at
912854Sgabeblack@google.com
1012854Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1112854Sgabeblack@google.com
1212854Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1312854Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1412854Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512854Sgabeblack@google.com  implied.  See the License for the specific language governing
1612854Sgabeblack@google.com  permissions and limitations under the License.
1712854Sgabeblack@google.com
1812854Sgabeblack@google.com *****************************************************************************/
1912854Sgabeblack@google.com
2012854Sgabeblack@google.com/*****************************************************************************
2112854Sgabeblack@google.com
2212854Sgabeblack@google.com  sc_nbcommon.cpp -- Functions common to both sc_signed and sc_unsigned.
2312854Sgabeblack@google.com                     This file is included in sc_signed.cpp and
2412854Sgabeblack@google.com                     sc_unsigned.cpp after the macros are defined accordingly.
2512854Sgabeblack@google.com                     For example, sc_signed.cpp will first define CLASS_TYPE
2612854Sgabeblack@google.com                     as sc_signed before including this file. This file like
2712854Sgabeblack@google.com                     sc_nbfriends.cpp and sc_nbexterns.cpp is created in order
2812854Sgabeblack@google.com                     to ensure only one version of each function, regardless
2912854Sgabeblack@google.com                     of the class that they interface to.
3012854Sgabeblack@google.com
3112854Sgabeblack@google.com  Original Author: Ali Dasdan, Synopsys, Inc.
3212854Sgabeblack@google.com
3312854Sgabeblack@google.com *****************************************************************************/
3412854Sgabeblack@google.com
3512854Sgabeblack@google.com/*****************************************************************************
3612854Sgabeblack@google.com
3712854Sgabeblack@google.com  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
3812854Sgabeblack@google.com  changes you are making here.
3912854Sgabeblack@google.com
4012854Sgabeblack@google.com      Name, Affiliation, Date:
4112854Sgabeblack@google.com  Description of Modification:
4212854Sgabeblack@google.com
4312854Sgabeblack@google.com *****************************************************************************/
4412854Sgabeblack@google.com
4512854Sgabeblack@google.com
4612854Sgabeblack@google.com// ----------------------------------------------------------------------------
4712854Sgabeblack@google.com//  SECTION : Public members
4812854Sgabeblack@google.com// ----------------------------------------------------------------------------
4912854Sgabeblack@google.com
5012854Sgabeblack@google.com// Create a CLASS_TYPE number with nb bits.
5112854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(int nb) :
5212854Sgabeblack@google.com    sc_value_base(), sgn(), nbits(), ndigits(), digit()
5312854Sgabeblack@google.com{
5412854Sgabeblack@google.com    sgn = default_sign();
5512854Sgabeblack@google.com    if (nb > 0) {
5612854Sgabeblack@google.com	nbits = num_bits(nb);
5712854Sgabeblack@google.com    } else {
5812854Sgabeblack@google.com        invalid_init("int nb", nb);
5912854Sgabeblack@google.com        sc_core::sc_abort(); // can't recover from here
6012854Sgabeblack@google.com    }
6112854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
6212854Sgabeblack@google.com#ifdef SC_MAX_NBITS
6312854Sgabeblack@google.com    test_bound(nb);
6412854Sgabeblack@google.com#else
6512854Sgabeblack@google.com    digit = new sc_digit[ndigits];
6612854Sgabeblack@google.com#endif
6712854Sgabeblack@google.com    makezero();
6812854Sgabeblack@google.com}
6912854Sgabeblack@google.com
7012854Sgabeblack@google.com
7112854Sgabeblack@google.com// Create a copy of v with sgn s. v is of the same type.
7212854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const CLASS_TYPE &v) :
7312854Sgabeblack@google.com    sc_value_base(v), sgn(v.sgn), nbits(v.nbits), ndigits(v.ndigits), digit()
7412854Sgabeblack@google.com{
7512854Sgabeblack@google.com#ifndef SC_MAX_NBITS
7612854Sgabeblack@google.com  digit = new sc_digit[ndigits];
7712854Sgabeblack@google.com#endif
7812854Sgabeblack@google.com
7912854Sgabeblack@google.com  vec_copy(ndigits, digit, v.digit);
8012854Sgabeblack@google.com}
8112854Sgabeblack@google.com
8212854Sgabeblack@google.com
8312854Sgabeblack@google.com// Create a copy of v where v is of the different type.
8412854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const OTHER_CLASS_TYPE &v) :
8512854Sgabeblack@google.com    sc_value_base(v), sgn(v.sgn), nbits(num_bits(v.nbits)), ndigits(), digit()
8612854Sgabeblack@google.com{
8712854Sgabeblack@google.com#if (IF_SC_SIGNED == 1)
8812854Sgabeblack@google.com  ndigits = v.ndigits;
8912854Sgabeblack@google.com#else
9012854Sgabeblack@google.com  ndigits = DIV_CEIL(nbits);
9112854Sgabeblack@google.com#endif
9212854Sgabeblack@google.com
9312854Sgabeblack@google.com#ifndef SC_MAX_NBITS
9412854Sgabeblack@google.com  digit = new sc_digit[ndigits];
9512854Sgabeblack@google.com#endif
9612854Sgabeblack@google.com
9712854Sgabeblack@google.com  copy_digits(v.nbits, v.ndigits, v.digit);
9812854Sgabeblack@google.com}
9912854Sgabeblack@google.com
10012854Sgabeblack@google.com// Create a copy of v where v is an sign-less instance.
10112854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const sc_bv_base &v) :
10212854Sgabeblack@google.com    sc_value_base(), sgn(), nbits(), ndigits(), digit()
10312854Sgabeblack@google.com{
10412854Sgabeblack@google.com    int nb = v.length();
10512854Sgabeblack@google.com    sgn = default_sign();
10612854Sgabeblack@google.com    if (nb > 0) {
10712854Sgabeblack@google.com        nbits = num_bits(nb);
10812854Sgabeblack@google.com    } else {
10912854Sgabeblack@google.com        invalid_init("sc_bv_base", nb);
11012854Sgabeblack@google.com        sc_core::sc_abort(); // can't recover from here
11112854Sgabeblack@google.com    }
11212854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
11312854Sgabeblack@google.com#   ifdef SC_MAX_NBITS
11412854Sgabeblack@google.com        test_bound(nb);
11512854Sgabeblack@google.com#    else
11612854Sgabeblack@google.com        digit = new sc_digit[ndigits];
11712854Sgabeblack@google.com#    endif
11812854Sgabeblack@google.com    makezero();
11912854Sgabeblack@google.com    *this = v;
12012854Sgabeblack@google.com}
12112854Sgabeblack@google.com
12212854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const sc_lv_base &v) :
12312854Sgabeblack@google.com    sc_value_base(), sgn(), nbits(), ndigits(), digit()
12412854Sgabeblack@google.com{
12512854Sgabeblack@google.com    int nb = v.length();
12612854Sgabeblack@google.com    sgn = default_sign();
12712854Sgabeblack@google.com    if (nb > 0) {
12812854Sgabeblack@google.com        nbits = num_bits(nb);
12912854Sgabeblack@google.com    } else {
13012854Sgabeblack@google.com        invalid_init("sc_lv_base", nb);
13112854Sgabeblack@google.com        sc_core::sc_abort(); // can't recover from here
13212854Sgabeblack@google.com    }
13312854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
13412854Sgabeblack@google.com#   ifdef SC_MAX_NBITS
13512854Sgabeblack@google.com        test_bound(nb);
13612854Sgabeblack@google.com#    else
13712854Sgabeblack@google.com        digit = new sc_digit[ndigits];
13812854Sgabeblack@google.com#    endif
13912854Sgabeblack@google.com    makezero();
14012854Sgabeblack@google.com    *this = v;
14112854Sgabeblack@google.com}
14212854Sgabeblack@google.com
14312854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const sc_int_subref_r &v) :
14412854Sgabeblack@google.com    sc_value_base(v), sgn(), nbits(), ndigits(), digit()
14512854Sgabeblack@google.com{
14612854Sgabeblack@google.com    int nb = v.length();
14712854Sgabeblack@google.com    sgn = default_sign();
14812854Sgabeblack@google.com    if (nb > 0) {
14912854Sgabeblack@google.com        nbits = num_bits(nb);
15012854Sgabeblack@google.com    } else {
15112854Sgabeblack@google.com        invalid_init("sc_int_subref", nb);
15212854Sgabeblack@google.com        sc_core::sc_abort(); // can't recover from here
15312854Sgabeblack@google.com    }
15412854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
15512854Sgabeblack@google.com#   ifdef SC_MAX_NBITS
15612854Sgabeblack@google.com        test_bound(nb);
15712854Sgabeblack@google.com#    else
15812854Sgabeblack@google.com        digit = new sc_digit[ndigits];
15912854Sgabeblack@google.com#    endif
16012854Sgabeblack@google.com    makezero();
16112854Sgabeblack@google.com    *this = v.to_uint64();
16212854Sgabeblack@google.com}
16312854Sgabeblack@google.com
16412854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const sc_uint_subref_r &v) :
16512854Sgabeblack@google.com    sc_value_base(v), sgn(), nbits(), ndigits(), digit()
16612854Sgabeblack@google.com{
16712854Sgabeblack@google.com    int nb = v.length();
16812854Sgabeblack@google.com    sgn = default_sign();
16912854Sgabeblack@google.com    if (nb > 0) {
17012854Sgabeblack@google.com        nbits = num_bits(nb);
17112854Sgabeblack@google.com    } else {
17212854Sgabeblack@google.com        invalid_init("sc_uint_subref", nb);
17312854Sgabeblack@google.com        sc_core::sc_abort(); // can't recover from here
17412854Sgabeblack@google.com    }
17512854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
17612854Sgabeblack@google.com#   ifdef SC_MAX_NBITS
17712854Sgabeblack@google.com        test_bound(nb);
17812854Sgabeblack@google.com#    else
17912854Sgabeblack@google.com        digit = new sc_digit[ndigits];
18012854Sgabeblack@google.com#    endif
18112854Sgabeblack@google.com    makezero();
18212854Sgabeblack@google.com    *this = v.to_uint64();
18312854Sgabeblack@google.com}
18412854Sgabeblack@google.com
18512854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const sc_signed_subref_r &v) :
18612854Sgabeblack@google.com    sc_value_base(v), sgn(), nbits(), ndigits(), digit()
18712854Sgabeblack@google.com{
18812854Sgabeblack@google.com    int nb = v.length();
18912854Sgabeblack@google.com    sgn = default_sign();
19012854Sgabeblack@google.com    if (nb > 0) {
19112854Sgabeblack@google.com        nbits = num_bits(nb);
19212854Sgabeblack@google.com    } else {
19312854Sgabeblack@google.com        invalid_init("sc_signed_subref", nb);
19412854Sgabeblack@google.com        sc_core::sc_abort(); // can't recover from here
19512854Sgabeblack@google.com    }
19612854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
19712854Sgabeblack@google.com#   ifdef SC_MAX_NBITS
19812854Sgabeblack@google.com        test_bound(nb);
19912854Sgabeblack@google.com#    else
20012854Sgabeblack@google.com        digit = new sc_digit[ndigits];
20112854Sgabeblack@google.com#    endif
20212854Sgabeblack@google.com    makezero();
20312854Sgabeblack@google.com    *this = sc_unsigned(v.m_obj_p, v.m_left, v.m_right);
20412854Sgabeblack@google.com}
20512854Sgabeblack@google.com
20612854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const sc_unsigned_subref_r &v) :
20712854Sgabeblack@google.com    sc_value_base(v), sgn(), nbits(), ndigits(), digit()
20812854Sgabeblack@google.com{
20912854Sgabeblack@google.com    int nb = v.length();
21012854Sgabeblack@google.com    sgn = default_sign();
21112854Sgabeblack@google.com    if (nb > 0) {
21212854Sgabeblack@google.com        nbits = num_bits(nb);
21312854Sgabeblack@google.com    } else {
21412854Sgabeblack@google.com        invalid_init("sc_unsigned_subref", nb);
21512854Sgabeblack@google.com        sc_core::sc_abort(); // can't recover from here
21612854Sgabeblack@google.com    }
21712854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
21812854Sgabeblack@google.com#   ifdef SC_MAX_NBITS
21912854Sgabeblack@google.com        test_bound(nb);
22012854Sgabeblack@google.com#    else
22112854Sgabeblack@google.com        digit = new sc_digit[ndigits];
22212854Sgabeblack@google.com#    endif
22312854Sgabeblack@google.com    makezero();
22412854Sgabeblack@google.com    *this = sc_unsigned(v.m_obj_p, v.m_left, v.m_right);
22512854Sgabeblack@google.com}
22612854Sgabeblack@google.com
22712854Sgabeblack@google.com// ----------------------------------------------------------------------------
22812854Sgabeblack@google.com//  SECTION: Public members - Concatenation support.
22912854Sgabeblack@google.com// ----------------------------------------------------------------------------
23012854Sgabeblack@google.com
23112854Sgabeblack@google.com
23212854Sgabeblack@google.com// ----------------------------------------------------------------------------
23312854Sgabeblack@google.com//  SECTION: Public members - Assignment operators.
23412854Sgabeblack@google.com// ----------------------------------------------------------------------------
23512854Sgabeblack@google.com
23612854Sgabeblack@google.com// Assignment from v of the same type.
23712854Sgabeblack@google.comconst CLASS_TYPE &
23812854Sgabeblack@google.comCLASS_TYPE::operator = (const CLASS_TYPE &v)
23912854Sgabeblack@google.com{
24012854Sgabeblack@google.com    if (this != &v) {
24112854Sgabeblack@google.com        sgn = v.sgn;
24212854Sgabeblack@google.com
24312854Sgabeblack@google.com        if (sgn == SC_ZERO)
24412854Sgabeblack@google.com            vec_zero(ndigits, digit);
24512854Sgabeblack@google.com        else
24612854Sgabeblack@google.com            copy_digits(v.nbits, v.ndigits, v.digit);
24712854Sgabeblack@google.com    }
24812854Sgabeblack@google.com    return *this;
24912854Sgabeblack@google.com}
25012854Sgabeblack@google.com
25112854Sgabeblack@google.com
25212854Sgabeblack@google.com// Assignment from v of the different type.
25312854Sgabeblack@google.comconst CLASS_TYPE &
25412854Sgabeblack@google.comCLASS_TYPE::operator = (const OTHER_CLASS_TYPE &v)
25512854Sgabeblack@google.com{
25612854Sgabeblack@google.com    sgn = v.sgn;
25712854Sgabeblack@google.com
25812854Sgabeblack@google.com    if (sgn == SC_ZERO)
25912854Sgabeblack@google.com        vec_zero(ndigits, digit);
26012854Sgabeblack@google.com    else
26112854Sgabeblack@google.com        copy_digits(v.nbits, v.ndigits, v.digit);
26212854Sgabeblack@google.com
26312854Sgabeblack@google.com    return *this;
26412854Sgabeblack@google.com}
26512854Sgabeblack@google.com
26612854Sgabeblack@google.com
26712854Sgabeblack@google.com// Assignment from an sc_unsigned_subref_r
26812854Sgabeblack@google.comconst CLASS_TYPE &
26912854Sgabeblack@google.comCLASS_TYPE::operator = (const sc_unsigned_subref_r &v)
27012854Sgabeblack@google.com{
27112854Sgabeblack@google.com    return operator=(sc_unsigned(v));
27212854Sgabeblack@google.com}
27312854Sgabeblack@google.com
27412854Sgabeblack@google.com
27512854Sgabeblack@google.com// Assignment from an sc_signed_subref_r
27612854Sgabeblack@google.comconst CLASS_TYPE &
27712854Sgabeblack@google.comCLASS_TYPE::operator = (const sc_signed_subref_r &v)
27812854Sgabeblack@google.com{
27912854Sgabeblack@google.com    return operator = (sc_unsigned(v));
28012854Sgabeblack@google.com}
28112854Sgabeblack@google.com
28212854Sgabeblack@google.com
28312854Sgabeblack@google.com// ----------------------------------------------------------------------------
28412854Sgabeblack@google.com//  SECTION: Input and output operators
28512854Sgabeblack@google.com// ----------------------------------------------------------------------------
28612854Sgabeblack@google.com
28712854Sgabeblack@google.comvoid
28812854Sgabeblack@google.comCLASS_TYPE::scan(::std::istream &is)
28912854Sgabeblack@google.com{
29012854Sgabeblack@google.com    std::string s;
29112854Sgabeblack@google.com    is >> s;
29212854Sgabeblack@google.com    *this = s.c_str();
29312854Sgabeblack@google.com}
29412854Sgabeblack@google.com
29512854Sgabeblack@google.com
29612854Sgabeblack@google.com// ----------------------------------------------------------------------------
29712854Sgabeblack@google.com//  SECTION: PLUS operators: +, +=, ++
29812854Sgabeblack@google.com// ----------------------------------------------------------------------------
29912854Sgabeblack@google.com
30012854Sgabeblack@google.com// Cases to consider when computing u + v:
30112854Sgabeblack@google.com// 1. 0 + v = v
30212854Sgabeblack@google.com// 2. u + 0 = u
30312854Sgabeblack@google.com// 3. if sgn(u) == sgn(v)
30412854Sgabeblack@google.com//    3.1 u + v = +(u + v) = sgn(u) * (u + v)
30512854Sgabeblack@google.com//    3.2 (-u) + (-v) = -(u + v) = sgn(u) * (u + v)
30612854Sgabeblack@google.com// 4. if sgn(u) != sgn(v)
30712854Sgabeblack@google.com//    4.1 u + (-v) = u - v = sgn(u) * (u - v)
30812854Sgabeblack@google.com//    4.2 (-u) + v = -(u - v) ==> sgn(u) * (u - v)
30912854Sgabeblack@google.com//
31012854Sgabeblack@google.com// Specialization of above cases for computing ++u or u++:
31112854Sgabeblack@google.com// 1. 0 + 1 = 1
31212854Sgabeblack@google.com// 3. u + 1 = u + 1 = sgn(u) * (u + 1)
31312854Sgabeblack@google.com// 4. (-u) + 1 = -(u - 1) = sgn(u) * (u - 1)
31412854Sgabeblack@google.com
31512854Sgabeblack@google.comconst CLASS_TYPE &
31612854Sgabeblack@google.comCLASS_TYPE::operator += (const CLASS_TYPE &v)
31712854Sgabeblack@google.com{
31812854Sgabeblack@google.com    // u = *this
31912854Sgabeblack@google.com
32012854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 1
32112854Sgabeblack@google.com        return (*this = v);
32212854Sgabeblack@google.com
32312854Sgabeblack@google.com    if (v.sgn == SC_ZERO) // case 2
32412854Sgabeblack@google.com        return *this;
32512854Sgabeblack@google.com
32612854Sgabeblack@google.com    // cases 3 and 4
32712854Sgabeblack@google.com    add_on_help(sgn, nbits, ndigits, digit,
32812854Sgabeblack@google.com                v.sgn, v.nbits, v.ndigits, v.digit);
32912854Sgabeblack@google.com
33012854Sgabeblack@google.com    convert_SM_to_2C_to_SM();
33112854Sgabeblack@google.com
33212854Sgabeblack@google.com    return *this;
33312854Sgabeblack@google.com}
33412854Sgabeblack@google.com
33512854Sgabeblack@google.com
33612854Sgabeblack@google.comconst CLASS_TYPE &
33712854Sgabeblack@google.comCLASS_TYPE::operator += (const OTHER_CLASS_TYPE &v)
33812854Sgabeblack@google.com{
33912854Sgabeblack@google.com    // u = *this
34012854Sgabeblack@google.com
34112854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 1
34212854Sgabeblack@google.com        return (*this = v);
34312854Sgabeblack@google.com
34412854Sgabeblack@google.com    if (v.sgn == SC_ZERO) // case 2
34512854Sgabeblack@google.com        return *this;
34612854Sgabeblack@google.com
34712854Sgabeblack@google.com    // cases 3 and 4
34812854Sgabeblack@google.com    add_on_help(sgn, nbits, ndigits, digit,
34912854Sgabeblack@google.com                v.sgn, v.nbits, v.ndigits, v.digit);
35012854Sgabeblack@google.com
35112854Sgabeblack@google.com    convert_SM_to_2C_to_SM();
35212854Sgabeblack@google.com
35312854Sgabeblack@google.com    return *this;
35412854Sgabeblack@google.com}
35512854Sgabeblack@google.com
35612854Sgabeblack@google.com
35712854Sgabeblack@google.comCLASS_TYPE &
35812854Sgabeblack@google.comCLASS_TYPE::operator ++ () // prefix
35912854Sgabeblack@google.com{
36012854Sgabeblack@google.com    *this = *this + 1;
36112854Sgabeblack@google.com    return *this;
36212854Sgabeblack@google.com}
36312854Sgabeblack@google.com
36412854Sgabeblack@google.com
36512854Sgabeblack@google.comconst CLASS_TYPE
36612854Sgabeblack@google.comCLASS_TYPE::operator ++ (int) // postfix
36712854Sgabeblack@google.com{
36812854Sgabeblack@google.com    // Copy digit into d.
36912854Sgabeblack@google.com
37012854Sgabeblack@google.com#ifdef SC_MAX_NBITS
37112854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS];
37212854Sgabeblack@google.com#else
37312854Sgabeblack@google.com    sc_digit *d = new sc_digit[ndigits];
37412854Sgabeblack@google.com#endif
37512854Sgabeblack@google.com
37612854Sgabeblack@google.com    small_type s = sgn;
37712854Sgabeblack@google.com
37812854Sgabeblack@google.com    vec_copy(ndigits, d, digit);
37912854Sgabeblack@google.com
38012854Sgabeblack@google.com    *this = *this + 1;
38112854Sgabeblack@google.com
38212854Sgabeblack@google.com    return CLASS_TYPE(s, nbits, ndigits, d);
38312854Sgabeblack@google.com}
38412854Sgabeblack@google.com
38512854Sgabeblack@google.com
38612854Sgabeblack@google.comconst CLASS_TYPE &
38712854Sgabeblack@google.comCLASS_TYPE::operator += (int64 v)
38812854Sgabeblack@google.com{
38912854Sgabeblack@google.com    // u = *this
39012854Sgabeblack@google.com
39112854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 1
39212854Sgabeblack@google.com        return (*this = v);
39312854Sgabeblack@google.com
39412854Sgabeblack@google.com    if (v == 0) // case 2
39512854Sgabeblack@google.com        return *this;
39612854Sgabeblack@google.com
39712854Sgabeblack@google.com    CONVERT_INT64(v);
39812854Sgabeblack@google.com
39912854Sgabeblack@google.com    // cases 3 and 4
40012854Sgabeblack@google.com    add_on_help(sgn, nbits, ndigits, digit,
40112854Sgabeblack@google.com                vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
40212854Sgabeblack@google.com
40312854Sgabeblack@google.com    convert_SM_to_2C_to_SM();
40412854Sgabeblack@google.com
40512854Sgabeblack@google.com    return *this;
40612854Sgabeblack@google.com}
40712854Sgabeblack@google.com
40812854Sgabeblack@google.com
40912854Sgabeblack@google.comconst CLASS_TYPE &
41012854Sgabeblack@google.comCLASS_TYPE::operator += (uint64 v)
41112854Sgabeblack@google.com{
41212854Sgabeblack@google.com    // u = *this
41312854Sgabeblack@google.com
41412854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 1
41512854Sgabeblack@google.com        return (*this = v);
41612854Sgabeblack@google.com
41712854Sgabeblack@google.com    if (v == 0)  // case 2
41812854Sgabeblack@google.com        return *this;
41912854Sgabeblack@google.com
42012854Sgabeblack@google.com    CONVERT_INT64(v);
42112854Sgabeblack@google.com
42212854Sgabeblack@google.com    // cases 3 and 4
42312854Sgabeblack@google.com    add_on_help(sgn, nbits, ndigits, digit,
42412854Sgabeblack@google.com                vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
42512854Sgabeblack@google.com
42612854Sgabeblack@google.com    convert_SM_to_2C_to_SM();
42712854Sgabeblack@google.com
42812854Sgabeblack@google.com    return *this;
42912854Sgabeblack@google.com}
43012854Sgabeblack@google.com
43112854Sgabeblack@google.com
43212854Sgabeblack@google.comconst CLASS_TYPE &
43312854Sgabeblack@google.comCLASS_TYPE::operator += (long v)
43412854Sgabeblack@google.com{
43512854Sgabeblack@google.com    // u = *this
43612854Sgabeblack@google.com
43712854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 1
43812854Sgabeblack@google.com        return (*this = v);
43912854Sgabeblack@google.com
44012854Sgabeblack@google.com    if (v == 0) // case 2
44112854Sgabeblack@google.com        return *this;
44212854Sgabeblack@google.com
44312854Sgabeblack@google.com    CONVERT_LONG(v);
44412854Sgabeblack@google.com
44512854Sgabeblack@google.com    // cases 3 and 4
44612854Sgabeblack@google.com    add_on_help(sgn, nbits, ndigits, digit,
44712854Sgabeblack@google.com                vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
44812854Sgabeblack@google.com
44912854Sgabeblack@google.com    convert_SM_to_2C_to_SM();
45012854Sgabeblack@google.com
45112854Sgabeblack@google.com    return *this;
45212854Sgabeblack@google.com}
45312854Sgabeblack@google.com
45412854Sgabeblack@google.com
45512854Sgabeblack@google.comconst CLASS_TYPE &
45612854Sgabeblack@google.comCLASS_TYPE::operator += (unsigned long v)
45712854Sgabeblack@google.com{
45812854Sgabeblack@google.com    // u = *this
45912854Sgabeblack@google.com
46012854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 1
46112854Sgabeblack@google.com        return (*this = v);
46212854Sgabeblack@google.com
46312854Sgabeblack@google.com    if (v == 0) // case 2
46412854Sgabeblack@google.com        return *this;
46512854Sgabeblack@google.com
46612854Sgabeblack@google.com    CONVERT_LONG(v);
46712854Sgabeblack@google.com
46812854Sgabeblack@google.com    // cases 3 and 4
46912854Sgabeblack@google.com    add_on_help(sgn, nbits, ndigits, digit,
47012854Sgabeblack@google.com                vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
47112854Sgabeblack@google.com
47212854Sgabeblack@google.com    convert_SM_to_2C_to_SM();
47312854Sgabeblack@google.com
47412854Sgabeblack@google.com    return *this;
47512854Sgabeblack@google.com}
47612854Sgabeblack@google.com
47712854Sgabeblack@google.com
47812854Sgabeblack@google.com// ----------------------------------------------------------------------------
47912854Sgabeblack@google.com//  SECTION: MINUS operators: -, -=, --
48012854Sgabeblack@google.com// ----------------------------------------------------------------------------
48112854Sgabeblack@google.com
48212854Sgabeblack@google.com// Cases to consider when computing u + v:
48312854Sgabeblack@google.com// 1. u - 0 = u
48412854Sgabeblack@google.com// 2. 0 - v = -v
48512854Sgabeblack@google.com// 3. if sgn(u) != sgn(v)
48612854Sgabeblack@google.com//    3.1 u - (-v) = u + v = sgn(u) * (u + v)
48712854Sgabeblack@google.com//    3.2 (-u) - v = -(u + v) ==> sgn(u) * (u + v)
48812854Sgabeblack@google.com// 4. if sgn(u) == sgn(v)
48912854Sgabeblack@google.com//    4.1 u - v = +(u - v) = sgn(u) * (u - v)
49012854Sgabeblack@google.com//    4.2 (-u) - (-v) = -(u - v) = sgn(u) * (u - v)
49112854Sgabeblack@google.com//
49212854Sgabeblack@google.com// Specialization of above cases for computing --u or u--:
49312854Sgabeblack@google.com// 1. 0 - 1 = -1
49412854Sgabeblack@google.com// 3. (-u) - 1 = -(u + 1) = sgn(u) * (u + 1)
49512854Sgabeblack@google.com// 4. u - 1 = u - 1 = sgn(u) * (u - 1)
49612854Sgabeblack@google.com
49712854Sgabeblack@google.comconst CLASS_TYPE &
49812854Sgabeblack@google.comCLASS_TYPE::operator -= (const CLASS_TYPE &v)
49912854Sgabeblack@google.com{
50012854Sgabeblack@google.com    // u = *this
50112854Sgabeblack@google.com    if (v.sgn == SC_ZERO) // case 1
50212854Sgabeblack@google.com        return *this;
50312854Sgabeblack@google.com    if (sgn == SC_ZERO) { // case 2
50412854Sgabeblack@google.com        sgn = -v.sgn;
50512854Sgabeblack@google.com        copy_digits(v.nbits, v.ndigits, v.digit);
50612854Sgabeblack@google.com    } else {
50712854Sgabeblack@google.com        // cases 3 and 4
50812854Sgabeblack@google.com        add_on_help(sgn, nbits, ndigits, digit,
50912854Sgabeblack@google.com                  -v.sgn, v.nbits, v.ndigits, v.digit);
51012854Sgabeblack@google.com        convert_SM_to_2C_to_SM();
51112854Sgabeblack@google.com    }
51212854Sgabeblack@google.com
51312854Sgabeblack@google.com    return *this;
51412854Sgabeblack@google.com}
51512854Sgabeblack@google.com
51612854Sgabeblack@google.com
51712854Sgabeblack@google.comconst CLASS_TYPE &
51812854Sgabeblack@google.comCLASS_TYPE::operator -= (const OTHER_CLASS_TYPE &v)
51912854Sgabeblack@google.com{
52012854Sgabeblack@google.com    // u = *this
52112854Sgabeblack@google.com    if (v.sgn == SC_ZERO) // case 1
52212854Sgabeblack@google.com        return *this;
52312854Sgabeblack@google.com    if (sgn == SC_ZERO) { // case 2
52412854Sgabeblack@google.com        sgn = -v.sgn;
52512854Sgabeblack@google.com        copy_digits(v.nbits, v.ndigits, v.digit);
52612854Sgabeblack@google.com    } else {
52712854Sgabeblack@google.com        // cases 3 and 4
52812854Sgabeblack@google.com        add_on_help(sgn, nbits, ndigits, digit,
52912854Sgabeblack@google.com                  -v.sgn, v.nbits, v.ndigits, v.digit);
53012854Sgabeblack@google.com
53112854Sgabeblack@google.com        convert_SM_to_2C_to_SM();
53212854Sgabeblack@google.com    }
53312854Sgabeblack@google.com    return *this;
53412854Sgabeblack@google.com}
53512854Sgabeblack@google.com
53612854Sgabeblack@google.comCLASS_TYPE &
53712854Sgabeblack@google.comCLASS_TYPE::operator -- () // prefix
53812854Sgabeblack@google.com{
53912854Sgabeblack@google.com    *this = *this - 1;
54012854Sgabeblack@google.com    return *this;
54112854Sgabeblack@google.com}
54212854Sgabeblack@google.com
54312854Sgabeblack@google.comconst CLASS_TYPE
54412854Sgabeblack@google.comCLASS_TYPE::operator -- (int) // postfix
54512854Sgabeblack@google.com{
54612854Sgabeblack@google.com    // Copy digit into d.
54712854Sgabeblack@google.com#ifdef SC_MAX_NBITS
54812854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS];
54912854Sgabeblack@google.com#else
55012854Sgabeblack@google.com    sc_digit *d = new sc_digit[ndigits];
55112854Sgabeblack@google.com#endif
55212854Sgabeblack@google.com    small_type s = sgn;
55312854Sgabeblack@google.com    vec_copy(ndigits, d, digit);
55412854Sgabeblack@google.com    *this = *this - 1;
55512854Sgabeblack@google.com    return CLASS_TYPE(s, nbits, ndigits, d);
55612854Sgabeblack@google.com}
55712854Sgabeblack@google.com
55812854Sgabeblack@google.com
55912854Sgabeblack@google.comconst CLASS_TYPE &
56012854Sgabeblack@google.comCLASS_TYPE::operator -= (int64 v)
56112854Sgabeblack@google.com{
56212854Sgabeblack@google.com    // u = *this
56312854Sgabeblack@google.com    if (v == 0) // case 1
56412854Sgabeblack@google.com        return *this;
56512854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
56612854Sgabeblack@google.com        return (*this = -v);
56712854Sgabeblack@google.com
56812854Sgabeblack@google.com    CONVERT_INT64(v);
56912854Sgabeblack@google.com
57012854Sgabeblack@google.com    // cases 3 and 4
57112854Sgabeblack@google.com    add_on_help(sgn, nbits, ndigits, digit,
57212854Sgabeblack@google.com                -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
57312854Sgabeblack@google.com
57412854Sgabeblack@google.com    convert_SM_to_2C_to_SM();
57512854Sgabeblack@google.com
57612854Sgabeblack@google.com    return *this;
57712854Sgabeblack@google.com}
57812854Sgabeblack@google.com
57912854Sgabeblack@google.com
58012854Sgabeblack@google.comconst CLASS_TYPE &
58112854Sgabeblack@google.comCLASS_TYPE::operator -= (uint64 v)
58212854Sgabeblack@google.com{
58312854Sgabeblack@google.com    // u = *this
58412854Sgabeblack@google.com
58512854Sgabeblack@google.com    if (v == 0) // case 1
58612854Sgabeblack@google.com        return *this;
58712854Sgabeblack@google.com
58812854Sgabeblack@google.com    int64 v2 = (int64) v;
58912854Sgabeblack@google.com
59012854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
59112854Sgabeblack@google.com        return (*this = -v2);
59212854Sgabeblack@google.com
59312854Sgabeblack@google.com    CONVERT_INT64(v);
59412854Sgabeblack@google.com
59512854Sgabeblack@google.com    // cases 3 and 4
59612854Sgabeblack@google.com    add_on_help(sgn, nbits, ndigits, digit,
59712854Sgabeblack@google.com                -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
59812854Sgabeblack@google.com
59912854Sgabeblack@google.com    convert_SM_to_2C_to_SM();
60012854Sgabeblack@google.com
60112854Sgabeblack@google.com    return *this;
60212854Sgabeblack@google.com}
60312854Sgabeblack@google.com
60412854Sgabeblack@google.comconst CLASS_TYPE &
60512854Sgabeblack@google.comCLASS_TYPE::operator -= (long v)
60612854Sgabeblack@google.com{
60712854Sgabeblack@google.com    // u = *this
60812854Sgabeblack@google.com
60912854Sgabeblack@google.com    if (v == 0) // case 1
61012854Sgabeblack@google.com        return *this;
61112854Sgabeblack@google.com
61212854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
61312854Sgabeblack@google.com        return (*this = -v);
61412854Sgabeblack@google.com
61512854Sgabeblack@google.com    CONVERT_LONG(v);
61612854Sgabeblack@google.com
61712854Sgabeblack@google.com    // cases 3 and 4
61812854Sgabeblack@google.com    add_on_help(sgn, nbits, ndigits, digit,
61912854Sgabeblack@google.com                -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
62012854Sgabeblack@google.com
62112854Sgabeblack@google.com    convert_SM_to_2C_to_SM();
62212854Sgabeblack@google.com
62312854Sgabeblack@google.com    return *this;
62412854Sgabeblack@google.com}
62512854Sgabeblack@google.com
62612854Sgabeblack@google.com
62712854Sgabeblack@google.comconst CLASS_TYPE &
62812854Sgabeblack@google.comCLASS_TYPE::operator -= (unsigned long v)
62912854Sgabeblack@google.com{
63012854Sgabeblack@google.com    // u = *this
63112854Sgabeblack@google.com
63212854Sgabeblack@google.com    if (v == 0) // case 1
63312854Sgabeblack@google.com        return *this;
63412854Sgabeblack@google.com
63512854Sgabeblack@google.com    long v2 = (long) v;
63612854Sgabeblack@google.com
63712854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
63812854Sgabeblack@google.com        return (*this = -v2);
63912854Sgabeblack@google.com
64012854Sgabeblack@google.com    CONVERT_LONG(v);
64112854Sgabeblack@google.com
64212854Sgabeblack@google.com    // cases 3 and 4
64312854Sgabeblack@google.com    add_on_help(sgn, nbits, ndigits, digit,
64412854Sgabeblack@google.com                -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
64512854Sgabeblack@google.com
64612854Sgabeblack@google.com    convert_SM_to_2C_to_SM();
64712854Sgabeblack@google.com
64812854Sgabeblack@google.com    return *this;
64912854Sgabeblack@google.com}
65012854Sgabeblack@google.com
65112854Sgabeblack@google.com
65212854Sgabeblack@google.com// ----------------------------------------------------------------------------
65312854Sgabeblack@google.com//  SECTION: MULTIPLICATION operators: *, *=
65412854Sgabeblack@google.com// ----------------------------------------------------------------------------
65512854Sgabeblack@google.com
65612854Sgabeblack@google.com// Cases to consider when computing u * v:
65712854Sgabeblack@google.com// 1. u * 0 = 0 * v = 0
65812854Sgabeblack@google.com// 2. 1 * v = v and -1 * v = -v
65912854Sgabeblack@google.com// 3. u * 1 = u and u * -1 = -u
66012854Sgabeblack@google.com// 4. u * v = u * v
66112854Sgabeblack@google.com
66212854Sgabeblack@google.comconst CLASS_TYPE &
66312854Sgabeblack@google.comCLASS_TYPE::operator *= (const CLASS_TYPE &v)
66412854Sgabeblack@google.com{
66512854Sgabeblack@google.com    // u = *this
66612854Sgabeblack@google.com
66712854Sgabeblack@google.com    sgn = mul_signs(sgn, v.sgn);
66812854Sgabeblack@google.com
66912854Sgabeblack@google.com    if (sgn == SC_ZERO) { // case 1
67012854Sgabeblack@google.com        vec_zero(ndigits, digit);
67112854Sgabeblack@google.com    } else {
67212854Sgabeblack@google.com        // cases 2-4
67312854Sgabeblack@google.com        MUL_ON_HELPER(sgn,    nbits, ndigits, digit,
67412854Sgabeblack@google.com                      v.nbits, v.ndigits, v.digit);
67512854Sgabeblack@google.com    }
67612854Sgabeblack@google.com
67712854Sgabeblack@google.com    return *this;
67812854Sgabeblack@google.com}
67912854Sgabeblack@google.com
68012854Sgabeblack@google.com
68112854Sgabeblack@google.comconst CLASS_TYPE &
68212854Sgabeblack@google.comCLASS_TYPE::operator *= (const OTHER_CLASS_TYPE &v)
68312854Sgabeblack@google.com{
68412854Sgabeblack@google.com    // u = *this
68512854Sgabeblack@google.com
68612854Sgabeblack@google.com    sgn = mul_signs(sgn, v.sgn);
68712854Sgabeblack@google.com
68812854Sgabeblack@google.com    if (sgn == SC_ZERO) { // case 1
68912854Sgabeblack@google.com        vec_zero(ndigits, digit);
69012854Sgabeblack@google.com    } else {
69112854Sgabeblack@google.com        // cases 2-4
69212854Sgabeblack@google.com        MUL_ON_HELPER(sgn,    nbits, ndigits, digit,
69312854Sgabeblack@google.com                      v.nbits, v.ndigits, v.digit);
69412854Sgabeblack@google.com    }
69512854Sgabeblack@google.com
69612854Sgabeblack@google.com    return *this;
69712854Sgabeblack@google.com}
69812854Sgabeblack@google.com
69912854Sgabeblack@google.com
70012854Sgabeblack@google.comconst CLASS_TYPE &
70112854Sgabeblack@google.comCLASS_TYPE::operator *= (int64 v)
70212854Sgabeblack@google.com{
70312854Sgabeblack@google.com    // u = *this
70412854Sgabeblack@google.com
70512854Sgabeblack@google.com    sgn = mul_signs(sgn, get_sign(v));
70612854Sgabeblack@google.com
70712854Sgabeblack@google.com    if (sgn == SC_ZERO) { // case 1
70812854Sgabeblack@google.com        vec_zero(ndigits, digit);
70912854Sgabeblack@google.com    } else { // cases 2-4
71012854Sgabeblack@google.com        CONVERT_INT64_2(v);
71112854Sgabeblack@google.com        MUL_ON_HELPER(sgn, nbits, ndigits, digit,
71212854Sgabeblack@google.com                      BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
71312854Sgabeblack@google.com    }
71412854Sgabeblack@google.com
71512854Sgabeblack@google.com    return *this;
71612854Sgabeblack@google.com}
71712854Sgabeblack@google.com
71812854Sgabeblack@google.com
71912854Sgabeblack@google.comconst CLASS_TYPE &
72012854Sgabeblack@google.comCLASS_TYPE::operator *= (uint64 v)
72112854Sgabeblack@google.com{
72212854Sgabeblack@google.com    // u = *this
72312854Sgabeblack@google.com    sgn = mul_signs(sgn, get_sign(v));
72412854Sgabeblack@google.com
72512854Sgabeblack@google.com    if (sgn == SC_ZERO) { // case 1
72612854Sgabeblack@google.com        vec_zero(ndigits, digit);
72712854Sgabeblack@google.com    } else { // cases 2-4
72812854Sgabeblack@google.com        CONVERT_INT64_2(v);
72912854Sgabeblack@google.com        MUL_ON_HELPER(sgn,    nbits, ndigits, digit,
73012854Sgabeblack@google.com                      BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
73112854Sgabeblack@google.com    }
73212854Sgabeblack@google.com
73312854Sgabeblack@google.com    return *this;
73412854Sgabeblack@google.com}
73512854Sgabeblack@google.com
73612854Sgabeblack@google.com
73712854Sgabeblack@google.comconst CLASS_TYPE &
73812854Sgabeblack@google.comCLASS_TYPE::operator *= (long v)
73912854Sgabeblack@google.com{
74012854Sgabeblack@google.com    // u = *this
74112854Sgabeblack@google.com
74212854Sgabeblack@google.com    sgn = mul_signs(sgn, get_sign(v));
74312854Sgabeblack@google.com
74412854Sgabeblack@google.com    if (sgn == SC_ZERO) { // case 1
74512854Sgabeblack@google.com        vec_zero(ndigits, digit);
74612854Sgabeblack@google.com    } else { // cases 2-4
74712854Sgabeblack@google.com        CONVERT_LONG_2(v);
74812854Sgabeblack@google.com        MUL_ON_HELPER(sgn,    nbits, ndigits, digit,
74912854Sgabeblack@google.com                      BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
75012854Sgabeblack@google.com    }
75112854Sgabeblack@google.com    return *this;
75212854Sgabeblack@google.com}
75312854Sgabeblack@google.com
75412854Sgabeblack@google.com
75512854Sgabeblack@google.comconst CLASS_TYPE &
75612854Sgabeblack@google.comCLASS_TYPE::operator *= (unsigned long v)
75712854Sgabeblack@google.com{
75812854Sgabeblack@google.com    // u = *this
75912854Sgabeblack@google.com
76012854Sgabeblack@google.com    sgn = mul_signs(sgn, get_sign(v));
76112854Sgabeblack@google.com
76212854Sgabeblack@google.com    if (sgn == SC_ZERO) { // case 1
76312854Sgabeblack@google.com        vec_zero(ndigits, digit);
76412854Sgabeblack@google.com    } else { // cases 2-4
76512854Sgabeblack@google.com        CONVERT_LONG_2(v);
76612854Sgabeblack@google.com        MUL_ON_HELPER(sgn,    nbits, ndigits, digit,
76712854Sgabeblack@google.com                      BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
76812854Sgabeblack@google.com    }
76912854Sgabeblack@google.com
77012854Sgabeblack@google.com    return *this;
77112854Sgabeblack@google.com}
77212854Sgabeblack@google.com
77312854Sgabeblack@google.com
77412854Sgabeblack@google.com// ----------------------------------------------------------------------------
77512854Sgabeblack@google.com//  SECTION: DIVISION operators: /, /=
77612854Sgabeblack@google.com// ----------------------------------------------------------------------------
77712854Sgabeblack@google.com
77812854Sgabeblack@google.com// Cases to consider when finding the quotient q = floor(u/v):
77912854Sgabeblack@google.com// Note that u = q * v + r for r < q.
78012854Sgabeblack@google.com// 1. 0 / 0 or u / 0 => error
78112854Sgabeblack@google.com// 2. 0 / v => 0 = 0 * v + 0
78212854Sgabeblack@google.com// 3. u / v && u = v => u = 1 * u + 0  - u or v can be 1 or -1
78312854Sgabeblack@google.com// 4. u / v && u < v => u = 0 * v + u  - u can be 1 or -1
78412854Sgabeblack@google.com// 5. u / v && u > v => u = q * v + r  - v can be 1 or -1
78512854Sgabeblack@google.com
78612854Sgabeblack@google.comconst CLASS_TYPE &
78712854Sgabeblack@google.comCLASS_TYPE::operator /= (const CLASS_TYPE &v)
78812854Sgabeblack@google.com{
78912854Sgabeblack@google.com    sgn = mul_signs(sgn, v.sgn);
79012854Sgabeblack@google.com
79112854Sgabeblack@google.com    if (sgn == SC_ZERO) {
79212854Sgabeblack@google.com        div_by_zero(v.sgn); // case 1
79312854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
79412854Sgabeblack@google.com    } else { // other cases
79512854Sgabeblack@google.com        DIV_ON_HELPER(sgn, nbits, ndigits, digit,
79612854Sgabeblack@google.com                      v.nbits, v.ndigits, v.digit);
79712854Sgabeblack@google.com    }
79812854Sgabeblack@google.com    return *this;
79912854Sgabeblack@google.com}
80012854Sgabeblack@google.com
80112854Sgabeblack@google.com
80212854Sgabeblack@google.comconst CLASS_TYPE &
80312854Sgabeblack@google.comCLASS_TYPE::operator /= (const OTHER_CLASS_TYPE &v)
80412854Sgabeblack@google.com{
80512854Sgabeblack@google.com    sgn = mul_signs(sgn, v.sgn);
80612854Sgabeblack@google.com
80712854Sgabeblack@google.com    if (sgn == SC_ZERO) {
80812854Sgabeblack@google.com        div_by_zero(v.sgn); // case 1
80912854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
81012854Sgabeblack@google.com    } else { // other cases
81112854Sgabeblack@google.com        DIV_ON_HELPER(sgn, nbits, ndigits, digit,
81212854Sgabeblack@google.com                      v.nbits, v.ndigits, v.digit);
81312854Sgabeblack@google.com    }
81412854Sgabeblack@google.com    return *this;
81512854Sgabeblack@google.com}
81612854Sgabeblack@google.com
81712854Sgabeblack@google.com
81812854Sgabeblack@google.comconst CLASS_TYPE &
81912854Sgabeblack@google.comCLASS_TYPE::operator /= (int64 v)
82012854Sgabeblack@google.com{
82112854Sgabeblack@google.com    // u = *this
82212854Sgabeblack@google.com
82312854Sgabeblack@google.com    sgn = mul_signs(sgn, get_sign(v));
82412854Sgabeblack@google.com
82512854Sgabeblack@google.com    if (sgn == SC_ZERO) {
82612854Sgabeblack@google.com        div_by_zero(v); // case 1
82712854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
82812854Sgabeblack@google.com    } else {
82912854Sgabeblack@google.com        CONVERT_INT64_2(v);
83012854Sgabeblack@google.com        // other cases
83112854Sgabeblack@google.com        DIV_ON_HELPER(sgn, nbits, ndigits, digit,
83212854Sgabeblack@google.com                      BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
83312854Sgabeblack@google.com    }
83412854Sgabeblack@google.com    return *this;
83512854Sgabeblack@google.com}
83612854Sgabeblack@google.com
83712854Sgabeblack@google.com
83812854Sgabeblack@google.comconst CLASS_TYPE &
83912854Sgabeblack@google.comCLASS_TYPE::operator /= (uint64 v)
84012854Sgabeblack@google.com{
84112854Sgabeblack@google.com    // u = *this
84212854Sgabeblack@google.com
84312854Sgabeblack@google.com    sgn = mul_signs(sgn, get_sign(v));
84412854Sgabeblack@google.com
84512854Sgabeblack@google.com    if (sgn == SC_ZERO) {
84612854Sgabeblack@google.com        div_by_zero(v); // case 1
84712854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
84812854Sgabeblack@google.com    } else {
84912854Sgabeblack@google.com        CONVERT_INT64_2(v);
85012854Sgabeblack@google.com        // other cases
85112854Sgabeblack@google.com        DIV_ON_HELPER(sgn, nbits, ndigits, digit,
85212854Sgabeblack@google.com                  BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
85312854Sgabeblack@google.com    }
85412854Sgabeblack@google.com    return *this;
85512854Sgabeblack@google.com}
85612854Sgabeblack@google.com
85712854Sgabeblack@google.com
85812854Sgabeblack@google.comconst CLASS_TYPE &
85912854Sgabeblack@google.comCLASS_TYPE::operator /= (long v)
86012854Sgabeblack@google.com{
86112854Sgabeblack@google.com    // u = *this
86212854Sgabeblack@google.com
86312854Sgabeblack@google.com    sgn = mul_signs(sgn, get_sign(v));
86412854Sgabeblack@google.com
86512854Sgabeblack@google.com    if (sgn == SC_ZERO) {
86612854Sgabeblack@google.com        div_by_zero(v); // case 1
86712854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
86812854Sgabeblack@google.com    } else {
86912854Sgabeblack@google.com        CONVERT_LONG_2(v);
87012854Sgabeblack@google.com        // other cases
87112854Sgabeblack@google.com        DIV_ON_HELPER(sgn,    nbits, ndigits, digit,
87212854Sgabeblack@google.com                      BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
87312854Sgabeblack@google.com    }
87412854Sgabeblack@google.com    return *this;
87512854Sgabeblack@google.com}
87612854Sgabeblack@google.com
87712854Sgabeblack@google.com
87812854Sgabeblack@google.comconst CLASS_TYPE &
87912854Sgabeblack@google.comCLASS_TYPE::operator /= (unsigned long v)
88012854Sgabeblack@google.com{
88112854Sgabeblack@google.com    // u = *this
88212854Sgabeblack@google.com
88312854Sgabeblack@google.com    sgn = mul_signs(sgn, get_sign(v));
88412854Sgabeblack@google.com
88512854Sgabeblack@google.com    if (sgn == SC_ZERO) {
88612854Sgabeblack@google.com        div_by_zero(v); // case 1
88712854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
88812854Sgabeblack@google.com    } else {
88912854Sgabeblack@google.com        CONVERT_LONG_2(v);
89012854Sgabeblack@google.com        // other cases
89112854Sgabeblack@google.com        DIV_ON_HELPER(sgn,    nbits, ndigits, digit,
89212854Sgabeblack@google.com                      BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
89312854Sgabeblack@google.com    }
89412854Sgabeblack@google.com    return *this;
89512854Sgabeblack@google.com}
89612854Sgabeblack@google.com
89712854Sgabeblack@google.com
89812854Sgabeblack@google.com// ----------------------------------------------------------------------------
89912854Sgabeblack@google.com//  SECTION: MOD operators: %, %=.
90012854Sgabeblack@google.com// ----------------------------------------------------------------------------
90112854Sgabeblack@google.com
90212854Sgabeblack@google.com// Cases to consider when finding the remainder r = u % v:
90312854Sgabeblack@google.com// Note that u = q * v + r for r < q.
90412854Sgabeblack@google.com// 1. 0 % 0 or u % 0 => error
90512854Sgabeblack@google.com// 2. 0 % v => 0 = 0 * v + 0
90612854Sgabeblack@google.com// 3. u % v && u = v => u = 1 * u + 0  - u or v can be 1 or -1
90712854Sgabeblack@google.com// 4. u % v && u < v => u = 0 * v + u  - u can be 1 or -1
90812854Sgabeblack@google.com// 5. u % v && u > v => u = q * v + r  - v can be 1 or -1
90912854Sgabeblack@google.com
91012854Sgabeblack@google.comconst CLASS_TYPE &
91112854Sgabeblack@google.comCLASS_TYPE::operator %= (const CLASS_TYPE &v)
91212854Sgabeblack@google.com{
91312854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) {
91412854Sgabeblack@google.com        div_by_zero(v.sgn); // case 1
91512854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
91612854Sgabeblack@google.com    } else { // other cases
91712854Sgabeblack@google.com        MOD_ON_HELPER(sgn, nbits, ndigits, digit,
91812854Sgabeblack@google.com                      v.nbits, v.ndigits, v.digit);
91912854Sgabeblack@google.com    }
92012854Sgabeblack@google.com    return *this;
92112854Sgabeblack@google.com}
92212854Sgabeblack@google.com
92312854Sgabeblack@google.com
92412854Sgabeblack@google.comconst CLASS_TYPE &
92512854Sgabeblack@google.comCLASS_TYPE::operator %= (const OTHER_CLASS_TYPE &v)
92612854Sgabeblack@google.com{
92712854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) {
92812854Sgabeblack@google.com        div_by_zero(v.sgn); // case 1
92912854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
93012854Sgabeblack@google.com    } else { // other cases
93112854Sgabeblack@google.com        MOD_ON_HELPER(sgn, nbits, ndigits, digit,
93212854Sgabeblack@google.com                      v.nbits, v.ndigits, v.digit);
93312854Sgabeblack@google.com    }
93412854Sgabeblack@google.com
93512854Sgabeblack@google.com    return *this;
93612854Sgabeblack@google.com}
93712854Sgabeblack@google.com
93812854Sgabeblack@google.com
93912854Sgabeblack@google.comconst CLASS_TYPE &
94012854Sgabeblack@google.comCLASS_TYPE::operator %= (int64 v)
94112854Sgabeblack@google.com{
94212854Sgabeblack@google.com    small_type vs = get_sign(v);
94312854Sgabeblack@google.com
94412854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (vs == SC_ZERO)) {
94512854Sgabeblack@google.com        div_by_zero(v); // case 1
94612854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
94712854Sgabeblack@google.com    } else {
94812854Sgabeblack@google.com        CONVERT_INT64_2(v);
94912854Sgabeblack@google.com        // other cases
95012854Sgabeblack@google.com        MOD_ON_HELPER(sgn, nbits, ndigits, digit,
95112854Sgabeblack@google.com                      BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
95212854Sgabeblack@google.com    }
95312854Sgabeblack@google.com    return *this;
95412854Sgabeblack@google.com}
95512854Sgabeblack@google.com
95612854Sgabeblack@google.com
95712854Sgabeblack@google.comconst CLASS_TYPE &
95812854Sgabeblack@google.comCLASS_TYPE::operator %= (uint64 v)
95912854Sgabeblack@google.com{
96012854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (v == 0)) {
96112854Sgabeblack@google.com        div_by_zero(v); // case 1
96212854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
96312854Sgabeblack@google.com    } else {
96412854Sgabeblack@google.com        CONVERT_INT64_2(v);
96512854Sgabeblack@google.com        // other cases
96612854Sgabeblack@google.com        MOD_ON_HELPER(sgn, nbits, ndigits, digit,
96712854Sgabeblack@google.com                      BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
96812854Sgabeblack@google.com
96912854Sgabeblack@google.com    }
97012854Sgabeblack@google.com    return *this;
97112854Sgabeblack@google.com}
97212854Sgabeblack@google.com
97312854Sgabeblack@google.com
97412854Sgabeblack@google.comconst CLASS_TYPE &
97512854Sgabeblack@google.comCLASS_TYPE::operator %= (long v)
97612854Sgabeblack@google.com{
97712854Sgabeblack@google.com    small_type vs = get_sign(v);
97812854Sgabeblack@google.com
97912854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (vs == SC_ZERO)) {
98012854Sgabeblack@google.com        div_by_zero(v); // case 1
98112854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
98212854Sgabeblack@google.com    } else {
98312854Sgabeblack@google.com        CONVERT_LONG_2(v);
98412854Sgabeblack@google.com        // other cases
98512854Sgabeblack@google.com        MOD_ON_HELPER(sgn, nbits, ndigits, digit,
98612854Sgabeblack@google.com                      BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
98712854Sgabeblack@google.com    }
98812854Sgabeblack@google.com    return *this;
98912854Sgabeblack@google.com}
99012854Sgabeblack@google.com
99112854Sgabeblack@google.com
99212854Sgabeblack@google.comconst CLASS_TYPE &
99312854Sgabeblack@google.comCLASS_TYPE::operator %= (unsigned long v)
99412854Sgabeblack@google.com{
99512854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (v == 0)) {
99612854Sgabeblack@google.com        div_by_zero(v); // case 1
99712854Sgabeblack@google.com        vec_zero(ndigits, digit); // case 2
99812854Sgabeblack@google.com    } else {
99912854Sgabeblack@google.com        CONVERT_LONG_2(v);
100012854Sgabeblack@google.com        // other cases
100112854Sgabeblack@google.com        MOD_ON_HELPER(sgn, nbits, ndigits, digit,
100212854Sgabeblack@google.com                      BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
100312854Sgabeblack@google.com    }
100412854Sgabeblack@google.com    return *this;
100512854Sgabeblack@google.com}
100612854Sgabeblack@google.com
100712854Sgabeblack@google.com
100812854Sgabeblack@google.com// ----------------------------------------------------------------------------
100912854Sgabeblack@google.com//    SECTION: Bitwise AND operators: &, &=
101012854Sgabeblack@google.com// ----------------------------------------------------------------------------
101112854Sgabeblack@google.com
101212854Sgabeblack@google.com// Cases to consider when computing u    &v:
101312854Sgabeblack@google.com// 1. u & 0 = 0    &v = 0
101412854Sgabeblack@google.com// 2. u    &v => sgn = +
101512854Sgabeblack@google.com// 3. (-u) & (-v) => sgn = -
101612854Sgabeblack@google.com// 4. u & (-v) => sgn = +
101712854Sgabeblack@google.com// 5. (-u)    &v => sgn = +
101812854Sgabeblack@google.com
101912854Sgabeblack@google.comconst CLASS_TYPE &
102012854Sgabeblack@google.comCLASS_TYPE::operator &= (const CLASS_TYPE &v)
102112854Sgabeblack@google.com{
102212854Sgabeblack@google.com    // u = *this
102312854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) { // case 1
102412854Sgabeblack@google.com        makezero();
102512854Sgabeblack@google.com    } else { // other cases
102612854Sgabeblack@google.com        and_on_help(sgn, nbits, ndigits, digit,
102712854Sgabeblack@google.com                    v.sgn, v.nbits, v.ndigits, v.digit);
102812854Sgabeblack@google.com        convert_2C_to_SM();
102912854Sgabeblack@google.com    }
103012854Sgabeblack@google.com    return *this;
103112854Sgabeblack@google.com}
103212854Sgabeblack@google.com
103312854Sgabeblack@google.com
103412854Sgabeblack@google.comconst CLASS_TYPE &
103512854Sgabeblack@google.comCLASS_TYPE::operator &= (const OTHER_CLASS_TYPE &v)
103612854Sgabeblack@google.com{
103712854Sgabeblack@google.com    // u = *this
103812854Sgabeblack@google.com
103912854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) { // case 1
104012854Sgabeblack@google.com        makezero();
104112854Sgabeblack@google.com    } else { // other cases
104212854Sgabeblack@google.com        and_on_help(sgn, nbits, ndigits, digit,
104312854Sgabeblack@google.com                    v.sgn, v.nbits, v.ndigits, v.digit);
104412854Sgabeblack@google.com        convert_2C_to_SM();
104512854Sgabeblack@google.com    }
104612854Sgabeblack@google.com    return *this;
104712854Sgabeblack@google.com}
104812854Sgabeblack@google.com
104912854Sgabeblack@google.com
105012854Sgabeblack@google.comconst CLASS_TYPE &
105112854Sgabeblack@google.comCLASS_TYPE::operator &= (int64 v)
105212854Sgabeblack@google.com{
105312854Sgabeblack@google.com    // u = *this
105412854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (v == 0)) { // case 1
105512854Sgabeblack@google.com        makezero();
105612854Sgabeblack@google.com    } else { // other cases
105712854Sgabeblack@google.com        CONVERT_INT64(v);
105812854Sgabeblack@google.com        and_on_help(sgn, nbits, ndigits, digit,
105912854Sgabeblack@google.com                    vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
106012854Sgabeblack@google.com        convert_2C_to_SM();
106112854Sgabeblack@google.com    }
106212854Sgabeblack@google.com    return *this;
106312854Sgabeblack@google.com}
106412854Sgabeblack@google.com
106512854Sgabeblack@google.com
106612854Sgabeblack@google.comconst CLASS_TYPE &
106712854Sgabeblack@google.comCLASS_TYPE::operator &= (uint64 v)
106812854Sgabeblack@google.com{
106912854Sgabeblack@google.com    // u = *this
107012854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (v == 0)) { // case 1
107112854Sgabeblack@google.com        makezero();
107212854Sgabeblack@google.com    } else { // other cases
107312854Sgabeblack@google.com        CONVERT_INT64(v);
107412854Sgabeblack@google.com        and_on_help(sgn, nbits, ndigits, digit,
107512854Sgabeblack@google.com                    vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
107612854Sgabeblack@google.com        convert_2C_to_SM();
107712854Sgabeblack@google.com    }
107812854Sgabeblack@google.com    return *this;
107912854Sgabeblack@google.com}
108012854Sgabeblack@google.com
108112854Sgabeblack@google.com
108212854Sgabeblack@google.comconst CLASS_TYPE &
108312854Sgabeblack@google.comCLASS_TYPE::operator &= (long v)
108412854Sgabeblack@google.com{
108512854Sgabeblack@google.com    // u = *this
108612854Sgabeblack@google.com
108712854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (v == 0)) { // case 1
108812854Sgabeblack@google.com        makezero();
108912854Sgabeblack@google.com    } else { // other cases
109012854Sgabeblack@google.com        CONVERT_LONG(v);
109112854Sgabeblack@google.com        and_on_help(sgn, nbits, ndigits, digit,
109212854Sgabeblack@google.com                    vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
109312854Sgabeblack@google.com        convert_2C_to_SM();
109412854Sgabeblack@google.com    }
109512854Sgabeblack@google.com
109612854Sgabeblack@google.com    return *this;
109712854Sgabeblack@google.com}
109812854Sgabeblack@google.com
109912854Sgabeblack@google.com
110012854Sgabeblack@google.comconst CLASS_TYPE &
110112854Sgabeblack@google.comCLASS_TYPE::operator &= (unsigned long v)
110212854Sgabeblack@google.com{
110312854Sgabeblack@google.com    // u = *this
110412854Sgabeblack@google.com    if ((sgn == SC_ZERO) || (v == 0)) { // case 1
110512854Sgabeblack@google.com        makezero();
110612854Sgabeblack@google.com    } else { // other cases
110712854Sgabeblack@google.com        CONVERT_LONG(v);
110812854Sgabeblack@google.com        and_on_help(sgn, nbits, ndigits, digit,
110912854Sgabeblack@google.com                    vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
111012854Sgabeblack@google.com        convert_2C_to_SM();
111112854Sgabeblack@google.com    }
111212854Sgabeblack@google.com    return *this;
111312854Sgabeblack@google.com}
111412854Sgabeblack@google.com
111512854Sgabeblack@google.com
111612854Sgabeblack@google.com// ----------------------------------------------------------------------------
111712854Sgabeblack@google.com//    SECTION: Bitwise OR operators: |, |=
111812854Sgabeblack@google.com// ----------------------------------------------------------------------------
111912854Sgabeblack@google.com
112012854Sgabeblack@google.com// Cases to consider when computing u | v:
112112854Sgabeblack@google.com// 1. u | 0 = u
112212854Sgabeblack@google.com// 2. 0 | v = v
112312854Sgabeblack@google.com// 3. u | v => sgn = +
112412854Sgabeblack@google.com// 4. (-u) | (-v) => sgn = -
112512854Sgabeblack@google.com// 5. u | (-v) => sgn = -
112612854Sgabeblack@google.com// 6. (-u) | v => sgn = -
112712854Sgabeblack@google.com
112812854Sgabeblack@google.comconst CLASS_TYPE &
112912854Sgabeblack@google.comCLASS_TYPE::operator |= (const CLASS_TYPE &v)
113012854Sgabeblack@google.com{
113112854Sgabeblack@google.com    if (v.sgn == SC_ZERO) // case 1
113212854Sgabeblack@google.com        return *this;
113312854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
113412854Sgabeblack@google.com        return (*this = v);
113512854Sgabeblack@google.com    // other cases
113612854Sgabeblack@google.com    or_on_help(sgn, nbits, ndigits, digit,
113712854Sgabeblack@google.com               v.sgn, v.nbits, v.ndigits, v.digit);
113812854Sgabeblack@google.com    convert_2C_to_SM();
113912854Sgabeblack@google.com    return *this;
114012854Sgabeblack@google.com}
114112854Sgabeblack@google.com
114212854Sgabeblack@google.com
114312854Sgabeblack@google.comconst CLASS_TYPE &
114412854Sgabeblack@google.comCLASS_TYPE::operator |= (const OTHER_CLASS_TYPE &v)
114512854Sgabeblack@google.com{
114612854Sgabeblack@google.com    if (v.sgn == SC_ZERO) // case 1
114712854Sgabeblack@google.com        return *this;
114812854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
114912854Sgabeblack@google.com        return (*this = v);
115012854Sgabeblack@google.com    // other cases
115112854Sgabeblack@google.com    or_on_help(sgn, nbits, ndigits, digit,
115212854Sgabeblack@google.com               v.sgn, v.nbits, v.ndigits, v.digit);
115312854Sgabeblack@google.com    convert_2C_to_SM();
115412854Sgabeblack@google.com    return *this;
115512854Sgabeblack@google.com}
115612854Sgabeblack@google.com
115712854Sgabeblack@google.com
115812854Sgabeblack@google.comconst CLASS_TYPE&
115912854Sgabeblack@google.comCLASS_TYPE::operator |= (int64 v)
116012854Sgabeblack@google.com{
116112854Sgabeblack@google.com    if (v == 0) // case 1
116212854Sgabeblack@google.com        return *this;
116312854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
116412854Sgabeblack@google.com        return (*this = v);
116512854Sgabeblack@google.com    // other cases
116612854Sgabeblack@google.com    CONVERT_INT64(v);
116712854Sgabeblack@google.com    or_on_help(sgn, nbits, ndigits, digit,
116812854Sgabeblack@google.com               vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
116912854Sgabeblack@google.com    convert_2C_to_SM();
117012854Sgabeblack@google.com    return *this;
117112854Sgabeblack@google.com}
117212854Sgabeblack@google.com
117312854Sgabeblack@google.com
117412854Sgabeblack@google.comconst CLASS_TYPE&
117512854Sgabeblack@google.comCLASS_TYPE::operator |= (uint64 v)
117612854Sgabeblack@google.com{
117712854Sgabeblack@google.com    if (v == 0) // case 1
117812854Sgabeblack@google.com        return *this;
117912854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
118012854Sgabeblack@google.com        return (*this = v);
118112854Sgabeblack@google.com    // other cases
118212854Sgabeblack@google.com    CONVERT_INT64(v);
118312854Sgabeblack@google.com    or_on_help(sgn, nbits, ndigits, digit,
118412854Sgabeblack@google.com               vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
118512854Sgabeblack@google.com    convert_2C_to_SM();
118612854Sgabeblack@google.com    return *this;
118712854Sgabeblack@google.com}
118812854Sgabeblack@google.com
118912854Sgabeblack@google.com
119012854Sgabeblack@google.comconst CLASS_TYPE &
119112854Sgabeblack@google.comCLASS_TYPE::operator |= (long v)
119212854Sgabeblack@google.com{
119312854Sgabeblack@google.com    if (v == 0) // case 1
119412854Sgabeblack@google.com        return *this;
119512854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
119612854Sgabeblack@google.com        return (*this = v);
119712854Sgabeblack@google.com    // other cases
119812854Sgabeblack@google.com    CONVERT_LONG(v);
119912854Sgabeblack@google.com    or_on_help(sgn, nbits, ndigits, digit,
120012854Sgabeblack@google.com               vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
120112854Sgabeblack@google.com    convert_2C_to_SM();
120212854Sgabeblack@google.com    return *this;
120312854Sgabeblack@google.com}
120412854Sgabeblack@google.com
120512854Sgabeblack@google.com
120612854Sgabeblack@google.comconst CLASS_TYPE &
120712854Sgabeblack@google.comCLASS_TYPE::operator |= (unsigned long v)
120812854Sgabeblack@google.com{
120912854Sgabeblack@google.com    if (v == 0) // case 1
121012854Sgabeblack@google.com        return *this;
121112854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
121212854Sgabeblack@google.com        return (*this = v);
121312854Sgabeblack@google.com    // other cases
121412854Sgabeblack@google.com    CONVERT_LONG(v);
121512854Sgabeblack@google.com    or_on_help(sgn, nbits, ndigits, digit,
121612854Sgabeblack@google.com               vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
121712854Sgabeblack@google.com    convert_2C_to_SM();
121812854Sgabeblack@google.com    return *this;
121912854Sgabeblack@google.com}
122012854Sgabeblack@google.com
122112854Sgabeblack@google.com
122212854Sgabeblack@google.com// ----------------------------------------------------------------------------
122312854Sgabeblack@google.com//    SECTION: Bitwise XOR operators: ^, ^=
122412854Sgabeblack@google.com// ----------------------------------------------------------------------------
122512854Sgabeblack@google.com
122612854Sgabeblack@google.com// Cases to consider when computing u ^ v:
122712854Sgabeblack@google.com// Note that    u ^ v = (~u    &v) | (u & ~v).
122812854Sgabeblack@google.com// 1. u ^ 0 = u
122912854Sgabeblack@google.com// 2. 0 ^ v = v
123012854Sgabeblack@google.com// 3. u ^ v => sgn = +
123112854Sgabeblack@google.com// 4. (-u) ^ (-v) => sgn = -
123212854Sgabeblack@google.com// 5. u ^ (-v) => sgn = -
123312854Sgabeblack@google.com// 6. (-u) ^ v => sgn = +
123412854Sgabeblack@google.com
123512854Sgabeblack@google.comconst CLASS_TYPE &
123612854Sgabeblack@google.comCLASS_TYPE::operator ^= (const CLASS_TYPE &v)
123712854Sgabeblack@google.com{
123812854Sgabeblack@google.com    // u = *this
123912854Sgabeblack@google.com    if (v.sgn == SC_ZERO) // case 1
124012854Sgabeblack@google.com        return *this;
124112854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
124212854Sgabeblack@google.com        return (*this = v);
124312854Sgabeblack@google.com    // other cases
124412854Sgabeblack@google.com    xor_on_help(sgn, nbits, ndigits, digit,
124512854Sgabeblack@google.com                v.sgn, v.nbits, v.ndigits, v.digit);
124612854Sgabeblack@google.com    convert_2C_to_SM();
124712854Sgabeblack@google.com    return *this;
124812854Sgabeblack@google.com}
124912854Sgabeblack@google.com
125012854Sgabeblack@google.com
125112854Sgabeblack@google.comconst CLASS_TYPE &
125212854Sgabeblack@google.comCLASS_TYPE::operator ^= (const OTHER_CLASS_TYPE &v)
125312854Sgabeblack@google.com{
125412854Sgabeblack@google.com    // u = *this
125512854Sgabeblack@google.com    if (v.sgn == SC_ZERO) // case 1
125612854Sgabeblack@google.com        return *this;
125712854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
125812854Sgabeblack@google.com        return (*this = v);
125912854Sgabeblack@google.com    // other cases
126012854Sgabeblack@google.com    xor_on_help(sgn, nbits, ndigits, digit,
126112854Sgabeblack@google.com                v.sgn, v.nbits, v.ndigits, v.digit);
126212854Sgabeblack@google.com    convert_2C_to_SM();
126312854Sgabeblack@google.com    return *this;
126412854Sgabeblack@google.com}
126512854Sgabeblack@google.com
126612854Sgabeblack@google.com
126712854Sgabeblack@google.comconst CLASS_TYPE&
126812854Sgabeblack@google.comCLASS_TYPE::operator ^= (int64 v)
126912854Sgabeblack@google.com{
127012854Sgabeblack@google.com    if (v == 0) // case 1
127112854Sgabeblack@google.com        return *this;
127212854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
127312854Sgabeblack@google.com        return (*this = v);
127412854Sgabeblack@google.com    // other cases
127512854Sgabeblack@google.com    CONVERT_INT64(v);
127612854Sgabeblack@google.com    xor_on_help(sgn, nbits, ndigits, digit,
127712854Sgabeblack@google.com                vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
127812854Sgabeblack@google.com    convert_2C_to_SM();
127912854Sgabeblack@google.com    return *this;
128012854Sgabeblack@google.com}
128112854Sgabeblack@google.com
128212854Sgabeblack@google.com
128312854Sgabeblack@google.comconst CLASS_TYPE &
128412854Sgabeblack@google.comCLASS_TYPE::operator ^= (uint64 v)
128512854Sgabeblack@google.com{
128612854Sgabeblack@google.com    if (v == 0) // case 1
128712854Sgabeblack@google.com        return *this;
128812854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
128912854Sgabeblack@google.com        return (*this = v);
129012854Sgabeblack@google.com    // other cases
129112854Sgabeblack@google.com    CONVERT_INT64(v);
129212854Sgabeblack@google.com    xor_on_help(sgn, nbits, ndigits, digit,
129312854Sgabeblack@google.com                vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd);
129412854Sgabeblack@google.com    convert_2C_to_SM();
129512854Sgabeblack@google.com    return *this;
129612854Sgabeblack@google.com}
129712854Sgabeblack@google.com
129812854Sgabeblack@google.com
129912854Sgabeblack@google.comconst CLASS_TYPE &
130012854Sgabeblack@google.comCLASS_TYPE::operator ^= (long v)
130112854Sgabeblack@google.com{
130212854Sgabeblack@google.com    if (v == 0) // case 1
130312854Sgabeblack@google.com        return *this;
130412854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
130512854Sgabeblack@google.com        return (*this = v);
130612854Sgabeblack@google.com    // other cases
130712854Sgabeblack@google.com    CONVERT_LONG(v);
130812854Sgabeblack@google.com    xor_on_help(sgn, nbits, ndigits, digit,
130912854Sgabeblack@google.com                vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
131012854Sgabeblack@google.com    convert_2C_to_SM();
131112854Sgabeblack@google.com    return *this;
131212854Sgabeblack@google.com}
131312854Sgabeblack@google.com
131412854Sgabeblack@google.com
131512854Sgabeblack@google.comconst CLASS_TYPE &
131612854Sgabeblack@google.comCLASS_TYPE::operator ^= (unsigned long v)
131712854Sgabeblack@google.com{
131812854Sgabeblack@google.com    if (v == 0) // case 1
131912854Sgabeblack@google.com        return *this;
132012854Sgabeblack@google.com    if (sgn == SC_ZERO) // case 2
132112854Sgabeblack@google.com        return (*this = v);
132212854Sgabeblack@google.com    // other cases
132312854Sgabeblack@google.com    CONVERT_LONG(v);
132412854Sgabeblack@google.com    xor_on_help(sgn, nbits, ndigits, digit,
132512854Sgabeblack@google.com                vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd);
132612854Sgabeblack@google.com    convert_2C_to_SM();
132712854Sgabeblack@google.com    return *this;
132812854Sgabeblack@google.com}
132912854Sgabeblack@google.com
133012854Sgabeblack@google.com
133112854Sgabeblack@google.com// ----------------------------------------------------------------------------
133212854Sgabeblack@google.com//    SECTION: Bitwise NOT operator: ~
133312854Sgabeblack@google.com// ----------------------------------------------------------------------------
133412854Sgabeblack@google.com
133512854Sgabeblack@google.comCLASS_TYPE
133612854Sgabeblack@google.comoperator ~ (const CLASS_TYPE &u)
133712854Sgabeblack@google.com{
133812854Sgabeblack@google.com    small_type s = u.sgn;
133912854Sgabeblack@google.com    if (s == SC_ZERO) {
134012854Sgabeblack@google.com        sc_digit d = 1;
134112854Sgabeblack@google.com        return CLASS_TYPE(SC_NEG, u.nbits, 1, &d, false);
134212854Sgabeblack@google.com    }
134312854Sgabeblack@google.com
134412854Sgabeblack@google.com    int nd = u.ndigits;
134512854Sgabeblack@google.com
134612854Sgabeblack@google.com#ifdef SC_MAX_NBITS
134712854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS];
134812854Sgabeblack@google.com#else
134912854Sgabeblack@google.com    sc_digit *d = new sc_digit[nd];
135012854Sgabeblack@google.com#endif
135112854Sgabeblack@google.com
135212854Sgabeblack@google.com    vec_copy(nd, d, u.digit);
135312854Sgabeblack@google.com    if (s == SC_POS) {
135412854Sgabeblack@google.com        s = SC_NEG;
135512854Sgabeblack@google.com        vec_add_small_on(nd, d, 1);
135612854Sgabeblack@google.com    } else {
135712854Sgabeblack@google.com        s = SC_POS;
135812854Sgabeblack@google.com        vec_sub_small_on(nd, d, 1);
135912854Sgabeblack@google.com        if (check_for_zero(nd, d))
136012854Sgabeblack@google.com            s = SC_ZERO;
136112854Sgabeblack@google.com    }
136212854Sgabeblack@google.com    return CLASS_TYPE(s, u.nbits, nd, d);
136312854Sgabeblack@google.com}
136412854Sgabeblack@google.com
136512854Sgabeblack@google.com
136612854Sgabeblack@google.com// ----------------------------------------------------------------------------
136712854Sgabeblack@google.com//    SECTION: LEFT SHIFT operators: <<, <<=
136812854Sgabeblack@google.com// ----------------------------------------------------------------------------
136912854Sgabeblack@google.com
137012854Sgabeblack@google.comCLASS_TYPE
137112854Sgabeblack@google.comoperator << (const CLASS_TYPE &u, const CLASS_TYPE &v)
137212854Sgabeblack@google.com{
137312854Sgabeblack@google.com    if (v.sgn == SC_ZERO)
137412854Sgabeblack@google.com        return CLASS_TYPE(u);
137512854Sgabeblack@google.com#ifdef SC_SIGNED
137612854Sgabeblack@google.com    if (v.sgn == SC_NEG)
137712854Sgabeblack@google.com        return CLASS_TYPE(u);
137812854Sgabeblack@google.com#endif
137912854Sgabeblack@google.com    return operator << (u, v.to_ulong());
138012854Sgabeblack@google.com}
138112854Sgabeblack@google.com
138212854Sgabeblack@google.com
138312854Sgabeblack@google.comconst CLASS_TYPE &
138412854Sgabeblack@google.comCLASS_TYPE::operator <<= (const CLASS_TYPE &v)
138512854Sgabeblack@google.com{
138612854Sgabeblack@google.com    if (v.sgn == SC_ZERO)
138712854Sgabeblack@google.com        return *this;
138812854Sgabeblack@google.com#ifdef SC_SIGNED
138912854Sgabeblack@google.com    if (v.sgn == SC_NEG)
139012854Sgabeblack@google.com        return *this;
139112854Sgabeblack@google.com#endif
139212854Sgabeblack@google.com    return operator <<= (v.to_ulong());
139312854Sgabeblack@google.com}
139412854Sgabeblack@google.com
139512854Sgabeblack@google.com
139612854Sgabeblack@google.comconst CLASS_TYPE &
139712854Sgabeblack@google.comCLASS_TYPE::operator <<= (const OTHER_CLASS_TYPE &v)
139812854Sgabeblack@google.com{
139912854Sgabeblack@google.com    if (v.sgn == SC_ZERO)
140012854Sgabeblack@google.com        return *this;
140112854Sgabeblack@google.com#ifdef SC_UNSIGNED
140212854Sgabeblack@google.com    if (v.sgn == SC_NEG)
140312854Sgabeblack@google.com        return *this;
140412854Sgabeblack@google.com#endif
140512854Sgabeblack@google.com    return operator <<= (v.to_ulong());
140612854Sgabeblack@google.com}
140712854Sgabeblack@google.com
140812854Sgabeblack@google.com
140912854Sgabeblack@google.comCLASS_TYPE
141012854Sgabeblack@google.comoperator << (const CLASS_TYPE &u, int64 v)
141112854Sgabeblack@google.com{
141212854Sgabeblack@google.com    if (v <= 0)
141312854Sgabeblack@google.com        return CLASS_TYPE(u);
141412854Sgabeblack@google.com    return operator << (u, (unsigned long)v);
141512854Sgabeblack@google.com}
141612854Sgabeblack@google.com
141712854Sgabeblack@google.com
141812854Sgabeblack@google.comCLASS_TYPE
141912854Sgabeblack@google.comoperator << (const CLASS_TYPE &u, uint64 v)
142012854Sgabeblack@google.com{
142112854Sgabeblack@google.com    if (v == 0)
142212854Sgabeblack@google.com        return CLASS_TYPE(u);
142312854Sgabeblack@google.com    return operator << (u, (unsigned long)v);
142412854Sgabeblack@google.com}
142512854Sgabeblack@google.com
142612854Sgabeblack@google.com
142712854Sgabeblack@google.comconst CLASS_TYPE &
142812854Sgabeblack@google.comCLASS_TYPE::operator <<= (int64 v)
142912854Sgabeblack@google.com{
143012854Sgabeblack@google.com    if (v <= 0)
143112854Sgabeblack@google.com        return *this;
143212854Sgabeblack@google.com    return operator <<= ((unsigned long)v);
143312854Sgabeblack@google.com}
143412854Sgabeblack@google.com
143512854Sgabeblack@google.com
143612854Sgabeblack@google.comconst CLASS_TYPE &
143712854Sgabeblack@google.comCLASS_TYPE::operator <<= (uint64 v)
143812854Sgabeblack@google.com{
143912854Sgabeblack@google.com    if (v == 0)
144012854Sgabeblack@google.com        return *this;
144112854Sgabeblack@google.com    return operator <<= ((unsigned long)v);
144212854Sgabeblack@google.com}
144312854Sgabeblack@google.com
144412854Sgabeblack@google.com
144512854Sgabeblack@google.comCLASS_TYPE
144612854Sgabeblack@google.comoperator << (const CLASS_TYPE &u, long v)
144712854Sgabeblack@google.com{
144812854Sgabeblack@google.com    if (v <= 0)
144912854Sgabeblack@google.com        return CLASS_TYPE(u);
145012854Sgabeblack@google.com    return operator << (u, (unsigned long)v);
145112854Sgabeblack@google.com}
145212854Sgabeblack@google.com
145312854Sgabeblack@google.comCLASS_TYPE
145412854Sgabeblack@google.comoperator << (const CLASS_TYPE &u, unsigned long v)
145512854Sgabeblack@google.com{
145612854Sgabeblack@google.com    if (v == 0)
145712854Sgabeblack@google.com        return CLASS_TYPE(u);
145812854Sgabeblack@google.com    if (u.sgn == SC_ZERO)
145912854Sgabeblack@google.com        return CLASS_TYPE(u);
146012854Sgabeblack@google.com
146112854Sgabeblack@google.com    int nb = u.nbits + v;
146212854Sgabeblack@google.com    int nd = DIV_CEIL(nb);
146312854Sgabeblack@google.com
146412854Sgabeblack@google.com#ifdef SC_MAX_NBITS
146512854Sgabeblack@google.com    test_bound(nb);
146612854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS];
146712854Sgabeblack@google.com#else
146812854Sgabeblack@google.com    sc_digit *d = new sc_digit[nd];
146912854Sgabeblack@google.com#endif
147012854Sgabeblack@google.com
147112854Sgabeblack@google.com    vec_copy_and_zero(nd, d, u.ndigits, u.digit);
147212854Sgabeblack@google.com    convert_SM_to_2C(u.sgn, nd, d);
147312854Sgabeblack@google.com    vec_shift_left(nd, d, v);
147412854Sgabeblack@google.com    small_type s = convert_signed_2C_to_SM(nb, nd, d);
147512854Sgabeblack@google.com    return CLASS_TYPE(s, nb, nd, d);
147612854Sgabeblack@google.com}
147712854Sgabeblack@google.com
147812854Sgabeblack@google.com
147912854Sgabeblack@google.comconst CLASS_TYPE &
148012854Sgabeblack@google.comCLASS_TYPE::operator <<= (long v)
148112854Sgabeblack@google.com{
148212854Sgabeblack@google.com    if (v <= 0)
148312854Sgabeblack@google.com        return *this;
148412854Sgabeblack@google.com    return operator <<= ((unsigned long)v);
148512854Sgabeblack@google.com}
148612854Sgabeblack@google.com
148712854Sgabeblack@google.com
148812854Sgabeblack@google.comconst CLASS_TYPE &
148912854Sgabeblack@google.comCLASS_TYPE::operator <<= (unsigned long v)
149012854Sgabeblack@google.com{
149112854Sgabeblack@google.com    if (v == 0)
149212854Sgabeblack@google.com        return *this;
149312854Sgabeblack@google.com    if (sgn == SC_ZERO)
149412854Sgabeblack@google.com        return *this;
149512854Sgabeblack@google.com    convert_SM_to_2C();
149612854Sgabeblack@google.com    vec_shift_left(ndigits, digit, v);
149712854Sgabeblack@google.com    convert_2C_to_SM();
149812854Sgabeblack@google.com    return *this;
149912854Sgabeblack@google.com}
150012854Sgabeblack@google.com
150112854Sgabeblack@google.com
150212854Sgabeblack@google.com// ----------------------------------------------------------------------------
150312854Sgabeblack@google.com//    SECTION: RIGHT SHIFT operators: >>, >>=
150412854Sgabeblack@google.com// ----------------------------------------------------------------------------
150512854Sgabeblack@google.com
150612854Sgabeblack@google.comCLASS_TYPE
150712854Sgabeblack@google.comoperator >> (const CLASS_TYPE &u, const CLASS_TYPE &v)
150812854Sgabeblack@google.com{
150912854Sgabeblack@google.com    if (v.sgn == SC_ZERO)
151012854Sgabeblack@google.com        return CLASS_TYPE(u);
151112854Sgabeblack@google.com#ifdef SC_SIGNED
151212854Sgabeblack@google.com    if (v.sgn == SC_NEG)
151312854Sgabeblack@google.com        return CLASS_TYPE(u);
151412854Sgabeblack@google.com#endif
151512854Sgabeblack@google.com    return operator >> (u, v.to_long());
151612854Sgabeblack@google.com}
151712854Sgabeblack@google.com
151812854Sgabeblack@google.com
151912854Sgabeblack@google.comconst CLASS_TYPE &
152012854Sgabeblack@google.comCLASS_TYPE::operator >>= (const CLASS_TYPE &v)
152112854Sgabeblack@google.com{
152212854Sgabeblack@google.com    if (v.sgn == SC_ZERO)
152312854Sgabeblack@google.com        return *this;
152412854Sgabeblack@google.com#ifdef SC_SIGNED
152512854Sgabeblack@google.com    if (v.sgn == SC_NEG)
152612854Sgabeblack@google.com        return *this;
152712854Sgabeblack@google.com#endif
152812854Sgabeblack@google.com    return operator >>= (v.to_long());
152912854Sgabeblack@google.com}
153012854Sgabeblack@google.com
153112854Sgabeblack@google.com
153212854Sgabeblack@google.comconst CLASS_TYPE &
153312854Sgabeblack@google.comCLASS_TYPE::operator >>= (const OTHER_CLASS_TYPE &v)
153412854Sgabeblack@google.com{
153512854Sgabeblack@google.com    if (v.sgn == SC_ZERO)
153612854Sgabeblack@google.com        return *this;
153712854Sgabeblack@google.com#ifdef SC_UNSIGNED
153812854Sgabeblack@google.com    if (v.sgn == SC_NEG)
153912854Sgabeblack@google.com        return *this;
154012854Sgabeblack@google.com#endif
154112854Sgabeblack@google.com    return operator >>= (v.to_ulong());
154212854Sgabeblack@google.com}
154312854Sgabeblack@google.com
154412854Sgabeblack@google.com
154512854Sgabeblack@google.comCLASS_TYPE
154612854Sgabeblack@google.comoperator >> (const CLASS_TYPE &u, int64 v)
154712854Sgabeblack@google.com{
154812854Sgabeblack@google.com    if (v <= 0)
154912854Sgabeblack@google.com        return CLASS_TYPE(u);
155012854Sgabeblack@google.com    return operator >> (u, (unsigned long)v);
155112854Sgabeblack@google.com}
155212854Sgabeblack@google.com
155312854Sgabeblack@google.com
155412854Sgabeblack@google.comCLASS_TYPE
155512854Sgabeblack@google.comoperator >> (const CLASS_TYPE &u, uint64 v)
155612854Sgabeblack@google.com{
155712854Sgabeblack@google.com    if (v == 0)
155812854Sgabeblack@google.com        return CLASS_TYPE(u);
155912854Sgabeblack@google.com    return operator >> (u, (unsigned long)v);
156012854Sgabeblack@google.com}
156112854Sgabeblack@google.com
156212854Sgabeblack@google.comconst CLASS_TYPE &
156312854Sgabeblack@google.comCLASS_TYPE::operator >>= (int64 v)
156412854Sgabeblack@google.com{
156512854Sgabeblack@google.com    if (v <= 0)
156612854Sgabeblack@google.com        return *this;
156712854Sgabeblack@google.com    return operator >>= ((unsigned long)v);
156812854Sgabeblack@google.com}
156912854Sgabeblack@google.com
157012854Sgabeblack@google.com
157112854Sgabeblack@google.comconst CLASS_TYPE &
157212854Sgabeblack@google.comCLASS_TYPE::operator >>= (uint64 v)
157312854Sgabeblack@google.com{
157412854Sgabeblack@google.com    if (v == 0)
157512854Sgabeblack@google.com        return *this;
157612854Sgabeblack@google.com    return operator >>= ((unsigned long)v);
157712854Sgabeblack@google.com}
157812854Sgabeblack@google.com
157912854Sgabeblack@google.com
158012854Sgabeblack@google.comCLASS_TYPE
158112854Sgabeblack@google.comoperator >> (const CLASS_TYPE &u, long v)
158212854Sgabeblack@google.com{
158312854Sgabeblack@google.com    if (v <= 0)
158412854Sgabeblack@google.com        return CLASS_TYPE(u);
158512854Sgabeblack@google.com    return operator >> (u, (unsigned long)v);
158612854Sgabeblack@google.com}
158712854Sgabeblack@google.com
158812854Sgabeblack@google.com
158912854Sgabeblack@google.comCLASS_TYPE
159012854Sgabeblack@google.comoperator >> (const CLASS_TYPE &u, unsigned long v)
159112854Sgabeblack@google.com{
159212854Sgabeblack@google.com    if (v == 0)
159312854Sgabeblack@google.com        return CLASS_TYPE(u);
159412854Sgabeblack@google.com    if (u.sgn == SC_ZERO)
159512854Sgabeblack@google.com        return CLASS_TYPE(u);
159612854Sgabeblack@google.com
159712854Sgabeblack@google.com    int nb = u.nbits;
159812854Sgabeblack@google.com    int nd = u.ndigits;
159912854Sgabeblack@google.com
160012854Sgabeblack@google.com#ifdef SC_MAX_NBITS
160112854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS];
160212854Sgabeblack@google.com#else
160312854Sgabeblack@google.com    sc_digit *d = new sc_digit[nd];
160412854Sgabeblack@google.com#endif
160512854Sgabeblack@google.com
160612854Sgabeblack@google.com    vec_copy(nd, d, u.digit);
160712854Sgabeblack@google.com    convert_SM_to_2C(u.sgn, nd, d);
160812854Sgabeblack@google.com    if (u.sgn == SC_NEG)
160912854Sgabeblack@google.com        vec_shift_right(nd, d, v, DIGIT_MASK);
161012854Sgabeblack@google.com    else
161112854Sgabeblack@google.com        vec_shift_right(nd, d, v, 0);
161212854Sgabeblack@google.com    small_type s = convert_signed_2C_to_SM(nb, nd, d);
161312854Sgabeblack@google.com    return CLASS_TYPE(s, nb, nd, d);
161412854Sgabeblack@google.com}
161512854Sgabeblack@google.com
161612854Sgabeblack@google.com
161712854Sgabeblack@google.comconst CLASS_TYPE &
161812854Sgabeblack@google.comCLASS_TYPE::operator >>= (long v)
161912854Sgabeblack@google.com{
162012854Sgabeblack@google.com    if (v <= 0)
162112854Sgabeblack@google.com        return *this;
162212854Sgabeblack@google.com    return operator >>= ((unsigned long)v);
162312854Sgabeblack@google.com}
162412854Sgabeblack@google.com
162512854Sgabeblack@google.com
162612854Sgabeblack@google.comconst CLASS_TYPE &
162712854Sgabeblack@google.comCLASS_TYPE::operator >>= (unsigned long v)
162812854Sgabeblack@google.com{
162912854Sgabeblack@google.com    if (v == 0)
163012854Sgabeblack@google.com        return *this;
163112854Sgabeblack@google.com    if (sgn == SC_ZERO)
163212854Sgabeblack@google.com        return *this;
163312854Sgabeblack@google.com
163412854Sgabeblack@google.com    convert_SM_to_2C();
163512854Sgabeblack@google.com
163612854Sgabeblack@google.com    if (sgn == SC_NEG)
163712854Sgabeblack@google.com        vec_shift_right(ndigits, digit, v, DIGIT_MASK);
163812854Sgabeblack@google.com    else
163912854Sgabeblack@google.com        vec_shift_right(ndigits, digit, v, 0);
164012854Sgabeblack@google.com    convert_2C_to_SM();
164112854Sgabeblack@google.com    return *this;
164212854Sgabeblack@google.com}
164312854Sgabeblack@google.com
164412854Sgabeblack@google.com
164512854Sgabeblack@google.com// ----------------------------------------------------------------------------
164612854Sgabeblack@google.com//    SECTION: EQUAL TO operator: ==
164712854Sgabeblack@google.com// ----------------------------------------------------------------------------
164812854Sgabeblack@google.com
164912854Sgabeblack@google.com// Defined in the sc_signed.cpp and sc_unsigned.cpp.
165012854Sgabeblack@google.com
165112854Sgabeblack@google.com
165212854Sgabeblack@google.com// ----------------------------------------------------------------------------
165312854Sgabeblack@google.com//    SECTION: NOT_EQUAL operator: !=
165412854Sgabeblack@google.com// ----------------------------------------------------------------------------
165512854Sgabeblack@google.com
165612854Sgabeblack@google.combool
165712854Sgabeblack@google.comoperator != (const CLASS_TYPE &u, const CLASS_TYPE &v)
165812854Sgabeblack@google.com{
165912854Sgabeblack@google.com    return (!operator == (u, v));
166012854Sgabeblack@google.com}
166112854Sgabeblack@google.com
166212854Sgabeblack@google.com
166312854Sgabeblack@google.combool
166412854Sgabeblack@google.comoperator != (const CLASS_TYPE &u, int64 v)
166512854Sgabeblack@google.com{
166612854Sgabeblack@google.com    return (!operator == (u, v));
166712854Sgabeblack@google.com}
166812854Sgabeblack@google.com
166912854Sgabeblack@google.com
167012854Sgabeblack@google.combool
167112854Sgabeblack@google.comoperator != (int64 u, const CLASS_TYPE &v)
167212854Sgabeblack@google.com{
167312854Sgabeblack@google.com    return (!operator == (u, v));
167412854Sgabeblack@google.com}
167512854Sgabeblack@google.com
167612854Sgabeblack@google.com
167712854Sgabeblack@google.combool
167812854Sgabeblack@google.comoperator != (const CLASS_TYPE &u, uint64 v)
167912854Sgabeblack@google.com{
168012854Sgabeblack@google.com    return (!operator == (u, v));
168112854Sgabeblack@google.com}
168212854Sgabeblack@google.com
168312854Sgabeblack@google.com
168412854Sgabeblack@google.combool
168512854Sgabeblack@google.comoperator != (uint64 u, const CLASS_TYPE &v)
168612854Sgabeblack@google.com{
168712854Sgabeblack@google.com    return (!operator == (u, v));
168812854Sgabeblack@google.com}
168912854Sgabeblack@google.com
169012854Sgabeblack@google.com
169112854Sgabeblack@google.combool
169212854Sgabeblack@google.comoperator != (const CLASS_TYPE &u, long v)
169312854Sgabeblack@google.com{
169412854Sgabeblack@google.com    return (!operator == (u, v));
169512854Sgabeblack@google.com}
169612854Sgabeblack@google.com
169712854Sgabeblack@google.com
169812854Sgabeblack@google.combool
169912854Sgabeblack@google.comoperator != (long u, const CLASS_TYPE &v)
170012854Sgabeblack@google.com{
170112854Sgabeblack@google.com    return (!operator == (u, v));
170212854Sgabeblack@google.com}
170312854Sgabeblack@google.com
170412854Sgabeblack@google.com
170512854Sgabeblack@google.combool
170612854Sgabeblack@google.comoperator != (const CLASS_TYPE &u, unsigned long v)
170712854Sgabeblack@google.com{
170812854Sgabeblack@google.com    return (!operator == (u, v));
170912854Sgabeblack@google.com}
171012854Sgabeblack@google.com
171112854Sgabeblack@google.com
171212854Sgabeblack@google.combool
171312854Sgabeblack@google.comoperator != (unsigned long u, const CLASS_TYPE &v)
171412854Sgabeblack@google.com{
171512854Sgabeblack@google.com    return (!operator == (u, v));
171612854Sgabeblack@google.com}
171712854Sgabeblack@google.com
171812854Sgabeblack@google.com
171912854Sgabeblack@google.com// ----------------------------------------------------------------------------
172012854Sgabeblack@google.com//    SECTION: LESS THAN operator: <
172112854Sgabeblack@google.com// ----------------------------------------------------------------------------
172212854Sgabeblack@google.com
172312854Sgabeblack@google.com// Defined in the sc_signed.cpp and sc_unsigned.cpp.
172412854Sgabeblack@google.com
172512854Sgabeblack@google.com
172612854Sgabeblack@google.com// ----------------------------------------------------------------------------
172712854Sgabeblack@google.com//    SECTION: LESS THAN or EQUAL operator: <=
172812854Sgabeblack@google.com// ----------------------------------------------------------------------------
172912854Sgabeblack@google.com
173012854Sgabeblack@google.combool
173112854Sgabeblack@google.comoperator <= (const CLASS_TYPE &u, const CLASS_TYPE &v)
173212854Sgabeblack@google.com{
173312854Sgabeblack@google.com    return (operator < (u, v) || operator == (u, v));
173412854Sgabeblack@google.com}
173512854Sgabeblack@google.com
173612854Sgabeblack@google.com
173712854Sgabeblack@google.combool
173812854Sgabeblack@google.comoperator <= (const CLASS_TYPE &u, int64 v)
173912854Sgabeblack@google.com{
174012854Sgabeblack@google.com    return (operator < (u, v) || operator == (u, v));
174112854Sgabeblack@google.com}
174212854Sgabeblack@google.com
174312854Sgabeblack@google.com
174412854Sgabeblack@google.combool
174512854Sgabeblack@google.comoperator <= (int64 u, const CLASS_TYPE &v)
174612854Sgabeblack@google.com{
174712854Sgabeblack@google.com    return (operator < (u, v) || operator == (u, v));
174812854Sgabeblack@google.com}
174912854Sgabeblack@google.com
175012854Sgabeblack@google.com
175112854Sgabeblack@google.combool
175212854Sgabeblack@google.comoperator <= (const CLASS_TYPE &u, uint64 v)
175312854Sgabeblack@google.com{
175412854Sgabeblack@google.com    return (operator < (u, v) || operator == (u, v));
175512854Sgabeblack@google.com}
175612854Sgabeblack@google.com
175712854Sgabeblack@google.com
175812854Sgabeblack@google.combool
175912854Sgabeblack@google.comoperator <= (uint64 u, const CLASS_TYPE &v)
176012854Sgabeblack@google.com{
176112854Sgabeblack@google.com    return (operator < (u, v) || operator == (u, v));
176212854Sgabeblack@google.com}
176312854Sgabeblack@google.com
176412854Sgabeblack@google.com
176512854Sgabeblack@google.combool
176612854Sgabeblack@google.comoperator <= (const CLASS_TYPE &u, long v)
176712854Sgabeblack@google.com{
176812854Sgabeblack@google.com    return (operator < (u, v) || operator == (u, v));
176912854Sgabeblack@google.com}
177012854Sgabeblack@google.com
177112854Sgabeblack@google.com
177212854Sgabeblack@google.combool
177312854Sgabeblack@google.comoperator <= (long u, const CLASS_TYPE &v)
177412854Sgabeblack@google.com{
177512854Sgabeblack@google.com    return (operator < (u, v) || operator == (u, v));
177612854Sgabeblack@google.com}
177712854Sgabeblack@google.com
177812854Sgabeblack@google.com
177912854Sgabeblack@google.combool
178012854Sgabeblack@google.comoperator <= (const CLASS_TYPE &u, unsigned long v)
178112854Sgabeblack@google.com{
178212854Sgabeblack@google.com    return (operator < (u, v) || operator == (u, v));
178312854Sgabeblack@google.com}
178412854Sgabeblack@google.com
178512854Sgabeblack@google.com
178612854Sgabeblack@google.combool
178712854Sgabeblack@google.comoperator <= (unsigned long u, const CLASS_TYPE &v)
178812854Sgabeblack@google.com{
178912854Sgabeblack@google.com    return (operator < (u, v) || operator == (u, v));
179012854Sgabeblack@google.com}
179112854Sgabeblack@google.com
179212854Sgabeblack@google.com
179312854Sgabeblack@google.com// ----------------------------------------------------------------------------
179412854Sgabeblack@google.com//    SECTION: GREATER THAN operator: >
179512854Sgabeblack@google.com// ----------------------------------------------------------------------------
179612854Sgabeblack@google.com
179712854Sgabeblack@google.combool
179812854Sgabeblack@google.comoperator > (const CLASS_TYPE &u, const CLASS_TYPE &v)
179912854Sgabeblack@google.com{
180012854Sgabeblack@google.com    return (!(operator <= (u, v)));
180112854Sgabeblack@google.com}
180212854Sgabeblack@google.com
180312854Sgabeblack@google.com
180412854Sgabeblack@google.combool
180512854Sgabeblack@google.comoperator > (const CLASS_TYPE &u, int64 v)
180612854Sgabeblack@google.com{
180712854Sgabeblack@google.com    return (!(operator <= (u, v)));
180812854Sgabeblack@google.com}
180912854Sgabeblack@google.com
181012854Sgabeblack@google.com
181112854Sgabeblack@google.combool
181212854Sgabeblack@google.comoperator > (int64 u, const CLASS_TYPE &v)
181312854Sgabeblack@google.com{
181412854Sgabeblack@google.com    return (!(operator <= (u, v)));
181512854Sgabeblack@google.com}
181612854Sgabeblack@google.com
181712854Sgabeblack@google.com
181812854Sgabeblack@google.combool
181912854Sgabeblack@google.comoperator > (const CLASS_TYPE &u, uint64 v)
182012854Sgabeblack@google.com{
182112854Sgabeblack@google.com    return (!(operator <= (u, v)));
182212854Sgabeblack@google.com}
182312854Sgabeblack@google.com
182412854Sgabeblack@google.com
182512854Sgabeblack@google.combool
182612854Sgabeblack@google.comoperator > (uint64 u, const CLASS_TYPE &v)
182712854Sgabeblack@google.com{
182812854Sgabeblack@google.com    return (!(operator <= (u, v)));
182912854Sgabeblack@google.com}
183012854Sgabeblack@google.com
183112854Sgabeblack@google.com
183212854Sgabeblack@google.combool
183312854Sgabeblack@google.comoperator > (const CLASS_TYPE &u, long v)
183412854Sgabeblack@google.com{
183512854Sgabeblack@google.com    return (!(operator <= (u, v)));
183612854Sgabeblack@google.com}
183712854Sgabeblack@google.com
183812854Sgabeblack@google.com
183912854Sgabeblack@google.combool
184012854Sgabeblack@google.comoperator > (long u, const CLASS_TYPE &v)
184112854Sgabeblack@google.com{
184212854Sgabeblack@google.com    return (!(operator <= (u, v)));
184312854Sgabeblack@google.com}
184412854Sgabeblack@google.com
184512854Sgabeblack@google.com
184612854Sgabeblack@google.combool
184712854Sgabeblack@google.comoperator > (const CLASS_TYPE &u, unsigned long v)
184812854Sgabeblack@google.com{
184912854Sgabeblack@google.com    return (!(operator <= (u, v)));
185012854Sgabeblack@google.com}
185112854Sgabeblack@google.com
185212854Sgabeblack@google.com
185312854Sgabeblack@google.combool
185412854Sgabeblack@google.comoperator > (unsigned long u, const CLASS_TYPE &v)
185512854Sgabeblack@google.com{
185612854Sgabeblack@google.com    return (!(operator <= (u, v)));
185712854Sgabeblack@google.com}
185812854Sgabeblack@google.com
185912854Sgabeblack@google.com
186012854Sgabeblack@google.com// ----------------------------------------------------------------------------
186112854Sgabeblack@google.com//    SECTION: GREATER THAN or EQUAL operator: >=
186212854Sgabeblack@google.com// ----------------------------------------------------------------------------
186312854Sgabeblack@google.com
186412854Sgabeblack@google.combool
186512854Sgabeblack@google.comoperator >= (const CLASS_TYPE &u, const CLASS_TYPE &v)
186612854Sgabeblack@google.com{
186712854Sgabeblack@google.com    return (!(operator < (u, v)));
186812854Sgabeblack@google.com}
186912854Sgabeblack@google.com
187012854Sgabeblack@google.com
187112854Sgabeblack@google.combool
187212854Sgabeblack@google.comoperator >= (const CLASS_TYPE &u, int64 v)
187312854Sgabeblack@google.com{
187412854Sgabeblack@google.com    return (!(operator < (u, v)));
187512854Sgabeblack@google.com}
187612854Sgabeblack@google.com
187712854Sgabeblack@google.com
187812854Sgabeblack@google.combool
187912854Sgabeblack@google.comoperator >= (int64 u, const CLASS_TYPE &v)
188012854Sgabeblack@google.com{
188112854Sgabeblack@google.com    return (!(operator < (u, v)));
188212854Sgabeblack@google.com}
188312854Sgabeblack@google.com
188412854Sgabeblack@google.com
188512854Sgabeblack@google.combool
188612854Sgabeblack@google.comoperator >= (const CLASS_TYPE &u, uint64 v)
188712854Sgabeblack@google.com{
188812854Sgabeblack@google.com    return (!(operator < (u, v)));
188912854Sgabeblack@google.com}
189012854Sgabeblack@google.com
189112854Sgabeblack@google.com
189212854Sgabeblack@google.combool
189312854Sgabeblack@google.comoperator >= (uint64 u, const CLASS_TYPE &v)
189412854Sgabeblack@google.com{
189512854Sgabeblack@google.com    return (!(operator < (u, v)));
189612854Sgabeblack@google.com}
189712854Sgabeblack@google.com
189812854Sgabeblack@google.com
189912854Sgabeblack@google.combool
190012854Sgabeblack@google.comoperator >= (const CLASS_TYPE &u, long v)
190112854Sgabeblack@google.com{
190212854Sgabeblack@google.com    return (!(operator < (u, v)));
190312854Sgabeblack@google.com}
190412854Sgabeblack@google.com
190512854Sgabeblack@google.com
190612854Sgabeblack@google.combool
190712854Sgabeblack@google.comoperator >= (long u, const CLASS_TYPE &v)
190812854Sgabeblack@google.com{
190912854Sgabeblack@google.com    return (!(operator < (u, v)));
191012854Sgabeblack@google.com}
191112854Sgabeblack@google.com
191212854Sgabeblack@google.com
191312854Sgabeblack@google.combool
191412854Sgabeblack@google.comoperator >= (const CLASS_TYPE &u, unsigned long v)
191512854Sgabeblack@google.com{
191612854Sgabeblack@google.com    return (!(operator < (u, v)));
191712854Sgabeblack@google.com}
191812854Sgabeblack@google.com
191912854Sgabeblack@google.com
192012854Sgabeblack@google.combool
192112854Sgabeblack@google.comoperator >= (unsigned long u, const CLASS_TYPE &v)
192212854Sgabeblack@google.com{
192312854Sgabeblack@google.com    return (!(operator < (u, v)));
192412854Sgabeblack@google.com}
192512854Sgabeblack@google.com
192612854Sgabeblack@google.com
192712854Sgabeblack@google.com// ----------------------------------------------------------------------------
192812854Sgabeblack@google.com//    SECTION: Public members - Other utils.
192912854Sgabeblack@google.com// ----------------------------------------------------------------------------
193012854Sgabeblack@google.com
193112854Sgabeblack@google.com// Convert to int64, long, or int.
193212854Sgabeblack@google.com#define TO_INTX(RET_TYPE, UP_RET_TYPE) \
193312854Sgabeblack@google.comif (sgn == SC_ZERO) \
193412854Sgabeblack@google.com    return 0; \
193512854Sgabeblack@google.comint vnd = sc_min((int)DIGITS_PER_ ## UP_RET_TYPE, ndigits); \
193612854Sgabeblack@google.comRET_TYPE v = 0; \
193712854Sgabeblack@google.comwhile (--vnd >= 0) \
193812854Sgabeblack@google.com    v = (v << BITS_PER_DIGIT) + digit[vnd]; \
193912854Sgabeblack@google.comif (sgn == SC_NEG) \
194012854Sgabeblack@google.com    return -v; \
194112854Sgabeblack@google.comelse \
194212854Sgabeblack@google.com    return v;
194312854Sgabeblack@google.com
194412854Sgabeblack@google.com
194512854Sgabeblack@google.comint64
194612854Sgabeblack@google.comCLASS_TYPE::to_int64() const
194712854Sgabeblack@google.com{
194812854Sgabeblack@google.com    TO_INTX(int64, INT64);
194912854Sgabeblack@google.com}
195012854Sgabeblack@google.com
195112854Sgabeblack@google.com
195212854Sgabeblack@google.comlong
195312854Sgabeblack@google.comCLASS_TYPE::to_long() const
195412854Sgabeblack@google.com{
195512854Sgabeblack@google.com    TO_INTX(long, LONG);
195612854Sgabeblack@google.com}
195712854Sgabeblack@google.com
195812854Sgabeblack@google.com
195912854Sgabeblack@google.comint
196012854Sgabeblack@google.comCLASS_TYPE::to_int() const
196112854Sgabeblack@google.com{
196212854Sgabeblack@google.com    TO_INTX(int, INT);
196312854Sgabeblack@google.com}
196412854Sgabeblack@google.com
196512854Sgabeblack@google.com
196612854Sgabeblack@google.com// Convert to unsigned int64, unsigned long or unsigned
196712854Sgabeblack@google.com// int. to_uint64, to_ulong, and to_uint have the same body except for
196812854Sgabeblack@google.com// the type of v defined inside.
196912854Sgabeblack@google.comuint64
197012854Sgabeblack@google.comCLASS_TYPE::to_uint64() const
197112854Sgabeblack@google.com{
197212854Sgabeblack@google.com    if (sgn == SC_ZERO)
197312854Sgabeblack@google.com        return 0;
197412854Sgabeblack@google.com
197512854Sgabeblack@google.com    int vnd = sc_min((int)DIGITS_PER_INT64, ndigits);
197612854Sgabeblack@google.com
197712854Sgabeblack@google.com    uint64 v = 0;
197812854Sgabeblack@google.com
197912854Sgabeblack@google.com    if (sgn == SC_NEG) {
198012854Sgabeblack@google.com#ifdef SC_MAX_NBITS
198112854Sgabeblack@google.com        sc_digit d[MAX_NDIGITS];
198212854Sgabeblack@google.com#else
198312854Sgabeblack@google.com        sc_digit *d = new sc_digit[ndigits];
198412854Sgabeblack@google.com#endif
198512854Sgabeblack@google.com        vec_copy(ndigits, d, digit);
198612854Sgabeblack@google.com        convert_SM_to_2C_trimmed(IF_SC_SIGNED, sgn, nbits, ndigits, d);
198712854Sgabeblack@google.com        while (--vnd >= 0)
198812854Sgabeblack@google.com            v = (v << BITS_PER_DIGIT) + d[vnd];
198912854Sgabeblack@google.com#ifndef SC_MAX_NBITS
199012854Sgabeblack@google.com        delete [] d;
199112854Sgabeblack@google.com#endif
199212854Sgabeblack@google.com    } else {
199312854Sgabeblack@google.com        while (--vnd >= 0)
199412854Sgabeblack@google.com            v = (v << BITS_PER_DIGIT) + digit[vnd];
199512854Sgabeblack@google.com    }
199612854Sgabeblack@google.com    return v;
199712854Sgabeblack@google.com}
199812854Sgabeblack@google.com
199912854Sgabeblack@google.com
200012854Sgabeblack@google.comunsigned long
200112854Sgabeblack@google.comCLASS_TYPE::to_ulong() const
200212854Sgabeblack@google.com{
200312854Sgabeblack@google.com    if (sgn == SC_ZERO)
200412854Sgabeblack@google.com        return 0;
200512854Sgabeblack@google.com
200612854Sgabeblack@google.com    int vnd = sc_min((int)DIGITS_PER_LONG, ndigits);
200712854Sgabeblack@google.com    unsigned long v = 0;
200812854Sgabeblack@google.com
200912854Sgabeblack@google.com    if (sgn == SC_NEG) {
201012854Sgabeblack@google.com#ifdef SC_MAX_NBITS
201112854Sgabeblack@google.com        sc_digit d[MAX_NDIGITS];
201212854Sgabeblack@google.com#else
201312854Sgabeblack@google.com        sc_digit *d = new sc_digit[ndigits];
201412854Sgabeblack@google.com#endif
201512854Sgabeblack@google.com        vec_copy(ndigits, d, digit);
201612854Sgabeblack@google.com        convert_SM_to_2C_trimmed(IF_SC_SIGNED, sgn, nbits, ndigits, d);
201712854Sgabeblack@google.com        while (--vnd >= 0)
201812854Sgabeblack@google.com            v = (v << BITS_PER_DIGIT) + d[vnd];
201912854Sgabeblack@google.com#ifndef SC_MAX_NBITS
202012854Sgabeblack@google.com        delete [] d;
202112854Sgabeblack@google.com#endif
202212854Sgabeblack@google.com    } else {
202312854Sgabeblack@google.com        while (--vnd >= 0)
202412854Sgabeblack@google.com            v = (v << BITS_PER_DIGIT) + digit[vnd];
202512854Sgabeblack@google.com    }
202612854Sgabeblack@google.com    return v;
202712854Sgabeblack@google.com}
202812854Sgabeblack@google.com
202912854Sgabeblack@google.com
203012854Sgabeblack@google.comunsigned int
203112854Sgabeblack@google.comCLASS_TYPE::to_uint() const
203212854Sgabeblack@google.com{
203312854Sgabeblack@google.com    if (sgn == SC_ZERO)
203412854Sgabeblack@google.com        return 0;
203512854Sgabeblack@google.com
203612854Sgabeblack@google.com    int vnd = sc_min((int)DIGITS_PER_INT, ndigits);
203712854Sgabeblack@google.com    unsigned int v = 0;
203812854Sgabeblack@google.com    if (sgn == SC_NEG) {
203912854Sgabeblack@google.com#ifdef SC_MAX_NBITS
204012854Sgabeblack@google.com        sc_digit d[MAX_NDIGITS];
204112854Sgabeblack@google.com#else
204212854Sgabeblack@google.com        sc_digit *d = new sc_digit[ndigits];
204312854Sgabeblack@google.com#endif
204412854Sgabeblack@google.com        vec_copy(ndigits, d, digit);
204512854Sgabeblack@google.com        convert_SM_to_2C_trimmed(IF_SC_SIGNED, sgn, nbits, ndigits, d);
204612854Sgabeblack@google.com        while (--vnd >= 0)
204712854Sgabeblack@google.com            v = (v << BITS_PER_DIGIT) + d[vnd];
204812854Sgabeblack@google.com#ifndef SC_MAX_NBITS
204912854Sgabeblack@google.com        delete [] d;
205012854Sgabeblack@google.com#endif
205112854Sgabeblack@google.com    } else {
205212854Sgabeblack@google.com        while (--vnd >= 0)
205312854Sgabeblack@google.com            v = (v << BITS_PER_DIGIT) + digit[vnd];
205412854Sgabeblack@google.com    }
205512854Sgabeblack@google.com    return v;
205612854Sgabeblack@google.com}
205712854Sgabeblack@google.com
205812854Sgabeblack@google.com
205912854Sgabeblack@google.com// Convert to double.
206012854Sgabeblack@google.comdouble
206112854Sgabeblack@google.comCLASS_TYPE::to_double() const
206212854Sgabeblack@google.com{
206312854Sgabeblack@google.com    if (sgn == SC_ZERO)
206412854Sgabeblack@google.com        return (double) 0.0;
206512854Sgabeblack@google.com
206612854Sgabeblack@google.com    int vnd = ndigits;
206712854Sgabeblack@google.com    double v = 0.0;
206812854Sgabeblack@google.com    while (--vnd >= 0)
206912854Sgabeblack@google.com        v = v * DIGIT_RADIX + digit[vnd];
207012854Sgabeblack@google.com    if (sgn == SC_NEG)
207112854Sgabeblack@google.com        return -v;
207212854Sgabeblack@google.com    else
207312854Sgabeblack@google.com        return v;
207412854Sgabeblack@google.com}
207512854Sgabeblack@google.com
207612854Sgabeblack@google.com
207712854Sgabeblack@google.com// Return true if the bit i is 1, false otherwise. If i is outside the
207812854Sgabeblack@google.com// bounds, return 1/0 according to the sign of the number by assuming
207912854Sgabeblack@google.com// that the number has infinite length.
208012854Sgabeblack@google.com
208112854Sgabeblack@google.combool
208212854Sgabeblack@google.comCLASS_TYPE::test(int i) const
208312854Sgabeblack@google.com{
208412854Sgabeblack@google.com#ifdef SC_SIGNED
208512854Sgabeblack@google.com    if (check_if_outside(i)) {
208612854Sgabeblack@google.com        if (sgn == SC_NEG)
208712854Sgabeblack@google.com            return 1;
208812854Sgabeblack@google.com        else
208912854Sgabeblack@google.com            return 0;
209012854Sgabeblack@google.com    }
209112854Sgabeblack@google.com#else
209212854Sgabeblack@google.com    if (check_if_outside(i))
209312854Sgabeblack@google.com        return 0;
209412854Sgabeblack@google.com#endif
209512854Sgabeblack@google.com
209612854Sgabeblack@google.com    int bit_num = bit_ord(i);
209712854Sgabeblack@google.com    int digit_num = digit_ord(i);
209812854Sgabeblack@google.com
209912854Sgabeblack@google.com    if (sgn == SC_NEG) {
210012854Sgabeblack@google.com#ifdef SC_MAX_NBITS
210112854Sgabeblack@google.com        sc_digit d[MAX_NDIGITS];
210212854Sgabeblack@google.com#else
210312854Sgabeblack@google.com        sc_digit *d = new sc_digit[ndigits];
210412854Sgabeblack@google.com#endif
210512854Sgabeblack@google.com        vec_copy(ndigits, d, digit);
210612854Sgabeblack@google.com        vec_complement(ndigits, d);
210712854Sgabeblack@google.com        bool val = ((d[digit_num] & one_and_zeros(bit_num)) != 0);
210812854Sgabeblack@google.com#ifndef SC_MAX_NBITS
210912854Sgabeblack@google.com        delete [] d;
211012854Sgabeblack@google.com#endif
211112854Sgabeblack@google.com        return val;
211212854Sgabeblack@google.com    } else {
211312854Sgabeblack@google.com        return ((digit[digit_num] & one_and_zeros(bit_num)) != 0);
211412854Sgabeblack@google.com    }
211512854Sgabeblack@google.com}
211612854Sgabeblack@google.com
211712854Sgabeblack@google.com
211812854Sgabeblack@google.com// Set the ith bit with 1.
211912854Sgabeblack@google.comvoid
212012854Sgabeblack@google.comCLASS_TYPE::set(int i)
212112854Sgabeblack@google.com{
212212854Sgabeblack@google.com    if (check_if_outside(i))
212312854Sgabeblack@google.com        return;
212412854Sgabeblack@google.com
212512854Sgabeblack@google.com    int bit_num = bit_ord(i);
212612854Sgabeblack@google.com    int digit_num = digit_ord(i);
212712854Sgabeblack@google.com
212812854Sgabeblack@google.com    convert_SM_to_2C();
212912854Sgabeblack@google.com    digit[digit_num] |= one_and_zeros(bit_num);
213012854Sgabeblack@google.com    digit[digit_num] &= DIGIT_MASK; // Needed to zero the overflow bits.
213112854Sgabeblack@google.com    convert_2C_to_SM();
213212854Sgabeblack@google.com}
213312854Sgabeblack@google.com
213412854Sgabeblack@google.com
213512854Sgabeblack@google.com// Set the ith bit with 0, i.e., clear the ith bit.
213612854Sgabeblack@google.comvoid
213712854Sgabeblack@google.comCLASS_TYPE::clear(int i)
213812854Sgabeblack@google.com{
213912854Sgabeblack@google.com    if (check_if_outside(i))
214012854Sgabeblack@google.com        return;
214112854Sgabeblack@google.com
214212854Sgabeblack@google.com    int bit_num = bit_ord(i);
214312854Sgabeblack@google.com    int digit_num = digit_ord(i);
214412854Sgabeblack@google.com
214512854Sgabeblack@google.com    convert_SM_to_2C();
214612854Sgabeblack@google.com    digit[digit_num] &= ~(one_and_zeros(bit_num));
214712854Sgabeblack@google.com    digit[digit_num] &= DIGIT_MASK; // Needed to zero the overflow bits.
214812854Sgabeblack@google.com    convert_2C_to_SM();
214912854Sgabeblack@google.com}
215012854Sgabeblack@google.com
215112854Sgabeblack@google.com
215212854Sgabeblack@google.com// Create a mirror image of the number.
215312854Sgabeblack@google.comvoid
215412854Sgabeblack@google.comCLASS_TYPE::reverse()
215512854Sgabeblack@google.com{
215612854Sgabeblack@google.com    convert_SM_to_2C();
215712854Sgabeblack@google.com    vec_reverse(length(), ndigits, digit, length() - 1);
215812854Sgabeblack@google.com    convert_2C_to_SM();
215912854Sgabeblack@google.com}
216012854Sgabeblack@google.com
216112854Sgabeblack@google.com
216212854Sgabeblack@google.com// Get a packed bit representation of the number.
216312854Sgabeblack@google.comvoid
216412854Sgabeblack@google.comCLASS_TYPE::get_packed_rep(sc_digit *buf) const
216512854Sgabeblack@google.com{
216612854Sgabeblack@google.com    int buf_ndigits = (length() - 1) / BITS_PER_DIGIT_TYPE + 1;
216712854Sgabeblack@google.com    // Initialize buf to zero.
216812854Sgabeblack@google.com    vec_zero(buf_ndigits, buf);
216912854Sgabeblack@google.com
217012854Sgabeblack@google.com    if (sgn == SC_ZERO)
217112854Sgabeblack@google.com        return;
217212854Sgabeblack@google.com
217312854Sgabeblack@google.com    const sc_digit *digit_or_d;
217412854Sgabeblack@google.com#ifdef SC_MAX_NBITS
217512854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS];
217612854Sgabeblack@google.com#else
217712854Sgabeblack@google.com    sc_digit *d = new sc_digit[ndigits];
217812854Sgabeblack@google.com#endif
217912854Sgabeblack@google.com
218012854Sgabeblack@google.com    if (sgn == SC_POS) {
218112854Sgabeblack@google.com        digit_or_d = digit;
218212854Sgabeblack@google.com    } else {
218312854Sgabeblack@google.com        // If sgn is negative, we have to convert digit to its 2's
218412854Sgabeblack@google.com        // complement. Since this function is const, we can not do it on
218512854Sgabeblack@google.com        // digit. Since buf doesn't have overflow bits, we cannot also do
218612854Sgabeblack@google.com        // it on buf. Thus, we have to do the complementation on a copy of
218712854Sgabeblack@google.com        // digit, i.e., on d.
218812854Sgabeblack@google.com
218912854Sgabeblack@google.com        vec_copy(ndigits, d, digit);
219012854Sgabeblack@google.com        vec_complement(ndigits, d);
219112854Sgabeblack@google.com        buf[buf_ndigits - 1] = ~((sc_digit) 0);
219212854Sgabeblack@google.com        digit_or_d = d;
219312854Sgabeblack@google.com    }
219412854Sgabeblack@google.com
219512854Sgabeblack@google.com    // Copy the bits from digit to buf. The division and mod operations
219612854Sgabeblack@google.com    // below can be converted to addition/subtraction and comparison
219712854Sgabeblack@google.com    // operations at the expense of complicating the code. We can do it
219812854Sgabeblack@google.com    // if we see any performance problems.
219912854Sgabeblack@google.com
220012854Sgabeblack@google.com    for (int i = length() - 1; i >= 0; --i) {
220112854Sgabeblack@google.com
220212854Sgabeblack@google.com        if ((digit_or_d[digit_ord(i)] &
220312854Sgabeblack@google.com                    one_and_zeros(bit_ord(i))) != 0) { // Test.
220412854Sgabeblack@google.com            buf[i / BITS_PER_DIGIT_TYPE] |=
220512854Sgabeblack@google.com                one_and_zeros(i % BITS_PER_DIGIT_TYPE); // Set.
220612854Sgabeblack@google.com        } else {
220712854Sgabeblack@google.com            buf[i / BITS_PER_DIGIT_TYPE] &=
220812854Sgabeblack@google.com                ~(one_and_zeros(i % BITS_PER_DIGIT_TYPE)); // Clear.
220912854Sgabeblack@google.com        }
221012854Sgabeblack@google.com    }
221112854Sgabeblack@google.com
221212854Sgabeblack@google.com#ifndef SC_MAX_NBITS
221312854Sgabeblack@google.com    delete[] d;
221412854Sgabeblack@google.com#endif
221512854Sgabeblack@google.com}
221612854Sgabeblack@google.com
221712854Sgabeblack@google.com
221812854Sgabeblack@google.com// Set a packed bit representation of the number.
221912854Sgabeblack@google.comvoid
222012854Sgabeblack@google.comCLASS_TYPE::set_packed_rep(sc_digit *buf)
222112854Sgabeblack@google.com{
222212854Sgabeblack@google.com    // Initialize digit to zero.
222312854Sgabeblack@google.com    vec_zero(ndigits, digit);
222412854Sgabeblack@google.com
222512854Sgabeblack@google.com    // Copy the bits from buf to digit.
222612854Sgabeblack@google.com    for (int i = length() - 1; i >= 0; --i) {
222712854Sgabeblack@google.com        if ((buf[i / BITS_PER_DIGIT_TYPE] &
222812854Sgabeblack@google.com                 one_and_zeros(i % BITS_PER_DIGIT_TYPE)) != 0) { // Test.
222912854Sgabeblack@google.com            digit[digit_ord(i)] |= one_and_zeros(bit_ord(i)); // Set.
223012854Sgabeblack@google.com        } else {
223112854Sgabeblack@google.com            digit[digit_ord(i)] &= ~(one_and_zeros(bit_ord(i))); // Clear
223212854Sgabeblack@google.com        }
223312854Sgabeblack@google.com    }
223412854Sgabeblack@google.com    convert_2C_to_SM();
223512854Sgabeblack@google.com}
223612854Sgabeblack@google.com
223712854Sgabeblack@google.com
223812854Sgabeblack@google.com// ----------------------------------------------------------------------------
223912854Sgabeblack@google.com//    SECTION: Private members.
224012854Sgabeblack@google.com// ----------------------------------------------------------------------------
224112854Sgabeblack@google.com
224212854Sgabeblack@google.com// Create a copy of v with sgn s.
224312854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const CLASS_TYPE &v, small_type s) :
224412854Sgabeblack@google.com    sc_value_base(v), sgn(s), nbits(v.nbits), ndigits(v.ndigits), digit()
224512854Sgabeblack@google.com{
224612854Sgabeblack@google.com#ifndef SC_MAX_NBITS
224712854Sgabeblack@google.com    digit = new sc_digit[ndigits];
224812854Sgabeblack@google.com#endif
224912854Sgabeblack@google.com    vec_copy(ndigits, digit, v.digit);
225012854Sgabeblack@google.com}
225112854Sgabeblack@google.com
225212854Sgabeblack@google.com
225312854Sgabeblack@google.com// Create a copy of v where v is of the different type.
225412854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const OTHER_CLASS_TYPE &v, small_type s) :
225512854Sgabeblack@google.com    sc_value_base(v), sgn(s), nbits(num_bits(v.nbits)), ndigits(), digit()
225612854Sgabeblack@google.com{
225712854Sgabeblack@google.com#if (IF_SC_SIGNED == 1)
225812854Sgabeblack@google.com    ndigits = v.ndigits;
225912854Sgabeblack@google.com#else
226012854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
226112854Sgabeblack@google.com#endif
226212854Sgabeblack@google.com
226312854Sgabeblack@google.com#ifndef SC_MAX_NBITS
226412854Sgabeblack@google.com    digit = new sc_digit[ndigits];
226512854Sgabeblack@google.com#endif
226612854Sgabeblack@google.com
226712854Sgabeblack@google.com    copy_digits(v.nbits, v.ndigits, v.digit);
226812854Sgabeblack@google.com}
226912854Sgabeblack@google.com
227012854Sgabeblack@google.com
227112854Sgabeblack@google.com// Create a signed number with (s, nb, nd, d) as its attributes (as
227212854Sgabeblack@google.com// defined in class CLASS_TYPE). If alloc is set, delete d.
227312854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(
227412854Sgabeblack@google.com        small_type s, int nb, int nd, sc_digit *d, bool alloc) :
227512854Sgabeblack@google.com    sc_value_base(), sgn(s), nbits(num_bits(nb)), ndigits(), digit()
227612854Sgabeblack@google.com{
227712854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
227812854Sgabeblack@google.com#ifndef SC_MAX_NBITS
227912854Sgabeblack@google.com    digit = new sc_digit[ndigits];
228012854Sgabeblack@google.com#endif
228112854Sgabeblack@google.com
228212854Sgabeblack@google.com    if (ndigits <= nd)
228312854Sgabeblack@google.com        vec_copy(ndigits, digit, d);
228412854Sgabeblack@google.com    else
228512854Sgabeblack@google.com        vec_copy_and_zero(ndigits, digit, nd, d);
228612854Sgabeblack@google.com
228712854Sgabeblack@google.com#ifndef SC_MAX_NBITS
228812854Sgabeblack@google.com    if (alloc)
228912854Sgabeblack@google.com        delete [] d;
229012854Sgabeblack@google.com#endif
229112854Sgabeblack@google.com}
229212854Sgabeblack@google.com
229312854Sgabeblack@google.com// This constructor is mainly used in finding a "range" of bits from a
229412854Sgabeblack@google.com// number of type CLASS_TYPE. The function range(l, r) can have
229512854Sgabeblack@google.com// arbitrary precedence between l and r. If l is smaller than r, then
229612854Sgabeblack@google.com// the output is the reverse of range(r, l).
229712854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const CLASS_TYPE *u, int l, int r) :
229812854Sgabeblack@google.com        sc_value_base(), sgn(), nbits(), ndigits(), digit()
229912854Sgabeblack@google.com{
230012854Sgabeblack@google.com    bool reversed = false;
230112854Sgabeblack@google.com
230212854Sgabeblack@google.com    if (l < r) {
230312854Sgabeblack@google.com        reversed = true;
230412854Sgabeblack@google.com        int tmp = l;
230512854Sgabeblack@google.com        l = r;
230612854Sgabeblack@google.com        r = tmp;
230712854Sgabeblack@google.com    }
230812854Sgabeblack@google.com
230912854Sgabeblack@google.com    // at this point, l >= r
231012854Sgabeblack@google.com
231112854Sgabeblack@google.com    // make sure that l and r point to the bits of u
231212854Sgabeblack@google.com    r = sc_max(r, 0);
231312854Sgabeblack@google.com    l = sc_min(l, u->nbits - 1);
231412854Sgabeblack@google.com
231512854Sgabeblack@google.com    nbits = num_bits(l - r + 1);
231612854Sgabeblack@google.com
231712854Sgabeblack@google.com    // nbits can still be <= 0 because l and r have just been updated
231812854Sgabeblack@google.com    // with the bounds of u.
231912854Sgabeblack@google.com
232012854Sgabeblack@google.com    // if u == 0 or the range is out of bounds, return 0
232112854Sgabeblack@google.com    if (u->sgn == SC_ZERO || nbits <= num_bits(0)) {
232212854Sgabeblack@google.com        sgn = SC_ZERO;
232312854Sgabeblack@google.com        if (nbits <= num_bits(0)) {
232412854Sgabeblack@google.com            nbits = 1;
232512854Sgabeblack@google.com        }
232612854Sgabeblack@google.com        ndigits = DIV_CEIL(nbits);
232712854Sgabeblack@google.com#ifndef SC_MAX_NBITS
232812854Sgabeblack@google.com        digit = new sc_digit[ndigits];
232912854Sgabeblack@google.com#endif
233012854Sgabeblack@google.com        vec_zero(ndigits, digit);
233112854Sgabeblack@google.com        return;
233212854Sgabeblack@google.com    }
233312854Sgabeblack@google.com
233412854Sgabeblack@google.com    // The rest will be executed if u is not zero.
233512854Sgabeblack@google.com
233612854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
233712854Sgabeblack@google.com
233812854Sgabeblack@google.com    // The number of bits up to and including l and r, respectively.
233912854Sgabeblack@google.com    int nl = l + 1;
234012854Sgabeblack@google.com    int nr = r + 1;
234112854Sgabeblack@google.com
234212854Sgabeblack@google.com    // The indices of the digits that have lth and rth bits, respectively.
234312854Sgabeblack@google.com    int left_digit = DIV_CEIL(nl) - 1;
234412854Sgabeblack@google.com    int right_digit = DIV_CEIL(nr) - 1;
234512854Sgabeblack@google.com
234612854Sgabeblack@google.com    int nd;
234712854Sgabeblack@google.com
234812854Sgabeblack@google.com    // The range is performed on the 2's complement representation, so
234912854Sgabeblack@google.com    // first get the indices for that.
235012854Sgabeblack@google.com    if (u->sgn == SC_NEG)
235112854Sgabeblack@google.com        nd = left_digit + 1;
235212854Sgabeblack@google.com    else
235312854Sgabeblack@google.com        nd = left_digit - right_digit + 1;
235412854Sgabeblack@google.com
235512854Sgabeblack@google.com    // Allocate memory for the range.
235612854Sgabeblack@google.com#ifdef SC_MAX_NBITS
235712854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS];
235812854Sgabeblack@google.com#else
235912854Sgabeblack@google.com    digit = new sc_digit[ndigits];
236012854Sgabeblack@google.com    sc_digit *d = new sc_digit[nd];
236112854Sgabeblack@google.com#endif
236212854Sgabeblack@google.com
236312854Sgabeblack@google.com    // Getting the range on the 2's complement representation.
236412854Sgabeblack@google.com    if (u->sgn == SC_NEG) {
236512854Sgabeblack@google.com        vec_copy(nd, d, u->digit);
236612854Sgabeblack@google.com        vec_complement(nd, d); // d = -d;
236712854Sgabeblack@google.com        vec_shift_right(nd, d, r, DIGIT_MASK);
236812854Sgabeblack@google.com    } else {
236912854Sgabeblack@google.com        for (int i = right_digit; i <= left_digit; ++i)
237012854Sgabeblack@google.com            d[i - right_digit] = u->digit[i];
237112854Sgabeblack@google.com        vec_shift_right(nd, d, r - right_digit * BITS_PER_DIGIT, 0);
237212854Sgabeblack@google.com    }
237312854Sgabeblack@google.com
237412854Sgabeblack@google.com    vec_zero(ndigits, digit);
237512854Sgabeblack@google.com
237612854Sgabeblack@google.com    if (!reversed) {
237712854Sgabeblack@google.com        vec_copy(sc_min(nd, ndigits), digit, d);
237812854Sgabeblack@google.com    } else {
237912854Sgabeblack@google.com        // If l < r, i.e., reversed is set, reverse the bits of digit.    d
238012854Sgabeblack@google.com        // will be used as a temporary store. The following code tries to
238112854Sgabeblack@google.com        // minimize the use of bit_ord and digit_ord, which use mod and
238212854Sgabeblack@google.com        // div operators. Since these operators are function calls to
238312854Sgabeblack@google.com        // standard library routines, they are slow. The main idea in
238412854Sgabeblack@google.com        // reversing is "read bits out of d from left to right and push
238512854Sgabeblack@google.com        // them into digit using right shifting."
238612854Sgabeblack@google.com
238712854Sgabeblack@google.com        // Take care of the last digit.
238812854Sgabeblack@google.com        int nd_less_1 = nd - 1;
238912854Sgabeblack@google.com
239012854Sgabeblack@google.com        // Deletions will start from the left end and move one position
239112854Sgabeblack@google.com        // after each deletion.
239212854Sgabeblack@google.com        sc_digit del_mask = one_and_zeros(bit_ord(l - r));
239312854Sgabeblack@google.com
239412854Sgabeblack@google.com        while (del_mask) {
239512854Sgabeblack@google.com            vec_shift_right(ndigits, digit, 1,
239612854Sgabeblack@google.com                    ((d[nd_less_1] & del_mask) != 0));
239712854Sgabeblack@google.com            del_mask >>= 1;
239812854Sgabeblack@google.com        }
239912854Sgabeblack@google.com
240012854Sgabeblack@google.com        // Take care of the other digits if any.
240112854Sgabeblack@google.com
240212854Sgabeblack@google.com        // Insertion to digit will always occur at the left end.
240312854Sgabeblack@google.com        sc_digit ins_mask = one_and_zeros(BITS_PER_DIGIT - 1);
240412854Sgabeblack@google.com
240512854Sgabeblack@google.com        for (int j = nd - 2; j >= 0; --j) { // j = nd - 2
240612854Sgabeblack@google.com            // Deletions will start from the left end and move one position
240712854Sgabeblack@google.com            // after each deletion.
240812854Sgabeblack@google.com            del_mask = ins_mask;
240912854Sgabeblack@google.com            while (del_mask) {
241012854Sgabeblack@google.com                vec_shift_right(ndigits, digit, 1, ((d[j] & del_mask) != 0));
241112854Sgabeblack@google.com                del_mask >>= 1;
241212854Sgabeblack@google.com            }
241312854Sgabeblack@google.com        }
241412854Sgabeblack@google.com
241512854Sgabeblack@google.com        if (u->sgn == SC_NEG)
241612854Sgabeblack@google.com            vec_shift_right(ndigits, digit,
241712854Sgabeblack@google.com                            ndigits * BITS_PER_DIGIT - length(), DIGIT_MASK);
241812854Sgabeblack@google.com        else
241912854Sgabeblack@google.com            vec_shift_right(ndigits, digit,
242012854Sgabeblack@google.com                            ndigits * BITS_PER_DIGIT - length(), 0);
242112854Sgabeblack@google.com
242212854Sgabeblack@google.com
242312854Sgabeblack@google.com    } // if reversed.
242412854Sgabeblack@google.com
242512854Sgabeblack@google.com    convert_2C_to_SM();
242612854Sgabeblack@google.com
242712854Sgabeblack@google.com#ifndef SC_MAX_NBITS
242812854Sgabeblack@google.com    delete [] d;
242912854Sgabeblack@google.com#endif
243012854Sgabeblack@google.com}
243112854Sgabeblack@google.com
243212854Sgabeblack@google.com// This constructor is mainly used in finding a "range" of bits from a
243312854Sgabeblack@google.com// number of type OTHER_CLASS_TYPE. The function range(l, r) can have
243412854Sgabeblack@google.com// arbitrary precedence between l and r. If l is smaller than r, then
243512854Sgabeblack@google.com// the output is the reverse of range(r, l).
243612854Sgabeblack@google.comCLASS_TYPE::CLASS_TYPE(const OTHER_CLASS_TYPE *u, int l, int r) :
243712854Sgabeblack@google.com        sc_value_base(), sgn(), nbits(), ndigits(), digit()
243812854Sgabeblack@google.com{
243912854Sgabeblack@google.com    bool reversed = false;
244012854Sgabeblack@google.com
244112854Sgabeblack@google.com    if (l < r) {
244212854Sgabeblack@google.com        reversed = true;
244312854Sgabeblack@google.com        int tmp = l;
244412854Sgabeblack@google.com        l = r;
244512854Sgabeblack@google.com        r = tmp;
244612854Sgabeblack@google.com    }
244712854Sgabeblack@google.com
244812854Sgabeblack@google.com    // at this point, l >= r
244912854Sgabeblack@google.com
245012854Sgabeblack@google.com    // make sure that l and r point to the bits of u
245112854Sgabeblack@google.com    r = sc_max(r, 0);
245212854Sgabeblack@google.com    l = sc_min(l, u->nbits - 1);
245312854Sgabeblack@google.com
245412854Sgabeblack@google.com    nbits = num_bits(l - r + 1);
245512854Sgabeblack@google.com
245612854Sgabeblack@google.com    // nbits can still be <= 0 because l and r have just been updated
245712854Sgabeblack@google.com    // with the bounds of u.
245812854Sgabeblack@google.com
245912854Sgabeblack@google.com    // if u == 0 or the range is out of bounds, return 0
246012854Sgabeblack@google.com    if (u->sgn == SC_ZERO || nbits <= num_bits(0)) {
246112854Sgabeblack@google.com        sgn = SC_ZERO;
246212854Sgabeblack@google.com        if (nbits <= num_bits(0)) {
246312854Sgabeblack@google.com            nbits = 1;
246412854Sgabeblack@google.com        }
246512854Sgabeblack@google.com        ndigits = DIV_CEIL(nbits);
246612854Sgabeblack@google.com#ifndef SC_MAX_NBITS
246712854Sgabeblack@google.com        digit = new sc_digit[ndigits];
246812854Sgabeblack@google.com#endif
246912854Sgabeblack@google.com        vec_zero(ndigits, digit);
247012854Sgabeblack@google.com        return;
247112854Sgabeblack@google.com    }
247212854Sgabeblack@google.com
247312854Sgabeblack@google.com    // The rest will be executed if u is not zero.
247412854Sgabeblack@google.com
247512854Sgabeblack@google.com    ndigits = DIV_CEIL(nbits);
247612854Sgabeblack@google.com
247712854Sgabeblack@google.com    // The number of bits up to and including l and r, respectively.
247812854Sgabeblack@google.com    int nl = l + 1;
247912854Sgabeblack@google.com    int nr = r + 1;
248012854Sgabeblack@google.com
248112854Sgabeblack@google.com    // The indices of the digits that have lth and rth bits, respectively.
248212854Sgabeblack@google.com    int left_digit = DIV_CEIL(nl) - 1;
248312854Sgabeblack@google.com    int right_digit = DIV_CEIL(nr) - 1;
248412854Sgabeblack@google.com
248512854Sgabeblack@google.com    int nd;
248612854Sgabeblack@google.com
248712854Sgabeblack@google.com    // The range is performed on the 2's complement representation, so
248812854Sgabeblack@google.com    // first get the indices for that.
248912854Sgabeblack@google.com    if (u->sgn == SC_NEG)
249012854Sgabeblack@google.com        nd = left_digit + 1;
249112854Sgabeblack@google.com    else
249212854Sgabeblack@google.com        nd = left_digit - right_digit + 1;
249312854Sgabeblack@google.com
249412854Sgabeblack@google.com    // Allocate memory for the range.
249512854Sgabeblack@google.com#ifdef SC_MAX_NBITS
249612854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS];
249712854Sgabeblack@google.com#else
249812854Sgabeblack@google.com    digit = new sc_digit[ndigits];
249912854Sgabeblack@google.com    sc_digit *d = new sc_digit[nd];
250012854Sgabeblack@google.com#endif
250112854Sgabeblack@google.com
250212854Sgabeblack@google.com    // Getting the range on the 2's complement representation.
250312854Sgabeblack@google.com    if (u->sgn == SC_NEG) {
250412854Sgabeblack@google.com        vec_copy(nd, d, u->digit);
250512854Sgabeblack@google.com        vec_complement(nd, d); // d = -d;
250612854Sgabeblack@google.com        vec_shift_right(nd, d, r, DIGIT_MASK);
250712854Sgabeblack@google.com    } else {
250812854Sgabeblack@google.com        for (int i = right_digit; i <= left_digit; ++i)
250912854Sgabeblack@google.com            d[i - right_digit] = u->digit[i];
251012854Sgabeblack@google.com        vec_shift_right(nd, d, r - right_digit * BITS_PER_DIGIT, 0);
251112854Sgabeblack@google.com    }
251212854Sgabeblack@google.com
251312854Sgabeblack@google.com    vec_zero(ndigits, digit);
251412854Sgabeblack@google.com
251512854Sgabeblack@google.com    if (!reversed) {
251612854Sgabeblack@google.com        vec_copy(sc_min(nd, ndigits), digit, d);
251712854Sgabeblack@google.com    } else {
251812854Sgabeblack@google.com        // If l < r, i.e., reversed is set, reverse the bits of digit.    d
251912854Sgabeblack@google.com        // will be used as a temporary store. The following code tries to
252012854Sgabeblack@google.com        // minimize the use of bit_ord and digit_ord, which use mod and
252112854Sgabeblack@google.com        // div operators. Since these operators are function calls to
252212854Sgabeblack@google.com        // standard library routines, they are slow. The main idea in
252312854Sgabeblack@google.com        // reversing is "read bits out of d from left to right and push
252412854Sgabeblack@google.com        // them into digit using right shifting."
252512854Sgabeblack@google.com
252612854Sgabeblack@google.com        // Take care of the last digit.
252712854Sgabeblack@google.com        int nd_less_1 = nd - 1;
252812854Sgabeblack@google.com
252912854Sgabeblack@google.com        // Deletions will start from the left end and move one position
253012854Sgabeblack@google.com        // after each deletion.
253112854Sgabeblack@google.com        sc_digit del_mask = one_and_zeros(bit_ord(l - r));
253212854Sgabeblack@google.com
253312854Sgabeblack@google.com        while (del_mask) {
253412854Sgabeblack@google.com            vec_shift_right(ndigits, digit, 1,
253512854Sgabeblack@google.com                    ((d[nd_less_1] & del_mask) != 0));
253612854Sgabeblack@google.com            del_mask >>= 1;
253712854Sgabeblack@google.com        }
253812854Sgabeblack@google.com
253912854Sgabeblack@google.com        // Take care of the other digits if any.
254012854Sgabeblack@google.com
254112854Sgabeblack@google.com        // Insertion to digit will always occur at the left end.
254212854Sgabeblack@google.com        sc_digit ins_mask = one_and_zeros(BITS_PER_DIGIT - 1);
254312854Sgabeblack@google.com
254412854Sgabeblack@google.com        for (int j = nd - 2; j >= 0; --j) { // j = nd - 2
254512854Sgabeblack@google.com            // Deletions will start from the left end and move one position
254612854Sgabeblack@google.com            // after each deletion.
254712854Sgabeblack@google.com            del_mask = ins_mask;
254812854Sgabeblack@google.com
254912854Sgabeblack@google.com            while (del_mask) {
255012854Sgabeblack@google.com                vec_shift_right(ndigits, digit, 1, ((d[j] & del_mask) != 0));
255112854Sgabeblack@google.com                del_mask >>= 1;
255212854Sgabeblack@google.com            }
255312854Sgabeblack@google.com        }
255412854Sgabeblack@google.com
255512854Sgabeblack@google.com        if (u->sgn == SC_NEG)
255612854Sgabeblack@google.com            vec_shift_right(ndigits, digit,
255712854Sgabeblack@google.com                            ndigits * BITS_PER_DIGIT - length(), DIGIT_MASK);
255812854Sgabeblack@google.com        else
255912854Sgabeblack@google.com            vec_shift_right(ndigits, digit,
256012854Sgabeblack@google.com                            ndigits * BITS_PER_DIGIT - length(), 0);
256112854Sgabeblack@google.com
256212854Sgabeblack@google.com
256312854Sgabeblack@google.com    } // if reversed.
256412854Sgabeblack@google.com
256512854Sgabeblack@google.com    convert_2C_to_SM();
256612854Sgabeblack@google.com
256712854Sgabeblack@google.com#ifndef SC_MAX_NBITS
256812854Sgabeblack@google.com    delete [] d;
256912854Sgabeblack@google.com#endif
257012854Sgabeblack@google.com}
257112854Sgabeblack@google.com
257212854Sgabeblack@google.com
257312854Sgabeblack@google.com// Print out all the physical attributes.
257412854Sgabeblack@google.comvoid
257512854Sgabeblack@google.comCLASS_TYPE::dump(::std::ostream &os) const
257612854Sgabeblack@google.com{
257712854Sgabeblack@google.com    // Save the current setting, and set the base to decimal.
257812854Sgabeblack@google.com    ::std::ios::fmtflags old_flags =
257912854Sgabeblack@google.com        os.setf(::std::ios::dec, ::std::ios::basefield);
258012854Sgabeblack@google.com
258112854Sgabeblack@google.com    os << "width = " << length() << ::std::endl;
258212854Sgabeblack@google.com    os << "value = " << *this << ::std::endl;
258313011Sgabeblack@google.com    os << "bits  = ";
258412854Sgabeblack@google.com
258512854Sgabeblack@google.com    int len = length();
258612854Sgabeblack@google.com
258712854Sgabeblack@google.com    for (int i = len - 1; i >= 0; --i) {
258812854Sgabeblack@google.com        os << "01"[test(i)];
258912854Sgabeblack@google.com        if (--len % 4 == 0)
259012854Sgabeblack@google.com            os << " ";
259112854Sgabeblack@google.com    }
259212854Sgabeblack@google.com
259312854Sgabeblack@google.com    os << ::std::endl;
259412854Sgabeblack@google.com
259512854Sgabeblack@google.com    // Restore old_flags.
259612854Sgabeblack@google.com    os.setf(old_flags, ::std::ios::basefield);
259712854Sgabeblack@google.com}
259812854Sgabeblack@google.com
259912854Sgabeblack@google.com
260012854Sgabeblack@google.com// Checks to see if bit_num is out of bounds.
260112854Sgabeblack@google.combool
260212854Sgabeblack@google.comCLASS_TYPE::check_if_outside(int bit_num) const
260312854Sgabeblack@google.com{
260412854Sgabeblack@google.com    if ((bit_num < 0) || (num_bits(bit_num) >= nbits)) {
260512854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
260612854Sgabeblack@google.com        if (bit_num < 0 || bit_num >= nbits) {
260712854Sgabeblack@google.com                std::stringstream msg;
260812854Sgabeblack@google.com                msg << CLASS_TYPE_STR "::check_if_outside(int bit_num) : "
260912854Sgabeblack@google.com                             "bit_num = " << bit_num << " is out of bounds";
261012854Sgabeblack@google.com                SC_REPORT_WARNING(sc_core::SC_ID_OUT_OF_BOUNDS_,
261112854Sgabeblack@google.com                                  msg.str().c_str());
261212854Sgabeblack@google.com        }
261312854Sgabeblack@google.com#endif
261412854Sgabeblack@google.com        return true;
261512854Sgabeblack@google.com    }
261612854Sgabeblack@google.com    return false;
261712854Sgabeblack@google.com}
2618