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_nbfriends.inc -- Friend functions for both sc_signed and sc_unsigned
2312854Sgabeblack@google.com                      classes. The vec_* functions are called through either
2412854Sgabeblack@google.com                      these functions or those in sc_nbexterns.cpp. These
2512854Sgabeblack@google.com                      functions perform their work on two inputs u and v, and
2612854Sgabeblack@google.com                      return the result object. The functions in
2712854Sgabeblack@google.com                      sc_nbexterns.cpp perform their work on one of their
2812854Sgabeblack@google.com                      inputs.
2912854Sgabeblack@google.com
3012854Sgabeblack@google.com                      The functions here try to use faster algorithms in case
3112854Sgabeblack@google.com                      the input numbers are small. The bitwise functions (and,
3212854Sgabeblack@google.com                      or, and xor) need the 2's complement representations of
3312854Sgabeblack@google.com                      their inputs. Instead of complementing their inputs
3412854Sgabeblack@google.com                      first and then processing, they complement their inputs
3512854Sgabeblack@google.com                      while processing without allocating extra temporary
3612854Sgabeblack@google.com                      memory.
3712854Sgabeblack@google.com
3812854Sgabeblack@google.com  Original Author: Ali Dasdan, Synopsys, Inc.
3912854Sgabeblack@google.com
4012854Sgabeblack@google.com *****************************************************************************/
4112854Sgabeblack@google.com
4212854Sgabeblack@google.com/*****************************************************************************
4312854Sgabeblack@google.com
4412854Sgabeblack@google.com  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
4512854Sgabeblack@google.com  changes you are making here.
4612854Sgabeblack@google.com
4712854Sgabeblack@google.com      Name, Affiliation, Date:
4812854Sgabeblack@google.com  Description of Modification:
4912854Sgabeblack@google.com
5012854Sgabeblack@google.com *****************************************************************************/
5112854Sgabeblack@google.com
5212854Sgabeblack@google.com
5312854Sgabeblack@google.com// ----------------------------------------------------------------------------
5412854Sgabeblack@google.com//  Naming conventions:
5512854Sgabeblack@google.com//  For sc_signed or sc_unsigned number u:
5612854Sgabeblack@google.com//    us : u's sign, unb : u's number of bits,
5712854Sgabeblack@google.com//    und : u's number of digits, ud : u's digits array.
5812854Sgabeblack@google.com// ----------------------------------------------------------------------------
5912854Sgabeblack@google.com
6012854Sgabeblack@google.com// ----------------------------------------------------------------------------
6112854Sgabeblack@google.com//  SECTION: Friend functions for PLUS operators.
6212854Sgabeblack@google.com// ----------------------------------------------------------------------------
6312854Sgabeblack@google.com
6412854Sgabeblack@google.com// Handles cases 3 and 4 and returns the result.
6512854Sgabeblack@google.comCLASS_TYPE
6612854Sgabeblack@google.comADD_HELPER(small_type us, int unb, int und, const sc_digit *ud,
6712854Sgabeblack@google.com           small_type vs, int vnb, int vnd, const sc_digit *vd)
6812854Sgabeblack@google.com{
6912854Sgabeblack@google.com    und = vec_skip_leading_zeros(und, ud);
7012854Sgabeblack@google.com    vnd = vec_skip_leading_zeros(vnd, vd);
7112854Sgabeblack@google.com
7212854Sgabeblack@google.com    int nb = sc_max(unb, vnb);
7312854Sgabeblack@google.com    int nd = sc_max(und, vnd) + 1;
7412854Sgabeblack@google.com
7512854Sgabeblack@google.com#ifdef SC_MAX_NBITS
7612854Sgabeblack@google.com    test_bound(nb);
7712854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS];
7812854Sgabeblack@google.com#else
7912854Sgabeblack@google.com    sc_digit *d = new sc_digit[nd];
8012854Sgabeblack@google.com#endif
8112854Sgabeblack@google.com
8212854Sgabeblack@google.com    d[nd - 1] = d[nd - 2] = 0;
8312854Sgabeblack@google.com
8412854Sgabeblack@google.com    // case 3
8512854Sgabeblack@google.com    if (us == vs) {
8612854Sgabeblack@google.com
8712854Sgabeblack@google.com        ++nb;
8812854Sgabeblack@google.com
8912854Sgabeblack@google.com        if ((und == 1) && (vnd == 1)) {
9012854Sgabeblack@google.com            sc_digit carry = (*ud) + (*vd);
9112854Sgabeblack@google.com            d[0] = carry & DIGIT_MASK;
9212854Sgabeblack@google.com            d[1] = carry >> BITS_PER_DIGIT;
9312854Sgabeblack@google.com        } else if (und >= vnd) {
9412854Sgabeblack@google.com            vec_add(und, ud, vnd, vd, d);
9512854Sgabeblack@google.com        } else {
9612854Sgabeblack@google.com            vec_add(vnd, vd, und, ud, d);
9712854Sgabeblack@google.com        }
9812854Sgabeblack@google.com    } else {
9912854Sgabeblack@google.com        // case 4
10012854Sgabeblack@google.com        int cmp_res = vec_cmp(und, ud, vnd, vd);
10112854Sgabeblack@google.com
10212854Sgabeblack@google.com        if (cmp_res == 0) { // u == v
10312854Sgabeblack@google.com#ifndef SC_MAX_NBITS
10412854Sgabeblack@google.com            delete[] d;
10512854Sgabeblack@google.com#endif
10612854Sgabeblack@google.com            return CLASS_TYPE();
10712854Sgabeblack@google.com        }
10812854Sgabeblack@google.com
10912854Sgabeblack@google.com        if (cmp_res > 0) { // u > v
11012854Sgabeblack@google.com            if ((und == 1) && (vnd == 1))
11112854Sgabeblack@google.com                d[0] = (*ud) - (*vd);
11212854Sgabeblack@google.com            else
11312854Sgabeblack@google.com                vec_sub(und, ud, vnd, vd, d);
11412854Sgabeblack@google.com        } else { // u < v
11512854Sgabeblack@google.com            us = -us;
11612854Sgabeblack@google.com            if ((und == 1) && (vnd == 1))
11712854Sgabeblack@google.com                d[0] = (*vd) - (*ud);
11812854Sgabeblack@google.com            else
11912854Sgabeblack@google.com                vec_sub(vnd, vd, und, ud, d);
12012854Sgabeblack@google.com        }
12112854Sgabeblack@google.com    }
12212854Sgabeblack@google.com    return CLASS_TYPE(us, nb, nd, d);
12312854Sgabeblack@google.com}
12412854Sgabeblack@google.com
12512854Sgabeblack@google.com
12612854Sgabeblack@google.com// ----------------------------------------------------------------------------
12712854Sgabeblack@google.com//  SECTION: Friend functions of MULTIPLICATION operators.
12812854Sgabeblack@google.com// ----------------------------------------------------------------------------
12912854Sgabeblack@google.com
13012854Sgabeblack@google.com// Handles the case 4 and returns the result.
13112854Sgabeblack@google.comCLASS_TYPE
13212854Sgabeblack@google.comMUL_HELPER(small_type s, int unb, int und,  const sc_digit *ud,
13312854Sgabeblack@google.com           int vnb, int vnd, const sc_digit *vd)
13412854Sgabeblack@google.com{
13512854Sgabeblack@google.com    und = vec_skip_leading_zeros(und, ud);
13612854Sgabeblack@google.com    vnd = vec_skip_leading_zeros(vnd, vd);
13712854Sgabeblack@google.com
13812854Sgabeblack@google.com    int nb = unb + vnb;
13912854Sgabeblack@google.com    int nd = und + vnd;
14012854Sgabeblack@google.com
14112854Sgabeblack@google.com#ifdef SC_MAX_NBITS
14212854Sgabeblack@google.com    test_bound(nb);
14312854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS];
14412854Sgabeblack@google.com#else
14512854Sgabeblack@google.com    sc_digit *d = new sc_digit[nd];
14612854Sgabeblack@google.com#endif
14712854Sgabeblack@google.com
14812854Sgabeblack@google.com    vec_zero(nd, d);
14912854Sgabeblack@google.com
15012854Sgabeblack@google.com    sc_digit ud0 = (*ud);
15112854Sgabeblack@google.com    sc_digit vd0 = (*vd);
15212854Sgabeblack@google.com
15312854Sgabeblack@google.com    if ((vnd == 1) && (vd0 == 1)) {
15412854Sgabeblack@google.com        vec_copy(und, d, ud);
15512854Sgabeblack@google.com    } else if ((und == 1) && (ud0 == 1)) {
15612854Sgabeblack@google.com        vec_copy(vnd, d, vd);
15712854Sgabeblack@google.com    } else if ((und == 1) && (vnd == 1) &&
15812854Sgabeblack@google.com               (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
15912854Sgabeblack@google.com        d[0] = ud0 * vd0;
16012854Sgabeblack@google.com    } else if ((und == 1) && (ud0 < HALF_DIGIT_RADIX)) {
16112854Sgabeblack@google.com        vec_mul_small(vnd, vd, ud0, d);
16212854Sgabeblack@google.com    } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
16312854Sgabeblack@google.com        vec_mul_small(und, ud, vd0, d);
16412854Sgabeblack@google.com    } else if (vnd < und) {
16512854Sgabeblack@google.com        vec_mul(und, ud, vnd, vd, d);
16612854Sgabeblack@google.com    } else {
16712854Sgabeblack@google.com        vec_mul(vnd, vd, und, ud, d);
16812854Sgabeblack@google.com    }
16912854Sgabeblack@google.com    return CLASS_TYPE(s, nb, nd, d);
17012854Sgabeblack@google.com}
17112854Sgabeblack@google.com
17212854Sgabeblack@google.com
17312854Sgabeblack@google.com// ----------------------------------------------------------------------------
17412854Sgabeblack@google.com//  SECTION: Friend functions for DIVISION operators.
17512854Sgabeblack@google.com// ----------------------------------------------------------------------------
17612854Sgabeblack@google.com
17712854Sgabeblack@google.com// Handles the cases 3-4 and returns the result.
17812854Sgabeblack@google.comCLASS_TYPE
17912854Sgabeblack@google.comDIV_HELPER(small_type s, int unb, int und, const sc_digit *ud,
18012854Sgabeblack@google.com           int vnb, int vnd, const sc_digit *vd)
18112854Sgabeblack@google.com{
18212854Sgabeblack@google.com    und = vec_skip_leading_zeros(und, ud);
18312854Sgabeblack@google.com    vnd = vec_skip_leading_zeros(vnd, vd);
18412854Sgabeblack@google.com
18512854Sgabeblack@google.com    int cmp_res = vec_cmp(und, ud, vnd, vd);
18612854Sgabeblack@google.com
18712854Sgabeblack@google.com    // u < v => u / v = 0 - case 4
18812854Sgabeblack@google.com    if (cmp_res < 0)
18912854Sgabeblack@google.com        return CLASS_TYPE();
19012854Sgabeblack@google.com
19112854Sgabeblack@google.com    // One extra digit for d is allocated to simplify vec_div_*().
19212854Sgabeblack@google.com    int nd = sc_max(und, vnd) + 1;
19312854Sgabeblack@google.com
19412854Sgabeblack@google.com#ifdef SC_MAX_NBITS
19512854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS + 1];
19612854Sgabeblack@google.com#else
19712854Sgabeblack@google.com    sc_digit *d = new sc_digit[nd];
19812854Sgabeblack@google.com#endif
19912854Sgabeblack@google.com
20012854Sgabeblack@google.com    vec_zero(nd, d);
20112854Sgabeblack@google.com    sc_digit vd0 = (*vd);
20212854Sgabeblack@google.com
20312854Sgabeblack@google.com    // u = v => u / v = 1 - case 3
20412854Sgabeblack@google.com    if (cmp_res == 0) {
20512854Sgabeblack@google.com        d[0] = 1;
20612854Sgabeblack@google.com    // else if u > v - case 5
20712854Sgabeblack@google.com    } else if ((vnd == 1) && (vd0 == 1)) {
20812854Sgabeblack@google.com        vec_copy(und, d, ud);
20912854Sgabeblack@google.com    } else if ((vnd == 1) && (und == 1)) {
21012854Sgabeblack@google.com        d[0] = (*ud) / vd0;
21112854Sgabeblack@google.com    } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
21212854Sgabeblack@google.com        vec_div_small(und, ud, vd0, d);
21312854Sgabeblack@google.com    } else {
21412854Sgabeblack@google.com        vec_div_large(und, ud, vnd, vd, d);
21512854Sgabeblack@google.com    }
21612854Sgabeblack@google.com
21712854Sgabeblack@google.com    return CLASS_TYPE(s, sc_max(unb, vnb), nd - 1, d);
21812854Sgabeblack@google.com}
21912854Sgabeblack@google.com
22012854Sgabeblack@google.com
22112854Sgabeblack@google.com// ----------------------------------------------------------------------------
22212854Sgabeblack@google.com//  SECTION: Friend functions for MOD operators.
22312854Sgabeblack@google.com// ----------------------------------------------------------------------------
22412854Sgabeblack@google.com
22512854Sgabeblack@google.com// Handles the cases 3-4 and returns the result.
22612854Sgabeblack@google.comCLASS_TYPE
22712854Sgabeblack@google.comMOD_HELPER(small_type us, int unb, int und, const sc_digit *ud,
22812854Sgabeblack@google.com           int vnb, int vnd, const sc_digit *vd)
22912854Sgabeblack@google.com{
23012854Sgabeblack@google.com    und = vec_skip_leading_zeros(und, ud);
23112854Sgabeblack@google.com    vnd = vec_skip_leading_zeros(vnd, vd);
23212854Sgabeblack@google.com
23312854Sgabeblack@google.com    int cmp_res = vec_cmp(und, ud, vnd, vd);
23412854Sgabeblack@google.com    // u = v => u % v = 0 - case 3
23512854Sgabeblack@google.com    if (cmp_res == 0)
23612854Sgabeblack@google.com        return CLASS_TYPE();
23712854Sgabeblack@google.com
23812854Sgabeblack@google.com    sc_digit vd0 = (*vd);
23912854Sgabeblack@google.com    if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1))
24012854Sgabeblack@google.com        return CLASS_TYPE();
24112854Sgabeblack@google.com
24212854Sgabeblack@google.com    // One extra digit for d is allocated to simplify vec_div_*().
24312854Sgabeblack@google.com    int nd = sc_max(und, vnd) + 1;
24412854Sgabeblack@google.com
24512854Sgabeblack@google.com#ifdef SC_MAX_NBITS
24612854Sgabeblack@google.com    sc_digit d[MAX_NDIGITS + 1];
24712854Sgabeblack@google.com#else
24812854Sgabeblack@google.com    sc_digit *d = new sc_digit[nd];
24912854Sgabeblack@google.com#endif
25012854Sgabeblack@google.com
25112854Sgabeblack@google.com    vec_zero(nd, d);
25212854Sgabeblack@google.com
25312854Sgabeblack@google.com    // u < v => u % v = u - case 4
25412854Sgabeblack@google.com    if (cmp_res < 0) {
25512854Sgabeblack@google.com        vec_copy(und, d, ud);
25612854Sgabeblack@google.com    // else if u > v - case 5
25712854Sgabeblack@google.com    } else if ((vnd == 1) && (und == 1)) {
25812854Sgabeblack@google.com        d[0] = (*ud) % vd0;
25912854Sgabeblack@google.com    } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
26012854Sgabeblack@google.com        d[0] = vec_rem_small(und, ud, vd0);
26112854Sgabeblack@google.com    } else {
26212854Sgabeblack@google.com        vec_rem_large(und, ud, vnd, vd, d);
26312854Sgabeblack@google.com    }
26412854Sgabeblack@google.com
26512854Sgabeblack@google.com    us = check_for_zero(us, nd - 1, d);
26612854Sgabeblack@google.com
26712854Sgabeblack@google.com    if (us == SC_ZERO) {
26812854Sgabeblack@google.com#ifndef SC_MAX_NBITS
26912854Sgabeblack@google.com        delete[] d;
27012854Sgabeblack@google.com#endif
27112854Sgabeblack@google.com        return CLASS_TYPE();
27212854Sgabeblack@google.com    } else {
27312854Sgabeblack@google.com        return CLASS_TYPE(us, sc_min(unb, vnb), nd - 1, d);
27412854Sgabeblack@google.com    }
27512854Sgabeblack@google.com}
27612854Sgabeblack@google.com
27712854Sgabeblack@google.com
27812854Sgabeblack@google.com// ----------------------------------------------------------------------------
27912854Sgabeblack@google.com//  SECTION: Friend functions for AND operators.
28012854Sgabeblack@google.com// ----------------------------------------------------------------------------
28112854Sgabeblack@google.com
28212854Sgabeblack@google.com// Handles the cases 2-5 and returns the result.
28312854Sgabeblack@google.comCLASS_TYPE
28412854Sgabeblack@google.comAND_HELPER(small_type us, int unb, int und, const sc_digit *ud,
28512854Sgabeblack@google.com           small_type vs, int vnb, int vnd, const sc_digit *vd)
28612854Sgabeblack@google.com{
28712854Sgabeblack@google.com    int nb = sc_max(unb, vnb);
28812854Sgabeblack@google.com    int nd = sc_max(und, vnd);
28912854Sgabeblack@google.com
29012854Sgabeblack@google.com#ifdef SC_MAX_NBITS
29112854Sgabeblack@google.com    sc_digit dbegin[MAX_NDIGITS];
29212854Sgabeblack@google.com#else
29312854Sgabeblack@google.com    sc_digit *dbegin = new sc_digit[nd];
29412854Sgabeblack@google.com#endif
29512854Sgabeblack@google.com
29612854Sgabeblack@google.com    sc_digit *d = dbegin;
29712854Sgabeblack@google.com
29812854Sgabeblack@google.com    const sc_digit *x;
29912854Sgabeblack@google.com    const sc_digit *y;
30012854Sgabeblack@google.com    int xnd;
30112854Sgabeblack@google.com    int ynd;
30212854Sgabeblack@google.com    small_type xs;
30312854Sgabeblack@google.com    small_type ys;
30412854Sgabeblack@google.com
30512854Sgabeblack@google.com    if (und >= vnd) {
30612854Sgabeblack@google.com        x = ud;
30712854Sgabeblack@google.com        y = vd;
30812854Sgabeblack@google.com        xnd = und;
30912854Sgabeblack@google.com        ynd = vnd;
31012854Sgabeblack@google.com        xs = us;
31112854Sgabeblack@google.com        ys = vs;
31212854Sgabeblack@google.com    } else {
31312854Sgabeblack@google.com        y = ud;
31412854Sgabeblack@google.com        x = vd;
31512854Sgabeblack@google.com        ynd = und;
31612854Sgabeblack@google.com        xnd = vnd;
31712854Sgabeblack@google.com        ys = us;
31812854Sgabeblack@google.com        xs = vs;
31912854Sgabeblack@google.com    }
32012854Sgabeblack@google.com
32112854Sgabeblack@google.com    const sc_digit *xend = (x + xnd);
32212854Sgabeblack@google.com    const sc_digit *yend = (y + ynd);
32312854Sgabeblack@google.com
32412854Sgabeblack@google.com    // x is longer than y.
32512854Sgabeblack@google.com    small_type s = mul_signs(xs, ys);
32612854Sgabeblack@google.com    if (s > 0) {
32712854Sgabeblack@google.com        if (xs > 0) { // case 2
32812854Sgabeblack@google.com            while (y < yend)
32912854Sgabeblack@google.com                (*d++) = (*x++) & (*y++);
33012854Sgabeblack@google.com            while (x++ < xend)
33112854Sgabeblack@google.com                (*d++) = 0;
33212854Sgabeblack@google.com        } else { // case 3
33312854Sgabeblack@google.com            sc_digit xcarry = 1;
33412854Sgabeblack@google.com            sc_digit ycarry = 1;
33512854Sgabeblack@google.com            while (y < yend) {
33612854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
33712854Sgabeblack@google.com                ycarry += (~(*y++) & DIGIT_MASK);
33812854Sgabeblack@google.com                (*d++) = (xcarry & ycarry) & DIGIT_MASK;
33912854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
34012854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
34112854Sgabeblack@google.com            }
34212854Sgabeblack@google.com            while (x < xend) {
34312854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
34412854Sgabeblack@google.com                ycarry += DIGIT_MASK;
34512854Sgabeblack@google.com                (*d++) = (xcarry & ycarry) & DIGIT_MASK;
34612854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
34712854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
34812854Sgabeblack@google.com            }
34912854Sgabeblack@google.com        }
35012854Sgabeblack@google.com    } else {
35112854Sgabeblack@google.com        if (xs > 0) { // case 4
35212854Sgabeblack@google.com            sc_digit ycarry = 1;
35312854Sgabeblack@google.com            while (y < yend) {
35412854Sgabeblack@google.com                ycarry += (~(*y++) & DIGIT_MASK);
35512854Sgabeblack@google.com                (*d++) = ((*x++) & ycarry) & DIGIT_MASK;
35612854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
35712854Sgabeblack@google.com            }
35812854Sgabeblack@google.com            while (x < xend) {
35912854Sgabeblack@google.com                ycarry += DIGIT_MASK;
36012854Sgabeblack@google.com                (*d++) = ((*x++) & ycarry) & DIGIT_MASK;
36112854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
36212854Sgabeblack@google.com            }
36312854Sgabeblack@google.com        } else { // case 5
36412854Sgabeblack@google.com            sc_digit xcarry = 1;
36512854Sgabeblack@google.com            while (y < yend) {
36612854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
36712854Sgabeblack@google.com                (*d++) = (xcarry & (*y++)) & DIGIT_MASK;
36812854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
36912854Sgabeblack@google.com            }
37012854Sgabeblack@google.com            while (x++ < xend)
37112854Sgabeblack@google.com                (*d++) = 0;
37212854Sgabeblack@google.com        }
37312854Sgabeblack@google.com    }
37412854Sgabeblack@google.com    s = convert_signed_2C_to_SM(nb, nd, dbegin);
37512854Sgabeblack@google.com    return CLASS_TYPE(s, nb, nd, dbegin);
37612854Sgabeblack@google.com}
37712854Sgabeblack@google.com
37812854Sgabeblack@google.com
37912854Sgabeblack@google.com// ----------------------------------------------------------------------------
38012854Sgabeblack@google.com//  SECTION: Friend functions for OR operators.
38112854Sgabeblack@google.com// ----------------------------------------------------------------------------
38212854Sgabeblack@google.com
38312854Sgabeblack@google.com// Handles the cases 3-5 and returns the result.
38412854Sgabeblack@google.comCLASS_TYPE
38512854Sgabeblack@google.comOR_HELPER(small_type us, int unb, int und, const sc_digit *ud,
38612854Sgabeblack@google.com          small_type vs, int vnb, int vnd, const sc_digit *vd)
38712854Sgabeblack@google.com{
38812854Sgabeblack@google.com    int nb = sc_max(unb, vnb);
38912854Sgabeblack@google.com    int nd = sc_max(und, vnd);
39012854Sgabeblack@google.com
39112854Sgabeblack@google.com#ifdef SC_MAX_NBITS
39212854Sgabeblack@google.com    sc_digit dbegin[MAX_NDIGITS];
39312854Sgabeblack@google.com#else
39412854Sgabeblack@google.com    sc_digit *dbegin = new sc_digit[nd];
39512854Sgabeblack@google.com#endif
39612854Sgabeblack@google.com    sc_digit *d = dbegin;
39712854Sgabeblack@google.com    const sc_digit *x;
39812854Sgabeblack@google.com    const sc_digit *y;
39912854Sgabeblack@google.com    int xnd;
40012854Sgabeblack@google.com    int ynd;
40112854Sgabeblack@google.com    small_type xs;
40212854Sgabeblack@google.com    small_type ys;
40312854Sgabeblack@google.com
40412854Sgabeblack@google.com    if (und >= vnd) {
40512854Sgabeblack@google.com        x = ud;
40612854Sgabeblack@google.com        y = vd;
40712854Sgabeblack@google.com        xnd = und;
40812854Sgabeblack@google.com        ynd = vnd;
40912854Sgabeblack@google.com        xs = us;
41012854Sgabeblack@google.com        ys = vs;
41112854Sgabeblack@google.com    } else {
41212854Sgabeblack@google.com        y = ud;
41312854Sgabeblack@google.com        x = vd;
41412854Sgabeblack@google.com        ynd = und;
41512854Sgabeblack@google.com        xnd = vnd;
41612854Sgabeblack@google.com        ys = us;
41712854Sgabeblack@google.com        xs = vs;
41812854Sgabeblack@google.com    }
41912854Sgabeblack@google.com
42012854Sgabeblack@google.com    const sc_digit *xend = (x + xnd);
42112854Sgabeblack@google.com    const sc_digit *yend = (y + ynd);
42212854Sgabeblack@google.com
42312854Sgabeblack@google.com    // x is longer than y.
42412854Sgabeblack@google.com    small_type s = mul_signs(xs, ys);
42512854Sgabeblack@google.com    if (s > 0) {
42612854Sgabeblack@google.com        if (xs > 0) { // case 3
42712854Sgabeblack@google.com            while (y < yend)
42812854Sgabeblack@google.com                (*d++) = (*x++) | (*y++);
42912854Sgabeblack@google.com            while (x < xend)
43012854Sgabeblack@google.com                (*d++) = (*x++);
43112854Sgabeblack@google.com        } else { // case 4
43212854Sgabeblack@google.com            sc_digit xcarry = 1;
43312854Sgabeblack@google.com            sc_digit ycarry = 1;
43412854Sgabeblack@google.com            while (y < yend) {
43512854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
43612854Sgabeblack@google.com                ycarry += (~(*y++) & DIGIT_MASK);
43712854Sgabeblack@google.com                (*d++) = (xcarry | ycarry) & DIGIT_MASK;
43812854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
43912854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
44012854Sgabeblack@google.com            }
44112854Sgabeblack@google.com            while (x < xend) {
44212854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
44312854Sgabeblack@google.com                ycarry += DIGIT_MASK;
44412854Sgabeblack@google.com                (*d++) = (xcarry | ycarry) & DIGIT_MASK;
44512854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
44612854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
44712854Sgabeblack@google.com            }
44812854Sgabeblack@google.com        }
44912854Sgabeblack@google.com    } else {
45012854Sgabeblack@google.com        if (xs > 0) { // case 5
45112854Sgabeblack@google.com            sc_digit ycarry = 1;
45212854Sgabeblack@google.com            while (y < yend) {
45312854Sgabeblack@google.com                ycarry += (~(*y++) & DIGIT_MASK);
45412854Sgabeblack@google.com                (*d++) = ((*x++) | ycarry) & DIGIT_MASK;
45512854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
45612854Sgabeblack@google.com            }
45712854Sgabeblack@google.com            while (x < xend) {
45812854Sgabeblack@google.com                ycarry += DIGIT_MASK;
45912854Sgabeblack@google.com                (*d++) = ((*x++) | ycarry) & DIGIT_MASK;
46012854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
46112854Sgabeblack@google.com            }
46212854Sgabeblack@google.com        } else { // case 6
46312854Sgabeblack@google.com            sc_digit xcarry = 1;
46412854Sgabeblack@google.com            while (y < yend) {
46512854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
46612854Sgabeblack@google.com                (*d++) = (xcarry | (*y++)) & DIGIT_MASK;
46712854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
46812854Sgabeblack@google.com            }
46912854Sgabeblack@google.com            while (x < xend) {
47012854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
47112854Sgabeblack@google.com                (*d++) = xcarry & DIGIT_MASK;
47212854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
47312854Sgabeblack@google.com            }
47412854Sgabeblack@google.com        }
47512854Sgabeblack@google.com    }
47612854Sgabeblack@google.com    s = convert_signed_2C_to_SM(nb, nd, dbegin);
47712854Sgabeblack@google.com    return CLASS_TYPE(s, nb, nd, dbegin);
47812854Sgabeblack@google.com}
47912854Sgabeblack@google.com
48012854Sgabeblack@google.com
48112854Sgabeblack@google.com// ----------------------------------------------------------------------------
48212854Sgabeblack@google.com//  SECTION: Friend functions for XOR operators.
48312854Sgabeblack@google.com// ----------------------------------------------------------------------------
48412854Sgabeblack@google.com
48512854Sgabeblack@google.com// Handles the cases 3-5 and returns the result.
48612854Sgabeblack@google.comCLASS_TYPE
48712854Sgabeblack@google.comXOR_HELPER(small_type us, int unb, int und, const sc_digit *ud,
48812854Sgabeblack@google.com           small_type vs, int vnb, int vnd, const sc_digit *vd)
48912854Sgabeblack@google.com{
49012854Sgabeblack@google.com    int nb = sc_max(unb, vnb);
49112854Sgabeblack@google.com    int nd = sc_max(und, vnd);
49212854Sgabeblack@google.com
49312854Sgabeblack@google.com#ifdef SC_MAX_NBITS
49412854Sgabeblack@google.com    sc_digit dbegin[MAX_NDIGITS];
49512854Sgabeblack@google.com#else
49612854Sgabeblack@google.com    sc_digit *dbegin = new sc_digit[nd];
49712854Sgabeblack@google.com#endif
49812854Sgabeblack@google.com
49912854Sgabeblack@google.com    sc_digit *d = dbegin;
50012854Sgabeblack@google.com
50112854Sgabeblack@google.com    const sc_digit *x;
50212854Sgabeblack@google.com    const sc_digit *y;
50312854Sgabeblack@google.com    int xnd;
50412854Sgabeblack@google.com    int ynd;
50512854Sgabeblack@google.com    small_type xs;
50612854Sgabeblack@google.com    small_type ys;
50712854Sgabeblack@google.com
50812854Sgabeblack@google.com    if (und >= vnd) {
50912854Sgabeblack@google.com        x = ud;
51012854Sgabeblack@google.com        y = vd;
51112854Sgabeblack@google.com        xnd = und;
51212854Sgabeblack@google.com        ynd = vnd;
51312854Sgabeblack@google.com        xs = us;
51412854Sgabeblack@google.com        ys = vs;
51512854Sgabeblack@google.com    } else {
51612854Sgabeblack@google.com        y = ud;
51712854Sgabeblack@google.com        x = vd;
51812854Sgabeblack@google.com        ynd = und;
51912854Sgabeblack@google.com        xnd = vnd;
52012854Sgabeblack@google.com        ys = us;
52112854Sgabeblack@google.com        xs = vs;
52212854Sgabeblack@google.com    }
52312854Sgabeblack@google.com
52412854Sgabeblack@google.com    const sc_digit *xend = (x + xnd);
52512854Sgabeblack@google.com    const sc_digit *yend = (y + ynd);
52612854Sgabeblack@google.com
52712854Sgabeblack@google.com    // x is longer than y.
52812854Sgabeblack@google.com    small_type s = mul_signs(xs, ys);
52912854Sgabeblack@google.com    if (s > 0) {
53012854Sgabeblack@google.com        if (xs > 0) { // case 3
53112854Sgabeblack@google.com            while (y < yend)
53212854Sgabeblack@google.com                (*d++) = ((*x++) ^ (*y++)) & DIGIT_MASK;
53312854Sgabeblack@google.com            while (x < xend)
53412854Sgabeblack@google.com                (*d++) = (*x++);
53512854Sgabeblack@google.com        } else { // case 4
53612854Sgabeblack@google.com            sc_digit xcarry = 1;
53712854Sgabeblack@google.com            sc_digit ycarry = 1;
53812854Sgabeblack@google.com            while (y < yend) {
53912854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
54012854Sgabeblack@google.com                ycarry += (~(*y++) & DIGIT_MASK);
54112854Sgabeblack@google.com                (*d++) = (xcarry ^ ycarry) & DIGIT_MASK;
54212854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
54312854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
54412854Sgabeblack@google.com            }
54512854Sgabeblack@google.com            while (x < xend) {
54612854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
54712854Sgabeblack@google.com                ycarry += DIGIT_MASK;
54812854Sgabeblack@google.com                (*d++) = (xcarry ^ ycarry) & DIGIT_MASK;
54912854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
55012854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
55112854Sgabeblack@google.com            }
55212854Sgabeblack@google.com        }
55312854Sgabeblack@google.com    } else {
55412854Sgabeblack@google.com        if (xs > 0) { // case 5
55512854Sgabeblack@google.com            sc_digit ycarry = 1;
55612854Sgabeblack@google.com            while (y < yend) {
55712854Sgabeblack@google.com                ycarry += (~(*y++) & DIGIT_MASK);
55812854Sgabeblack@google.com                (*d++) = ((*x++) ^ ycarry) & DIGIT_MASK;
55912854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
56012854Sgabeblack@google.com            }
56112854Sgabeblack@google.com            while (x < xend) {
56212854Sgabeblack@google.com                ycarry += DIGIT_MASK;
56312854Sgabeblack@google.com                (*d++) = ((*x++) ^ ycarry) & DIGIT_MASK;
56412854Sgabeblack@google.com                ycarry >>= BITS_PER_DIGIT;
56512854Sgabeblack@google.com            }
56612854Sgabeblack@google.com        } else { // case 6
56712854Sgabeblack@google.com            sc_digit xcarry = 1;
56812854Sgabeblack@google.com            while (y < yend) {
56912854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
57012854Sgabeblack@google.com                (*d++) = (xcarry ^ (*y++)) & DIGIT_MASK;
57112854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
57212854Sgabeblack@google.com            }
57312854Sgabeblack@google.com            while (x < xend) {
57412854Sgabeblack@google.com                xcarry += (~(*x++) & DIGIT_MASK);
57512854Sgabeblack@google.com                (*d++) = xcarry & DIGIT_MASK;
57612854Sgabeblack@google.com                xcarry >>= BITS_PER_DIGIT;
57712854Sgabeblack@google.com            }
57812854Sgabeblack@google.com        }
57912854Sgabeblack@google.com    }
58012854Sgabeblack@google.com    s = convert_signed_2C_to_SM(nb, nd, dbegin);
58112854Sgabeblack@google.com    return CLASS_TYPE(s, nb, nd, dbegin);
58212854Sgabeblack@google.com}
583