1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22  sc_nbfriends.inc -- Friend functions for both sc_signed and sc_unsigned
23                      classes. The vec_* functions are called through either
24                      these functions or those in sc_nbexterns.cpp. These
25                      functions perform their work on two inputs u and v, and
26                      return the result object. The functions in
27                      sc_nbexterns.cpp perform their work on one of their
28                      inputs.
29
30                      The functions here try to use faster algorithms in case
31                      the input numbers are small. The bitwise functions (and,
32                      or, and xor) need the 2's complement representations of
33                      their inputs. Instead of complementing their inputs
34                      first and then processing, they complement their inputs
35                      while processing without allocating extra temporary
36                      memory.
37
38  Original Author: Ali Dasdan, Synopsys, Inc.
39
40 *****************************************************************************/
41
42/*****************************************************************************
43
44  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
45  changes you are making here.
46
47      Name, Affiliation, Date:
48  Description of Modification:
49
50 *****************************************************************************/
51
52
53// ----------------------------------------------------------------------------
54//  Naming conventions:
55//  For sc_signed or sc_unsigned number u:
56//    us : u's sign, unb : u's number of bits,
57//    und : u's number of digits, ud : u's digits array.
58// ----------------------------------------------------------------------------
59
60// ----------------------------------------------------------------------------
61//  SECTION: Friend functions for PLUS operators.
62// ----------------------------------------------------------------------------
63
64// Handles cases 3 and 4 and returns the result.
65CLASS_TYPE
66ADD_HELPER(small_type us, int unb, int und, const sc_digit *ud,
67           small_type vs, int vnb, int vnd, const sc_digit *vd)
68{
69    und = vec_skip_leading_zeros(und, ud);
70    vnd = vec_skip_leading_zeros(vnd, vd);
71
72    int nb = sc_max(unb, vnb);
73    int nd = sc_max(und, vnd) + 1;
74
75#ifdef SC_MAX_NBITS
76    test_bound(nb);
77    sc_digit d[MAX_NDIGITS];
78#else
79    sc_digit *d = new sc_digit[nd];
80#endif
81
82    d[nd - 1] = d[nd - 2] = 0;
83
84    // case 3
85    if (us == vs) {
86
87        ++nb;
88
89        if ((und == 1) && (vnd == 1)) {
90            sc_digit carry = (*ud) + (*vd);
91            d[0] = carry & DIGIT_MASK;
92            d[1] = carry >> BITS_PER_DIGIT;
93        } else if (und >= vnd) {
94            vec_add(und, ud, vnd, vd, d);
95        } else {
96            vec_add(vnd, vd, und, ud, d);
97        }
98    } else {
99        // case 4
100        int cmp_res = vec_cmp(und, ud, vnd, vd);
101
102        if (cmp_res == 0) { // u == v
103#ifndef SC_MAX_NBITS
104            delete[] d;
105#endif
106            return CLASS_TYPE();
107        }
108
109        if (cmp_res > 0) { // u > v
110            if ((und == 1) && (vnd == 1))
111                d[0] = (*ud) - (*vd);
112            else
113                vec_sub(und, ud, vnd, vd, d);
114        } else { // u < v
115            us = -us;
116            if ((und == 1) && (vnd == 1))
117                d[0] = (*vd) - (*ud);
118            else
119                vec_sub(vnd, vd, und, ud, d);
120        }
121    }
122    return CLASS_TYPE(us, nb, nd, d);
123}
124
125
126// ----------------------------------------------------------------------------
127//  SECTION: Friend functions of MULTIPLICATION operators.
128// ----------------------------------------------------------------------------
129
130// Handles the case 4 and returns the result.
131CLASS_TYPE
132MUL_HELPER(small_type s, int unb, int und,  const sc_digit *ud,
133           int vnb, int vnd, const sc_digit *vd)
134{
135    und = vec_skip_leading_zeros(und, ud);
136    vnd = vec_skip_leading_zeros(vnd, vd);
137
138    int nb = unb + vnb;
139    int nd = und + vnd;
140
141#ifdef SC_MAX_NBITS
142    test_bound(nb);
143    sc_digit d[MAX_NDIGITS];
144#else
145    sc_digit *d = new sc_digit[nd];
146#endif
147
148    vec_zero(nd, d);
149
150    sc_digit ud0 = (*ud);
151    sc_digit vd0 = (*vd);
152
153    if ((vnd == 1) && (vd0 == 1)) {
154        vec_copy(und, d, ud);
155    } else if ((und == 1) && (ud0 == 1)) {
156        vec_copy(vnd, d, vd);
157    } else if ((und == 1) && (vnd == 1) &&
158               (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
159        d[0] = ud0 * vd0;
160    } else if ((und == 1) && (ud0 < HALF_DIGIT_RADIX)) {
161        vec_mul_small(vnd, vd, ud0, d);
162    } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
163        vec_mul_small(und, ud, vd0, d);
164    } else if (vnd < und) {
165        vec_mul(und, ud, vnd, vd, d);
166    } else {
167        vec_mul(vnd, vd, und, ud, d);
168    }
169    return CLASS_TYPE(s, nb, nd, d);
170}
171
172
173// ----------------------------------------------------------------------------
174//  SECTION: Friend functions for DIVISION operators.
175// ----------------------------------------------------------------------------
176
177// Handles the cases 3-4 and returns the result.
178CLASS_TYPE
179DIV_HELPER(small_type s, int unb, int und, const sc_digit *ud,
180           int vnb, int vnd, const sc_digit *vd)
181{
182    und = vec_skip_leading_zeros(und, ud);
183    vnd = vec_skip_leading_zeros(vnd, vd);
184
185    int cmp_res = vec_cmp(und, ud, vnd, vd);
186
187    // u < v => u / v = 0 - case 4
188    if (cmp_res < 0)
189        return CLASS_TYPE();
190
191    // One extra digit for d is allocated to simplify vec_div_*().
192    int nd = sc_max(und, vnd) + 1;
193
194#ifdef SC_MAX_NBITS
195    sc_digit d[MAX_NDIGITS + 1];
196#else
197    sc_digit *d = new sc_digit[nd];
198#endif
199
200    vec_zero(nd, d);
201    sc_digit vd0 = (*vd);
202
203    // u = v => u / v = 1 - case 3
204    if (cmp_res == 0) {
205        d[0] = 1;
206    // else if u > v - case 5
207    } else if ((vnd == 1) && (vd0 == 1)) {
208        vec_copy(und, d, ud);
209    } else if ((vnd == 1) && (und == 1)) {
210        d[0] = (*ud) / vd0;
211    } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
212        vec_div_small(und, ud, vd0, d);
213    } else {
214        vec_div_large(und, ud, vnd, vd, d);
215    }
216
217    return CLASS_TYPE(s, sc_max(unb, vnb), nd - 1, d);
218}
219
220
221// ----------------------------------------------------------------------------
222//  SECTION: Friend functions for MOD operators.
223// ----------------------------------------------------------------------------
224
225// Handles the cases 3-4 and returns the result.
226CLASS_TYPE
227MOD_HELPER(small_type us, int unb, int und, const sc_digit *ud,
228           int vnb, int vnd, const sc_digit *vd)
229{
230    und = vec_skip_leading_zeros(und, ud);
231    vnd = vec_skip_leading_zeros(vnd, vd);
232
233    int cmp_res = vec_cmp(und, ud, vnd, vd);
234    // u = v => u % v = 0 - case 3
235    if (cmp_res == 0)
236        return CLASS_TYPE();
237
238    sc_digit vd0 = (*vd);
239    if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1))
240        return CLASS_TYPE();
241
242    // One extra digit for d is allocated to simplify vec_div_*().
243    int nd = sc_max(und, vnd) + 1;
244
245#ifdef SC_MAX_NBITS
246    sc_digit d[MAX_NDIGITS + 1];
247#else
248    sc_digit *d = new sc_digit[nd];
249#endif
250
251    vec_zero(nd, d);
252
253    // u < v => u % v = u - case 4
254    if (cmp_res < 0) {
255        vec_copy(und, d, ud);
256    // else if u > v - case 5
257    } else if ((vnd == 1) && (und == 1)) {
258        d[0] = (*ud) % vd0;
259    } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
260        d[0] = vec_rem_small(und, ud, vd0);
261    } else {
262        vec_rem_large(und, ud, vnd, vd, d);
263    }
264
265    us = check_for_zero(us, nd - 1, d);
266
267    if (us == SC_ZERO) {
268#ifndef SC_MAX_NBITS
269        delete[] d;
270#endif
271        return CLASS_TYPE();
272    } else {
273        return CLASS_TYPE(us, sc_min(unb, vnb), nd - 1, d);
274    }
275}
276
277
278// ----------------------------------------------------------------------------
279//  SECTION: Friend functions for AND operators.
280// ----------------------------------------------------------------------------
281
282// Handles the cases 2-5 and returns the result.
283CLASS_TYPE
284AND_HELPER(small_type us, int unb, int und, const sc_digit *ud,
285           small_type vs, int vnb, int vnd, const sc_digit *vd)
286{
287    int nb = sc_max(unb, vnb);
288    int nd = sc_max(und, vnd);
289
290#ifdef SC_MAX_NBITS
291    sc_digit dbegin[MAX_NDIGITS];
292#else
293    sc_digit *dbegin = new sc_digit[nd];
294#endif
295
296    sc_digit *d = dbegin;
297
298    const sc_digit *x;
299    const sc_digit *y;
300    int xnd;
301    int ynd;
302    small_type xs;
303    small_type ys;
304
305    if (und >= vnd) {
306        x = ud;
307        y = vd;
308        xnd = und;
309        ynd = vnd;
310        xs = us;
311        ys = vs;
312    } else {
313        y = ud;
314        x = vd;
315        ynd = und;
316        xnd = vnd;
317        ys = us;
318        xs = vs;
319    }
320
321    const sc_digit *xend = (x + xnd);
322    const sc_digit *yend = (y + ynd);
323
324    // x is longer than y.
325    small_type s = mul_signs(xs, ys);
326    if (s > 0) {
327        if (xs > 0) { // case 2
328            while (y < yend)
329                (*d++) = (*x++) & (*y++);
330            while (x++ < xend)
331                (*d++) = 0;
332        } else { // case 3
333            sc_digit xcarry = 1;
334            sc_digit ycarry = 1;
335            while (y < yend) {
336                xcarry += (~(*x++) & DIGIT_MASK);
337                ycarry += (~(*y++) & DIGIT_MASK);
338                (*d++) = (xcarry & ycarry) & DIGIT_MASK;
339                xcarry >>= BITS_PER_DIGIT;
340                ycarry >>= BITS_PER_DIGIT;
341            }
342            while (x < xend) {
343                xcarry += (~(*x++) & DIGIT_MASK);
344                ycarry += DIGIT_MASK;
345                (*d++) = (xcarry & ycarry) & DIGIT_MASK;
346                xcarry >>= BITS_PER_DIGIT;
347                ycarry >>= BITS_PER_DIGIT;
348            }
349        }
350    } else {
351        if (xs > 0) { // case 4
352            sc_digit ycarry = 1;
353            while (y < yend) {
354                ycarry += (~(*y++) & DIGIT_MASK);
355                (*d++) = ((*x++) & ycarry) & DIGIT_MASK;
356                ycarry >>= BITS_PER_DIGIT;
357            }
358            while (x < xend) {
359                ycarry += DIGIT_MASK;
360                (*d++) = ((*x++) & ycarry) & DIGIT_MASK;
361                ycarry >>= BITS_PER_DIGIT;
362            }
363        } else { // case 5
364            sc_digit xcarry = 1;
365            while (y < yend) {
366                xcarry += (~(*x++) & DIGIT_MASK);
367                (*d++) = (xcarry & (*y++)) & DIGIT_MASK;
368                xcarry >>= BITS_PER_DIGIT;
369            }
370            while (x++ < xend)
371                (*d++) = 0;
372        }
373    }
374    s = convert_signed_2C_to_SM(nb, nd, dbegin);
375    return CLASS_TYPE(s, nb, nd, dbegin);
376}
377
378
379// ----------------------------------------------------------------------------
380//  SECTION: Friend functions for OR operators.
381// ----------------------------------------------------------------------------
382
383// Handles the cases 3-5 and returns the result.
384CLASS_TYPE
385OR_HELPER(small_type us, int unb, int und, const sc_digit *ud,
386          small_type vs, int vnb, int vnd, const sc_digit *vd)
387{
388    int nb = sc_max(unb, vnb);
389    int nd = sc_max(und, vnd);
390
391#ifdef SC_MAX_NBITS
392    sc_digit dbegin[MAX_NDIGITS];
393#else
394    sc_digit *dbegin = new sc_digit[nd];
395#endif
396    sc_digit *d = dbegin;
397    const sc_digit *x;
398    const sc_digit *y;
399    int xnd;
400    int ynd;
401    small_type xs;
402    small_type ys;
403
404    if (und >= vnd) {
405        x = ud;
406        y = vd;
407        xnd = und;
408        ynd = vnd;
409        xs = us;
410        ys = vs;
411    } else {
412        y = ud;
413        x = vd;
414        ynd = und;
415        xnd = vnd;
416        ys = us;
417        xs = vs;
418    }
419
420    const sc_digit *xend = (x + xnd);
421    const sc_digit *yend = (y + ynd);
422
423    // x is longer than y.
424    small_type s = mul_signs(xs, ys);
425    if (s > 0) {
426        if (xs > 0) { // case 3
427            while (y < yend)
428                (*d++) = (*x++) | (*y++);
429            while (x < xend)
430                (*d++) = (*x++);
431        } else { // case 4
432            sc_digit xcarry = 1;
433            sc_digit ycarry = 1;
434            while (y < yend) {
435                xcarry += (~(*x++) & DIGIT_MASK);
436                ycarry += (~(*y++) & DIGIT_MASK);
437                (*d++) = (xcarry | ycarry) & DIGIT_MASK;
438                xcarry >>= BITS_PER_DIGIT;
439                ycarry >>= BITS_PER_DIGIT;
440            }
441            while (x < xend) {
442                xcarry += (~(*x++) & DIGIT_MASK);
443                ycarry += DIGIT_MASK;
444                (*d++) = (xcarry | ycarry) & DIGIT_MASK;
445                xcarry >>= BITS_PER_DIGIT;
446                ycarry >>= BITS_PER_DIGIT;
447            }
448        }
449    } else {
450        if (xs > 0) { // case 5
451            sc_digit ycarry = 1;
452            while (y < yend) {
453                ycarry += (~(*y++) & DIGIT_MASK);
454                (*d++) = ((*x++) | ycarry) & DIGIT_MASK;
455                ycarry >>= BITS_PER_DIGIT;
456            }
457            while (x < xend) {
458                ycarry += DIGIT_MASK;
459                (*d++) = ((*x++) | ycarry) & DIGIT_MASK;
460                ycarry >>= BITS_PER_DIGIT;
461            }
462        } else { // case 6
463            sc_digit xcarry = 1;
464            while (y < yend) {
465                xcarry += (~(*x++) & DIGIT_MASK);
466                (*d++) = (xcarry | (*y++)) & DIGIT_MASK;
467                xcarry >>= BITS_PER_DIGIT;
468            }
469            while (x < xend) {
470                xcarry += (~(*x++) & DIGIT_MASK);
471                (*d++) = xcarry & DIGIT_MASK;
472                xcarry >>= BITS_PER_DIGIT;
473            }
474        }
475    }
476    s = convert_signed_2C_to_SM(nb, nd, dbegin);
477    return CLASS_TYPE(s, nb, nd, dbegin);
478}
479
480
481// ----------------------------------------------------------------------------
482//  SECTION: Friend functions for XOR operators.
483// ----------------------------------------------------------------------------
484
485// Handles the cases 3-5 and returns the result.
486CLASS_TYPE
487XOR_HELPER(small_type us, int unb, int und, const sc_digit *ud,
488           small_type vs, int vnb, int vnd, const sc_digit *vd)
489{
490    int nb = sc_max(unb, vnb);
491    int nd = sc_max(und, vnd);
492
493#ifdef SC_MAX_NBITS
494    sc_digit dbegin[MAX_NDIGITS];
495#else
496    sc_digit *dbegin = new sc_digit[nd];
497#endif
498
499    sc_digit *d = dbegin;
500
501    const sc_digit *x;
502    const sc_digit *y;
503    int xnd;
504    int ynd;
505    small_type xs;
506    small_type ys;
507
508    if (und >= vnd) {
509        x = ud;
510        y = vd;
511        xnd = und;
512        ynd = vnd;
513        xs = us;
514        ys = vs;
515    } else {
516        y = ud;
517        x = vd;
518        ynd = und;
519        xnd = vnd;
520        ys = us;
521        xs = vs;
522    }
523
524    const sc_digit *xend = (x + xnd);
525    const sc_digit *yend = (y + ynd);
526
527    // x is longer than y.
528    small_type s = mul_signs(xs, ys);
529    if (s > 0) {
530        if (xs > 0) { // case 3
531            while (y < yend)
532                (*d++) = ((*x++) ^ (*y++)) & DIGIT_MASK;
533            while (x < xend)
534                (*d++) = (*x++);
535        } else { // case 4
536            sc_digit xcarry = 1;
537            sc_digit ycarry = 1;
538            while (y < yend) {
539                xcarry += (~(*x++) & DIGIT_MASK);
540                ycarry += (~(*y++) & DIGIT_MASK);
541                (*d++) = (xcarry ^ ycarry) & DIGIT_MASK;
542                xcarry >>= BITS_PER_DIGIT;
543                ycarry >>= BITS_PER_DIGIT;
544            }
545            while (x < xend) {
546                xcarry += (~(*x++) & DIGIT_MASK);
547                ycarry += DIGIT_MASK;
548                (*d++) = (xcarry ^ ycarry) & DIGIT_MASK;
549                xcarry >>= BITS_PER_DIGIT;
550                ycarry >>= BITS_PER_DIGIT;
551            }
552        }
553    } else {
554        if (xs > 0) { // case 5
555            sc_digit ycarry = 1;
556            while (y < yend) {
557                ycarry += (~(*y++) & DIGIT_MASK);
558                (*d++) = ((*x++) ^ ycarry) & DIGIT_MASK;
559                ycarry >>= BITS_PER_DIGIT;
560            }
561            while (x < xend) {
562                ycarry += DIGIT_MASK;
563                (*d++) = ((*x++) ^ ycarry) & DIGIT_MASK;
564                ycarry >>= BITS_PER_DIGIT;
565            }
566        } else { // case 6
567            sc_digit xcarry = 1;
568            while (y < yend) {
569                xcarry += (~(*x++) & DIGIT_MASK);
570                (*d++) = (xcarry ^ (*y++)) & DIGIT_MASK;
571                xcarry >>= BITS_PER_DIGIT;
572            }
573            while (x < xend) {
574                xcarry += (~(*x++) & DIGIT_MASK);
575                (*d++) = xcarry & DIGIT_MASK;
576                xcarry >>= BITS_PER_DIGIT;
577            }
578        }
579    }
580    s = convert_signed_2C_to_SM(nb, nd, dbegin);
581    return CLASS_TYPE(s, nb, nd, dbegin);
582}
583