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_nbexterns.cpp -- External functions for both sc_signed and sc_unsigned
23 classes. These functions work on two parameters u and
24 v, and copy the result to the first parameter u. This
25 is also the reason that they are suffixed with _on_help.
26
27 Original Author: Ali Dasdan, Synopsys, Inc.
28
29 *****************************************************************************/
30
31 /*****************************************************************************
32
33 MODIFICATION LOG - modifiers, enter your name, affiliation, date and
34 changes you are making here.
35
36 Name, Affiliation, Date:
37 Description of Modification:
38
39 *****************************************************************************/
40
41
42 // $Log: sc_nbexterns.cpp,v $
43 // Revision 1.2 2011/02/18 20:19:15 acg
44 // Andy Goodrich: updating Copyright notice.
45 //
46 // Revision 1.1.1.1 2006/12/15 20:20:05 acg
47 // SystemC 2.3
48 //
49 // Revision 1.3 2006/01/13 18:49:32 acg
50 // Added $Log command so that CVS check in comments are reproduced in the
51 // source.
52 //
53
54 #include "sysc/datatypes/int/sc_nbexterns.h"
55 #include "sysc/kernel/sc_macros.h"
56
57
58 namespace sc_dt
59 {
60
61 // ----------------------------------------------------------------------------
62 // SECTION: External functions for PLUS operators.
63 // ----------------------------------------------------------------------------
64
65 // Handles the cases 3 and 4 and returns the result in u.
66 void
add_on_help(small_type & us,int,int und,sc_digit * ud,small_type vs,int,int vnd,const sc_digit * vd)67 add_on_help(small_type &us, int /* unb */, int und,
68 sc_digit *ud,
69 small_type vs, int /* vnb */, int vnd,
70 const sc_digit *vd)
71 {
72
73 vnd = vec_skip_leading_zeros(vnd, vd);
74
75 if (us == vs) { // case 3
76
77 if (und >= vnd)
78 vec_add_on(und, ud, vnd, vd);
79 else
80 vec_add_on2(und, ud, vnd, vd);
81
82 }
83 else { // case 4
84
85 // vec_cmp expects that und is the number of non-zero digits in ud.
86 int new_und = vec_skip_leading_zeros(und, ud);
87 int cmp_res = vec_cmp(new_und, ud, vnd, vd);
88
89 if (cmp_res == 0) { // u == v
90 us = SC_ZERO;
91 vec_zero(und, ud);
92 return;
93 }
94
95 if (cmp_res > 0) // u > v
96 vec_sub_on(und, ud, vnd, vd);
97
98 else { // u < v
99 us = -us;
100 vec_sub_on2(und, ud, vnd, vd);
101 }
102
103 }
104 }
105
106
107 // ----------------------------------------------------------------------------
108
109 /*
110
111 mul_on_help_signed and mul_on_help_unsigned have the same body except
112 that CONVERT_SM_to_2C_to_SM and COPY_DIGITS are defined for signed and
113 unsigned, respectively. This comment also applies to the
114 signed/unsigned versions of div_on_help and mod_on_help. It is
115 possible to take COPY_DIGITS out of these functions and create a
116 single version of each of these helper functions; however, this will
117 impose an onverhead on performance. In the versions below, any change
118 in the signed version of a helper function must be carried to a
119 corresponding change in the unsigned verion of the same function or
120 vice versa.
121
122 */
123
124
125 // ----------------------------------------------------------------------------
126 // SECTION: External functions of MULTIPLICATION operators.
127 // ----------------------------------------------------------------------------
128
129 void
mul_on_help_signed(small_type & us,int unb,int und,sc_digit * ud,int vnb,int vnd,const sc_digit * vd)130 mul_on_help_signed(small_type &us,
131 int unb, int und,
132 sc_digit *ud,
133 int vnb, int vnd,
134 const sc_digit *vd)
135 {
136 #define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM
137 #define COPY_DIGITS copy_digits_signed
138
139 { // Body of mul_on_help
140
141 int old_und = und;
142
143 und = vec_skip_leading_zeros(und, ud);
144 vnd = vec_skip_leading_zeros(vnd, vd);
145
146 sc_digit ud0 = (*ud);
147 sc_digit vd0 = (*vd);
148
149 if ((vnd == 1) && (vd0 == 1)) {
150 us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
151 return;
152 }
153
154 if ((und == 1) && (ud0 == 1)) {
155 COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd);
156 return;
157 }
158
159 if ((und == 1) && (vnd == 1) &&
160 (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
161
162 sc_digit d = ud0 * vd0;
163 COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d);
164 return;
165
166 }
167
168 int nd = und + vnd;
169
170 #ifdef SC_MAX_NBITS
171 sc_digit d[MAX_NDIGITS];
172 #else
173 sc_digit *d = new sc_digit[nd];
174 #endif
175
176 vec_zero(nd, d);
177
178 if ((und == 1) && (ud0 < HALF_DIGIT_RADIX))
179 vec_mul_small(vnd, vd, ud0, d);
180
181 else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
182 vec_mul_small(und, ud, vd0, d);
183
184 else if (vnd < und)
185 vec_mul(und, ud, vnd, vd, d);
186
187 else
188 vec_mul(vnd, vd, und, ud, d);
189
190 COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d);
191
192 #ifndef SC_MAX_NBITS
193 delete [] d;
194 #endif
195
196 }
197
198 #undef COPY_DIGITS
199 #undef CONVERT_SM_to_2C_to_SM
200
201 }
202
203
204 void
mul_on_help_unsigned(small_type & us,int unb,int und,sc_digit * ud,int vnb,int vnd,const sc_digit * vd)205 mul_on_help_unsigned(small_type &us,
206 int unb, int und,
207 sc_digit *ud,
208 int vnb, int vnd,
209 const sc_digit *vd)
210 {
211 #define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM
212 #define COPY_DIGITS copy_digits_unsigned
213
214 { // Body of mul_on_help
215
216 int old_und = und;
217
218 und = vec_skip_leading_zeros(und, ud);
219 vnd = vec_skip_leading_zeros(vnd, vd);
220
221 sc_digit ud0 = (*ud);
222 sc_digit vd0 = (*vd);
223
224 if ((vnd == 1) && (vd0 == 1)) {
225 us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
226 return;
227 }
228
229 if ((und == 1) && (ud0 == 1)) {
230 COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd);
231 return;
232 }
233
234 if ((und == 1) && (vnd == 1) &&
235 (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
236
237 sc_digit d = ud0 * vd0;
238 COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d);
239 return;
240
241 }
242
243 int nd = und + vnd;
244
245 #ifdef SC_MAX_NBITS
246 sc_digit d[MAX_NDIGITS];
247 #else
248 sc_digit *d = new sc_digit[nd];
249 #endif
250
251 vec_zero(nd, d);
252
253 if ((und == 1) && (ud0 < HALF_DIGIT_RADIX))
254 vec_mul_small(vnd, vd, ud0, d);
255
256 else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
257 vec_mul_small(und, ud, vd0, d);
258
259 else if (vnd < und)
260 vec_mul(und, ud, vnd, vd, d);
261
262 else
263 vec_mul(vnd, vd, und, ud, d);
264
265 COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d);
266
267 #ifndef SC_MAX_NBITS
268 delete [] d;
269 #endif
270
271 }
272
273 #undef COPY_DIGITS
274 #undef CONVERT_SM_to_2C_to_SM
275
276 }
277
278
279 // ----------------------------------------------------------------------------
280 // SECTION: External functions for DIVISION operators.
281 // ----------------------------------------------------------------------------
282
283 void
div_on_help_signed(small_type & us,int unb,int und,sc_digit * ud,int vnb,int vnd,const sc_digit * vd)284 div_on_help_signed(small_type &us,
285 int unb, int und,
286 sc_digit *ud,
287 int vnb, int vnd,
288 const sc_digit *vd)
289 {
290 #define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM
291 #define COPY_DIGITS copy_digits_signed
292
293 { // Body of div_on_help
294
295 int old_und = und;
296
297 und = vec_skip_leading_zeros(und, ud);
298 vnd = vec_skip_leading_zeros(vnd, vd);
299
300 int cmp_res = vec_cmp(und, ud, vnd, vd);
301
302 if (cmp_res < 0) { // u < v => u / v = 0 - case 4
303 us = SC_ZERO;
304 vec_zero(old_und, ud);
305 return;
306 }
307
308 sc_digit vd0 = (*vd);
309
310 if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) {
311 us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
312 return;
313 }
314
315 // One extra digit for d is allocated to simplify vec_div_*().
316 int nd = sc_max(und, vnd) + 1;
317
318 #ifdef SC_MAX_NBITS
319 sc_digit d[MAX_NDIGITS + 1];
320 #else
321 sc_digit *d = new sc_digit[nd];
322 #endif
323
324 vec_zero(nd, d);
325
326 // u = v => u / v = 1 - case 3
327 if (cmp_res == 0)
328 d[0] = 1;
329
330 else if ((vnd == 1) && (und == 1))
331 d[0] = (*ud) / vd0;
332
333 else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
334 vec_div_small(und, ud, vd0, d);
335
336 else
337 vec_div_large(und, ud, vnd, vd, d);
338
339 COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d);
340
341 #ifndef SC_MAX_NBITS
342 delete [] d;
343 #endif
344
345 }
346
347 #undef COPY_DIGITS
348 #undef CONVERT_SM_to_2C_to_SM
349
350 }
351
352
353 void
div_on_help_unsigned(small_type & us,int unb,int und,sc_digit * ud,int vnb,int vnd,const sc_digit * vd)354 div_on_help_unsigned(small_type &us,
355 int unb, int und,
356 sc_digit *ud,
357 int vnb, int vnd,
358 const sc_digit *vd)
359 {
360 #define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM
361 #define COPY_DIGITS copy_digits_unsigned
362
363 { // Body of div_on_help
364
365 int old_und = und;
366
367 und = vec_skip_leading_zeros(und, ud);
368 vnd = vec_skip_leading_zeros(vnd, vd);
369
370 int cmp_res = vec_cmp(und, ud, vnd, vd);
371
372 if (cmp_res < 0) { // u < v => u / v = 0 - case 4
373 us = SC_ZERO;
374 vec_zero(old_und, ud);
375 return;
376 }
377
378 sc_digit vd0 = (*vd);
379
380 if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) {
381 us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
382 return;
383 }
384
385 // One extra digit for d is allocated to simplify vec_div_*().
386 int nd = sc_max(und, vnd) + 1;
387
388 #ifdef SC_MAX_NBITS
389 sc_digit d[MAX_NDIGITS + 1];
390 #else
391 sc_digit *d = new sc_digit[nd];
392 #endif
393
394 vec_zero(nd, d);
395
396 // u = v => u / v = 1 - case 3
397 if (cmp_res == 0)
398 d[0] = 1;
399
400 else if ((vnd == 1) && (und == 1))
401 d[0] = (*ud) / vd0;
402
403 else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
404 vec_div_small(und, ud, vd0, d);
405
406 else
407 vec_div_large(und, ud, vnd, vd, d);
408
409 COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d);
410
411 #ifndef SC_MAX_NBITS
412 delete [] d;
413 #endif
414
415 }
416
417 #undef COPY_DIGITS
418 #undef CONVERT_SM_to_2C_to_SM
419
420 }
421
422
423 // ----------------------------------------------------------------------------
424 // SECTION: External functions for MOD operators.
425 // ----------------------------------------------------------------------------
426
427 void
mod_on_help_signed(small_type & us,int unb,int und,sc_digit * ud,int,int vnd,const sc_digit * vd)428 mod_on_help_signed(small_type &us,
429 int unb, int und,
430 sc_digit *ud,
431 int /* vnb */, int vnd,
432 const sc_digit *vd)
433 {
434
435 #define COPY_DIGITS copy_digits_signed
436
437 { // Body of mod_on_help
438
439 int old_und = und;
440
441 und = vec_skip_leading_zeros(und, ud);
442 vnd = vec_skip_leading_zeros(vnd, vd);
443
444 int cmp_res = vec_cmp(und, ud, vnd, vd);
445
446 // u < v => u % v = u - case 4
447 if (cmp_res < 0)
448 return;
449
450 // u = v => u % v = 0 - case 3
451 if (cmp_res == 0) {
452 us = SC_ZERO;
453 vec_zero(old_und, ud);
454 return;
455 }
456
457 // else if u > v - case 5
458
459 sc_digit vd0 = (*vd);
460
461 if ((vnd == 1) && (vd0 == 1)) {
462 us = SC_ZERO;
463 vec_zero(old_und, ud);
464 return;
465 }
466
467 // One extra digit for d is allocated to simplify vec_div_*().
468 int nd = sc_max(und, vnd) + 1;
469
470 #ifdef SC_MAX_NBITS
471 sc_digit d[MAX_NDIGITS + 1];
472 #else
473 sc_digit *d = new sc_digit[nd];
474 #endif
475
476 vec_zero(nd, d);
477
478 if ((vnd == 1) && (und == 1))
479 d[0] = (*ud) % vd0;
480
481 if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
482 d[0] = vec_rem_small(und, ud, vd0);
483
484 else
485 vec_rem_large(und, ud, vnd, vd, d);
486
487 us = check_for_zero(us, nd - 1, d);
488
489 if (us == SC_ZERO)
490 vec_zero(old_und, ud);
491 else
492 COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d);
493
494 #ifndef SC_MAX_NBITS
495 delete [] d;
496 #endif
497
498 }
499
500 #undef COPY_DIGITS
501
502 }
503
504
505 void
mod_on_help_unsigned(small_type & us,int unb,int und,sc_digit * ud,int,int vnd,const sc_digit * vd)506 mod_on_help_unsigned(small_type &us,
507 int unb, int und,
508 sc_digit *ud,
509 int /* vnb */, int vnd,
510 const sc_digit *vd)
511 {
512
513 #define COPY_DIGITS copy_digits_unsigned
514
515 { // Body of mod_on_help
516
517 int old_und = und;
518
519 und = vec_skip_leading_zeros(und, ud);
520 vnd = vec_skip_leading_zeros(vnd, vd);
521
522 int cmp_res = vec_cmp(und, ud, vnd, vd);
523
524 // u < v => u % v = u - case 4
525 if (cmp_res < 0)
526 return;
527
528 // u = v => u % v = 0 - case 3
529 if (cmp_res == 0) {
530 us = SC_ZERO;
531 vec_zero(old_und, ud);
532 return;
533 }
534
535 // else if u > v - case 5
536
537 sc_digit vd0 = (*vd);
538
539 if ((vnd == 1) && (vd0 == 1)) {
540 us = SC_ZERO;
541 vec_zero(old_und, ud);
542 return;
543 }
544
545 // One extra digit for d is allocated to simplify vec_div_*().
546 int nd = sc_max(und, vnd) + 1;
547
548 #ifdef SC_MAX_NBITS
549 sc_digit d[MAX_NDIGITS + 1];
550 #else
551 sc_digit *d = new sc_digit[nd];
552 #endif
553
554 vec_zero(nd, d);
555
556 if ((vnd == 1) && (und == 1))
557 d[0] = (*ud) % vd0;
558
559 if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
560 d[0] = vec_rem_small(und, ud, vd0);
561
562 else
563 vec_rem_large(und, ud, vnd, vd, d);
564
565 us = check_for_zero(us, nd - 1, d);
566
567 if (us == SC_ZERO)
568 vec_zero(old_und, ud);
569 else
570 COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d);
571
572 #ifndef SC_MAX_NBITS
573 delete [] d;
574 #endif
575
576 }
577
578 #undef COPY_DIGITS
579
580 }
581
582
583 // ----------------------------------------------------------------------------
584 // SECTION: External functions for AND operators.
585 // ----------------------------------------------------------------------------
586
587 // Handles the cases 2-5 and returns the result in u.
588 void
and_on_help(small_type us,int,int und,sc_digit * ud,small_type vs,int,int vnd,const sc_digit * vd)589 and_on_help(small_type us,
590 int /* unb */, int und,
591 sc_digit *ud,
592 small_type vs,
593 int /* vnb */, int vnd,
594 const sc_digit *vd)
595 {
596
597 sc_digit *x = ud;
598 const sc_digit *y = vd;
599 int xnd = und;
600 int ynd = vnd;
601
602 // Truncate y.
603 if (xnd < ynd)
604 ynd = xnd;
605
606 const sc_digit *xend = (x + xnd);
607 const sc_digit *yend = (y + ynd);
608
609 // x is longer than y.
610
611 small_type s = mul_signs(us, vs);
612
613 if (s > 0) {
614
615 if (us > 0) { // case 2
616
617 while (y < yend)
618 (*x++) &= (*y++);
619
620 while (x < xend)
621 (*x++) = 0;
622
623 }
624 else { // case 3
625
626 sc_digit xcarry = 1;
627 sc_digit ycarry = 1;
628
629 while (y < yend) {
630 xcarry += (~(*x) & DIGIT_MASK);
631 ycarry += (~(*y++) & DIGIT_MASK);
632 (*x++) = (xcarry & ycarry) & DIGIT_MASK;
633 xcarry >>= BITS_PER_DIGIT;
634 ycarry >>= BITS_PER_DIGIT;
635 }
636
637 while (x < xend) {
638 xcarry += (~(*x) & DIGIT_MASK);
639 ycarry += DIGIT_MASK;
640 (*x++) = (xcarry & ycarry) & DIGIT_MASK;
641 xcarry >>= BITS_PER_DIGIT;
642 ycarry >>= BITS_PER_DIGIT;
643 }
644
645 }
646 }
647 else {
648
649 if (us > 0) { // case 4
650
651 sc_digit ycarry = 1;
652
653 while (y < yend) {
654 ycarry += (~(*y++) & DIGIT_MASK);
655 (*x++) &= ycarry & DIGIT_MASK;
656 ycarry >>= BITS_PER_DIGIT;
657 }
658
659 while (x < xend) {
660 ycarry += DIGIT_MASK;
661 (*x++) &= ycarry & DIGIT_MASK;
662 ycarry >>= BITS_PER_DIGIT;
663 }
664
665 }
666 else { // case 5
667
668 sc_digit xcarry = 1;
669
670 while (y < yend) {
671 xcarry += (~(*x) & DIGIT_MASK);
672 (*x++) = (xcarry & (*y++)) & DIGIT_MASK;
673 xcarry >>= BITS_PER_DIGIT;
674 }
675
676 while (x < xend)
677 (*x++) = 0;
678
679 }
680 }
681 }
682
683
684 // ----------------------------------------------------------------------------
685 // SECTION: External functions for OR operators.
686 // ----------------------------------------------------------------------------
687
688 // Handles the cases 3-5 and returns the result in u.
689 void
or_on_help(small_type us,int,int und,sc_digit * ud,small_type vs,int,int vnd,const sc_digit * vd)690 or_on_help(small_type us,
691 int /* unb */, int und,
692 sc_digit *ud,
693 small_type vs,
694 int /* vnb */, int vnd,
695 const sc_digit *vd)
696 {
697
698 sc_digit *x = ud;
699 const sc_digit *y = vd;
700 int xnd = und;
701 int ynd = vnd;
702
703 if (xnd < ynd)
704 ynd = xnd;
705
706 const sc_digit *xend = (x + xnd);
707 const sc_digit *yend = (y + ynd);
708
709 // x is longer than y.
710
711 small_type s = mul_signs(us, vs);
712
713 if (s > 0) {
714
715 if (us > 0) { // case 3
716
717 while (y < yend)
718 (*x++) |= (*y++);
719
720 // No change for the rest of x.
721
722 }
723 else { // case 4
724
725 sc_digit xcarry = 1;
726 sc_digit ycarry = 1;
727
728 while (y < yend) {
729 xcarry += (~(*x) & DIGIT_MASK);
730 ycarry += (~(*y++) & DIGIT_MASK);
731 (*x++) = (xcarry | ycarry) & DIGIT_MASK;
732 xcarry >>= BITS_PER_DIGIT;
733 ycarry >>= BITS_PER_DIGIT;
734 }
735
736 while (x < xend) {
737 xcarry += (~(*x) & DIGIT_MASK);
738 ycarry += DIGIT_MASK;
739 (*x++) = (xcarry | ycarry) & DIGIT_MASK;
740 xcarry >>= BITS_PER_DIGIT;
741 ycarry >>= BITS_PER_DIGIT;
742 }
743 }
744
745 }
746 else {
747
748 if (us > 0) { // case 5
749
750 sc_digit ycarry = 1;
751
752 while (y < yend) {
753 ycarry += (~(*y++) & DIGIT_MASK);
754 (*x) = ((*x) | ycarry) & DIGIT_MASK;
755 x++;
756 ycarry >>= BITS_PER_DIGIT;
757 }
758
759 while (x < xend) {
760 ycarry += DIGIT_MASK;
761 (*x) = ((*x) | ycarry) & DIGIT_MASK;
762 x++;
763 ycarry >>= BITS_PER_DIGIT;
764 }
765
766 }
767 else { // case 6
768
769 sc_digit xcarry = 1;
770
771 while (y < yend) {
772 xcarry += (~(*x) & DIGIT_MASK);
773 (*x++) = (xcarry | (*y++)) & DIGIT_MASK;
774 xcarry >>= BITS_PER_DIGIT;
775 }
776
777 while (x < xend) {
778 xcarry += (~(*x) & DIGIT_MASK);
779 (*x++) = xcarry & DIGIT_MASK;
780 xcarry >>= BITS_PER_DIGIT;
781 }
782 }
783 }
784 }
785
786
787 // ----------------------------------------------------------------------------
788 // SECTION: External functions for XOR operators.
789 // ----------------------------------------------------------------------------
790
791 // Handles the cases 3-5 and returns the result in u.
792 void
xor_on_help(small_type us,int,int und,sc_digit * ud,small_type vs,int,int vnd,const sc_digit * vd)793 xor_on_help(small_type us,
794 int /* unb */, int und,
795 sc_digit *ud,
796 small_type vs,
797 int /* vnb */, int vnd,
798 const sc_digit *vd)
799 {
800
801 sc_digit *x = ud;
802 const sc_digit *y = vd;
803 int xnd = und;
804 int ynd = vnd;
805
806 if (xnd < ynd)
807 ynd = xnd;
808
809 const sc_digit *xend = (x + xnd);
810 const sc_digit *yend = (y + ynd);
811
812 // x is longer than y.
813
814 small_type s = mul_signs(us, vs);
815
816 if (s > 0) {
817
818 if (us > 0) { // case 3
819
820 while (y < yend) {
821 (*x) = ((*x) ^ (*y)) & DIGIT_MASK;
822 x++;
823 y++;
824 }
825
826 // No change for the rest of x.
827
828 }
829 else { // case 4
830
831 sc_digit xcarry = 1;
832 sc_digit ycarry = 1;
833
834 while (y < yend) {
835 xcarry += (~(*x) & DIGIT_MASK);
836 ycarry += (~(*y++) & DIGIT_MASK);
837 (*x++) = (xcarry ^ ycarry) & DIGIT_MASK;
838 xcarry >>= BITS_PER_DIGIT;
839 ycarry >>= BITS_PER_DIGIT;
840 }
841
842 while (x < xend) {
843 xcarry += (~(*x) & DIGIT_MASK);
844 ycarry += DIGIT_MASK;
845 (*x++) = (xcarry ^ ycarry) & DIGIT_MASK;
846 xcarry >>= BITS_PER_DIGIT;
847 ycarry >>= BITS_PER_DIGIT;
848 }
849 }
850 }
851 else {
852
853 if (us > 0) { // case 5
854
855 sc_digit ycarry = 1;
856
857 while (y < yend) {
858 ycarry += (~(*y++) & DIGIT_MASK);
859 (*x) = ((*x) ^ ycarry) & DIGIT_MASK;
860 x++;
861 ycarry >>= BITS_PER_DIGIT;
862 }
863
864 while (x < xend) {
865 ycarry += DIGIT_MASK;
866 (*x) = ((*x) ^ ycarry) & DIGIT_MASK;
867 x++;
868 ycarry >>= BITS_PER_DIGIT;
869 }
870
871 }
872 else { // case 6
873
874 sc_digit xcarry = 1;
875
876 while (y < yend) {
877 xcarry += (~(*x) & DIGIT_MASK);
878 (*x++) = (xcarry ^ (*y++)) & DIGIT_MASK;
879 xcarry >>= BITS_PER_DIGIT;
880 }
881
882 while (x < xend) {
883 xcarry += (~(*x) & DIGIT_MASK);
884 (*x++) = xcarry & DIGIT_MASK;
885 xcarry >>= BITS_PER_DIGIT;
886 }
887 }
888 }
889 }
890
891 } // namespace sc_dt
892
893
894 // End of file
895