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