SystemC 3.0.0
Accellera SystemC proof-of-concept library
sc_big_ops.h
Go to the documentation of this file.
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_big_ops.h -- operator implementations for sc_bigint<W> and
23 sc_biguint<W> using twos complement notation.
24
25 This file contains inline implementations that require the other "int"
26 headers to have been included before its contents can be resolved.
27
28 Original Author: Andy Goodrich, Cadence Design Systems
29
30 *****************************************************************************/
31
32#ifndef SC_BIG_OPS_H
33#define SC_BIG_OPS_H
34
35#define SC_BIG_MAX(LEFT,RIGHT) ( (LEFT) > (RIGHT) ? (LEFT) : (RIGHT) )
36#define SC_BIG_MIN(LEFT,RIGHT) ( (LEFT) < (RIGHT) ? (LEFT) : (RIGHT) )
37
38namespace sc_dt {
39
40// +----------------------------------------------------------------------------
41// |"vector_dump"
42// |
43// | This inline function dumps the supplied vector.
44// |
45// | Arguments:
46// | source_hod = index of the high order 'source_p' digit.
47// | source_p = vector of digits to be dumped.
48// +----------------------------------------------------------------------------
49inline
50void
51vector_dump( int source_hod,
52 sc_digit* source_p )
53{
54 for ( int digit_i = source_hod; digit_i >= 0; --digit_i ) {
55 std::cout << std::hex << source_p[digit_i] << " ";
56 }
57 std::cout << std::dec << std::endl;
58}
59
60// +----------------------------------------------------------------------------
61// |"sc_big*int Addition"
62// |
63// | These inline operators implement addition of sc_bigint and sc_biguint
64// | data types.
65// |
66// | Arguments:
67// | result = where to put the result of the addition.
68// | left = first operand of the addition.
69// | right = second operand of the addition.
70// | Result:
71// | Is addition of left and right.
72// +----------------------------------------------------------------------------
73template<typename RESULT, typename LEFT, typename RIGHT>
74inline
75void
76sc_big_add( RESULT& result, const LEFT& left, const RIGHT& right )
77{
78 if ( 0 == RESULT::HOD ) {
79 *result.get_digits() = *left.get_digits() + *right.get_digits();
80 }
81 else if ( 1 == RESULT::HOD ) {
82 const sc_digit* left_p = left.get_digits();
83 int64 left_value;
84 sc_digit* result_p = result.get_digits();
85 int64 result_value;
86 const sc_digit* right_p = right.get_digits();
87 int64 right_value;
88 if ( 1 == LEFT::HOD ) {
89 left_value = ( (int64)left_p[1] << BITS_PER_DIGIT ) | *left_p;
90 }
91 else if ( LEFT::SIGNED ) {
92 left_value = (int64)(int)*left_p;
93 }
94 else {
95 left_value = (int64)*left_p;
96 }
97 if ( 1 == RIGHT::HOD ) {
98 right_value = ( (int64)right_p[1] << BITS_PER_DIGIT ) | *right_p;
99 }
100 else if ( RIGHT::SIGNED ) {
101 right_value = (int64)(int)*right_p;
102 }
103 else {
104 right_value = (int64)*right_p;
105 }
106 result_value = left_value + right_value;
107 *result_p = (sc_digit)result_value;
108 result_p[1] = (result_value >> BITS_PER_DIGIT);
109 }
110 else if ( (int)LEFT::HOD >= (int)RIGHT::HOD ) {
111 vector_add( LEFT::HOD, left.get_digits(),
112 RIGHT::HOD, right.get_digits(),
113 RESULT::HOD, result.get_digits() );
114 }
115 else {
116 vector_add( RIGHT::HOD, right.get_digits(),
117 LEFT::HOD, left.get_digits(),
118 RESULT::HOD, result.get_digits() );
119 }
120}
121
122template<int WL, int WR>
123inline
125operator + ( const sc_bigint<WL>& left, const sc_bigint<WR>& right )
126{
128 // sc_big_add<WL,true,WR,true>(result, left, right);
129 sc_big_add(result, left, right);
130 return result;
131}
132
133template<int WL, int WR>
134inline
136operator + ( const sc_biguint<WL>& left, const sc_bigint<WR>& right )
137{
139 sc_big_add(result, left, right);
140 return result;
141}
142
143template<int WL, int WR>
144inline
146operator + ( const sc_bigint<WL>& left, const sc_biguint<WR>& right )
147{
149 // sc_big_add<WL,false,WR,true>(result, left, right);
150 sc_big_add(result, left, right);
151 return result;
152}
153
154template<int WL, int WR>
155inline
157operator + ( const sc_biguint<WL>& left, const sc_biguint<WR>& right )
158{
160 // sc_big_add<WL,false,WR,false>(result, left, right);
161 sc_big_add(result, left, right);
162 return result;
163}
164
165// +----------------------------------------------------------------------------
166// |"sc_big*int Bitwise Logical And"
167// |
168// | These inline operators implement bit-wise logical ands of sc_bigint and
169// | sc_biguint data types.
170// |
171// | Arguments:
172// | result = where to put result of the bit-wise logical and.
173// | left = first operand of the bit-wise logical and.
174// | right = second operand of the bit-wise logical and.
175// | Result:
176// | Is bit-wise logical and of left and right.
177// +----------------------------------------------------------------------------
178template<typename RESULT, typename LEFT, typename RIGHT>
179inline
180void
181sc_big_and( RESULT& result, const LEFT& left, const RIGHT& right )
182{
183 if ( 0 == RESULT::HOD ) {
184 *result.get_digits() = *left.get_digits() & *right.get_digits();
185 }
186 else if ( 1 == RESULT::HOD ) {
187 const sc_digit* left_p = left.get_digits();
188 int64 left_value;
189 sc_digit* result_p = result.get_digits();
190 int64 result_value;
191 const sc_digit* right_p = right.get_digits();
192 int64 right_value;
193 if ( 1 == LEFT::HOD ) {
194 left_value = ( (int64)left_p[1] << BITS_PER_DIGIT ) | *left_p;
195 }
196 else if ( LEFT::SIGNED ) {
197 left_value = (int64)(int)*left_p;
198 }
199 else {
200 left_value = (int64)*left_p;
201 }
202 if ( 1 == RIGHT::HOD ) {
203 right_value = ( (int64)right_p[1] << BITS_PER_DIGIT ) | *right_p;
204 }
205 else if ( RIGHT::SIGNED ) {
206 right_value = (int64)(int)*right_p;
207 }
208 else {
209 right_value = (int64)*right_p;
210 }
211 result_value = left_value & right_value;
212 *result_p = result_value;
213 result_p[1] = (result_value >> BITS_PER_DIGIT);
214 }
215 else if ( (const int)LEFT::HOD >= (const int)RIGHT::HOD ) {
216 vector_and<LEFT::SIGNED,RIGHT::SIGNED>( LEFT::HOD,
217 left.get_digits(),
218 RIGHT::HOD,
219 right.get_digits(),
220 result.get_digits() );
221 }
222 else {
223 vector_and<RIGHT::SIGNED,LEFT::SIGNED>( RIGHT::HOD,
224 right.get_digits(),
225 LEFT::HOD,
226 left.get_digits(),
227 result.get_digits() );
228 }
229}
230
231template<int WL, int WR>
232inline
234operator & ( const sc_bigint<WL>& left, const sc_bigint<WR>& right )
235{
237 sc_big_and(result, left, right);
238 return result;
239}
240
241template<int WL, int WR>
242inline
244operator & ( const sc_biguint<WL>& left, const sc_bigint<WR>& right )
245{
247 sc_big_and(result, left, right);
248 return result;
249}
250
251template<int WL, int WR>
252inline
254operator & ( const sc_bigint<WL>& left, const sc_biguint<WR>& right )
255{
257 sc_big_and(result, left, right);
258 return result;
259}
260
261template<int WL, int WR>
262inline
264operator & ( const sc_biguint<WL>& left, const sc_biguint<WR>& right )
265{
267 sc_big_and(result, left, right);
268 return result;
269}
270
271// +----------------------------------------------------------------------------
272// |"sc_big*int Bitwise Logical Or"
273// |
274// | These inline operators implement bit-wise logical ors of sc_bigint and
275// | sc_biguint data types.
276// |
277// | Arguments:
278// | result = where to put result of the bit-wise logical or.
279// | left = first operand of the bit-wise logical or.
280// | right = second operand of the bit-wise logical or.
281// | Result:
282// | Is the bit-wise bit-wise logical or of left and right.
283// +----------------------------------------------------------------------------
284template<typename RESULT, typename LEFT, typename RIGHT>
285inline
286void
287sc_big_or( RESULT& result, const LEFT& left, const RIGHT& right )
288{
289 if ( 0 == RESULT::HOD ) {
290 *result.get_digits() = *left.get_digits() | *right.get_digits();
291 }
292 else if ( 1 == RESULT::HOD ) {
293 const sc_digit* left_p = left.get_digits();
294 int64 left_value;
295 sc_digit* result_p = result.get_digits();
296 int64 result_value;
297 const sc_digit* right_p = right.get_digits();
298 int64 right_value;
299 if ( 1 == LEFT::HOD ) {
300 left_value = ( (int64)left_p[1] << BITS_PER_DIGIT ) | *left_p;
301 }
302 else if ( LEFT::SIGNED ) {
303 left_value = (int64)(int)*left_p;
304 }
305 else {
306 left_value = (int64)*left_p;
307 }
308 if ( 1 == RIGHT::HOD ) {
309 right_value = ( (int64)right_p[1] << BITS_PER_DIGIT ) | *right_p;
310 }
311 else if ( RIGHT::SIGNED ) {
312 right_value = (int64)(int)*right_p;
313 }
314 else {
315 right_value = (int64)*right_p;
316 }
317 result_value = left_value | right_value;
318 *result_p = result_value;
319 result_p[1] = (result_value >> BITS_PER_DIGIT);
320 }
321 else if ( (const int)LEFT::HOD >= (const int)RIGHT::HOD ) {
322 vector_or<LEFT::SIGNED,RIGHT::SIGNED>( LEFT::HOD,
323 left.get_digits(),
324 RIGHT::HOD,
325 right.get_digits(),
326 result.get_digits() );
327 }
328 else {
329 vector_or<RIGHT::SIGNED,LEFT::SIGNED>( RIGHT::HOD,
330 right.get_digits(),
331 LEFT::HOD,
332 left.get_digits(),
333 result.get_digits() );
334 }
335}
336
337template<int WL, int WR>
338inline
340operator | ( const sc_bigint<WL>& left, const sc_bigint<WR>& right )
341{
343 sc_big_or(result, left, right);
344 return result;
345}
346
347template<int WL, int WR>
348inline
350operator | ( const sc_biguint<WL>& left, const sc_bigint<WR>& right )
351{
353 sc_big_or(result, left, right);
354 return result;
355}
356
357template<int WL, int WR>
358inline
360operator | ( const sc_bigint<WL>& left, const sc_biguint<WR>& right )
361{
363 sc_big_or(result, left, right);
364 return result;
365}
366
367template<int WL, int WR>
368inline
370operator | ( const sc_biguint<WL>& left, const sc_biguint<WR>& right )
371{
373 sc_big_or(result, left, right);
374 return result;
375}
376
377// +----------------------------------------------------------------------------
378// |"sc_big*int Bitwise Logical Xor"
379// |
380// | These inline operators implement bit-wise logical xors of sc_bigint and
381// | sc_biguint data types.
382// |
383// | Arguments:
384// | result = where to put result of the bit-wise logical xor.
385// | left = first operand of the bit-wise logical xor.
386// | right = second operand of the bit-wise logical xor.
387// | Result:
388// | Is bit-wise logical xor of left and right.
389// +----------------------------------------------------------------------------
390template<typename RESULT, typename LEFT, typename RIGHT>
391inline
392void
393sc_big_xor( RESULT& result, const LEFT& left, const RIGHT& right )
394{
395 if ( 0 == RESULT::HOD ) {
396 *result.get_digits() = *left.get_digits() ^ *right.get_digits();
397 }
398 else if ( 1 == RESULT::HOD ) {
399 const sc_digit* left_p = left.get_digits();
400 int64 left_value;
401 sc_digit* result_p = result.get_digits();
402 int64 result_value;
403 const sc_digit* right_p = right.get_digits();
404 int64 right_value;
405 if ( 1 == LEFT::HOD ) {
406 left_value = ( (int64)left_p[1] << BITS_PER_DIGIT ) | *left_p;
407 }
408 else if ( LEFT::SIGNED ) {
409 left_value = (int64)(int)*left_p;
410 }
411 else {
412 left_value = (int64)*left_p;
413 }
414 if ( 1 == RIGHT::HOD ) {
415 right_value = ( (int64)right_p[1] << BITS_PER_DIGIT ) | *right_p;
416 }
417 else if ( RIGHT::SIGNED ) {
418 right_value = (int64)(int)*right_p;
419 }
420 else {
421 right_value = (int64)*right_p;
422 }
423 result_value = left_value ^ right_value;
424 *result_p = result_value;
425 result_p[1] = (result_value >> BITS_PER_DIGIT);
426 }
427 else if ( (const int)LEFT::HOD >= (const int)RIGHT::HOD ) {
428 vector_xor<LEFT::SIGNED,RIGHT::SIGNED>( LEFT::HOD,
429 left.get_digits(),
430 RIGHT::HOD,
431 right.get_digits(),
432 result.get_digits() );
433 }
434 else {
435 vector_xor<RIGHT::SIGNED,LEFT::SIGNED>( RIGHT::HOD,
436 right.get_digits(),
437 LEFT::HOD,
438 left.get_digits(),
439 result.get_digits() );
440 }
441
442}
443
444template<int WL, int WR>
445inline
447operator ^ ( const sc_bigint<WL>& left, const sc_bigint<WR>& right )
448{
450 sc_big_xor(result, left, right);
451 return result;
452}
453
454template<int WL, int WR>
455inline
457operator ^ ( const sc_biguint<WL>& left, const sc_bigint<WR>& right )
458{
460 sc_big_xor(result, left, right);
461 return result;
462}
463
464template<int WL, int WR>
465inline
467operator ^ ( const sc_bigint<WL>& left, const sc_biguint<WR>& right )
468{
470 sc_big_xor(result, left, right);
471 return result;
472}
473
474template<int WL, int WR>
475inline
477operator ^ ( const sc_biguint<WL>& left, const sc_biguint<WR>& right )
478{
480 sc_big_xor(result, left, right);
481 return result;
482}
483
484// +----------------------------------------------------------------------------
485// |"sc_big*int Division"
486// |
487// | These inline operators implement division of sc_bigint and sc_biguint
488// | data types.
489// |
490// | Arguments:
491// | result = where to put the result of the division.
492// | numer = numerator of the division.
493// | denom = operand of the division.
494// | Result:
495// | Is division of numer by denom
496// +----------------------------------------------------------------------------
497template<typename RESULT, typename LEFT, typename RIGHT>
498inline
499void
500sc_big_divide( RESULT& result, const LEFT& left, const RIGHT& right )
501{
502 bool ok;
503
504 if ( 0 == RESULT::HOD ) {
505 typename LEFT::HOD_TYPE left_value = *left.get_digits();
506 typename RIGHT::HOD_TYPE right_value = *right.get_digits();
507 if ( 0 != right_value ) {
508 *result.get_digits() = left_value / right_value;
509 ok = true;
510 }
511 else {
512 ok = false;
513 }
514 }
515 else if ( 1 == RESULT::HOD && 2 > LEFT::HOD && 2 > RIGHT::HOD ) {
516 const sc_digit* left_p = left.get_digits();
517 int64 left_value;
518 sc_digit* result_p = result.get_digits();
519 int64 result_value;
520 const sc_digit* right_p = right.get_digits();
521 int64 right_value;
522 if ( 1 == LEFT::HOD ) {
523 left_value = ( (int64)left_p[1] << BITS_PER_DIGIT ) | *left_p;
524 }
525 else {
526 left_value = (typename LEFT::HOD_TYPE)*left_p;
527 }
528 if ( 1 == RIGHT::HOD ) {
529 right_value = ( (int64)right_p[1] << BITS_PER_DIGIT ) | *right_p;
530 }
531 else {
532 right_value = (typename RIGHT::HOD_TYPE)*right_p;
533 }
534 if ( right_value != 0 ) {
535 result_value = left_value / right_value;
536 *result_p = (sc_digit)result_value;
537 result_p[1] = (result_value >> BITS_PER_DIGIT);
538 ok = true;
539 }
540 else {
541 ok = false;
542 }
543 }
544 else {
545 ok = vector_divide<LEFT::SIGNED,RIGHT::SIGNED>( LEFT::DIGITS_N,
546 left.get_digits(),
547 RIGHT::DIGITS_N,
548 right.get_digits(),
549 RESULT::DIGITS_N,
550 result.get_digits(),
551 0,
552 NULL );
553 }
554 if ( !ok ) {
556 "division by zero detected" );
557 }
558}
559
560template<int WL, int WR>
561inline
563operator / ( const sc_bigint<WL>& numer, const sc_bigint<WR>& denom )
564{
566 sc_big_divide(result, numer, denom);
567 return result;
568}
569
570template<int WL, int WR>
571inline
573operator / ( const sc_biguint<WL>& numer, const sc_bigint<WR>& denom )
574{
576 sc_big_divide(result, numer, denom);
577 return result;
578}
579
580template<int WL, int WR>
581inline
583operator / ( const sc_bigint<WL>& numer, const sc_biguint<WR>& denom )
584{
586 sc_big_divide(result, numer, denom);
587 return result;
588}
589
590template<int WL, int WR>
591inline
593operator / ( const sc_biguint<WL>& numer, const sc_biguint<WR>& denom )
594{
596 sc_big_divide(result, numer, denom);
597 return result;
598}
599
600// +----------------------------------------------------------------------------
601// |"sc_big*int Modulo"
602// |
603// | These inline operators implement modulo of sc_bigint and sc_biguint
604// | data types.
605// |
606// | Arguments:
607// | result = where to place the result of the modulo.
608// | numer = numerator of the modulo.
609// | denom = denominator of the modulo.
610// | Result:
611// | Is modulo of numer by denom
612// +----------------------------------------------------------------------------
613template<typename RESULT, typename LEFT, typename RIGHT>
614inline
615void
616sc_big_modulo( RESULT& result, const LEFT& left, const RIGHT& right )
617{
618 bool ok; // true if operation was okay, false if divide by zero.
619
620 if ( 0 == RESULT::HOD ) {
621 typename LEFT::HOD_TYPE left_value = *left.get_digits();
622 typename RIGHT::HOD_TYPE right_value = *right.get_digits();
623 if ( right_value != 0 ) {
624 *result.get_digits() = left_value % right_value;
625 ok = true;
626 }
627 else {
628 ok = false;
629 }
630 }
631 else if ( 1 == RESULT::HOD && 2 > LEFT::HOD && 2 > RIGHT::HOD ) {
632 const sc_digit* left_p = left.get_digits();
633 int64 left_value;
634 sc_digit* result_p = result.get_digits();
635 int64 result_value;
636 const sc_digit* right_p = right.get_digits();
637 int64 right_value;
638 if ( 1 == LEFT::HOD ) {
639 left_value = ( (int64)left_p[1] << BITS_PER_DIGIT ) | *left_p;
640 }
641 else {
642 left_value = (typename LEFT::HOD_TYPE)*left_p;
643 }
644 if ( 1 == RIGHT::HOD ) {
645 right_value = ( (int64)right_p[1] << BITS_PER_DIGIT ) | *right_p;
646 }
647 else {
648 right_value = (typename RIGHT::HOD_TYPE)*right_p;
649 }
650 if ( 0 != right_value ) {
651 result_value = left_value % right_value;
652 *result_p = (sc_digit)result_value;
653 result_p[1] = (result_value >> BITS_PER_DIGIT);
654 ok = true;
655 }
656 else {
657 ok = false;
658 }
659 }
660 else {
661
662 ok = vector_divide<LEFT::SIGNED,RIGHT::SIGNED>( LEFT::DIGITS_N,
663 left.get_digits(),
664 RIGHT::DIGITS_N,
665 right.get_digits(),
666 0,
667 NULL,
668 RESULT::DIGITS_N,
669 result.get_digits() );
670 }
671 if ( !ok ) {
673 "division by zero detected" );
674 }
675}
676
677template<int WL, int WR>
678inline
680operator % ( const sc_bigint<WL>& numer, const sc_bigint<WR>& denom )
681{
683 sc_big_modulo(result, numer, denom);
684 return result;
685}
686
687template<int WL, int WR>
688inline
690operator % ( const sc_biguint<WL>& numer, const sc_bigint<WR>& denom )
691{
693 sc_big_modulo(result, numer, denom);
694 return result;
695}
696
697template<int WL, int WR>
698inline
700operator % ( const sc_bigint<WL>& numer, const sc_biguint<WR>& denom )
701{
703 sc_big_modulo(result, numer, denom);
704 return result;
705}
706
707template<int WL, int WR>
708inline
710operator % ( const sc_biguint<WL>& numer, const sc_biguint<WR>& denom )
711{
713 sc_big_modulo(result, numer, denom);
714 return result;
715}
716
717// +----------------------------------------------------------------------------
718// |"sc_big*int Multiply"
719// |
720// | These inline operators implement multiplication of sc_bigint and sc_biguint
721// | data types.
722// |
723// | Arguments:
724// | result = where to put the result of the multiply.
725// | left = first operand of the multiplication.
726// | right = second operand of the multiplication.
727// | Result:
728// | Is multiplication of left and right.
729// +----------------------------------------------------------------------------
730
731template<typename RESULT, typename LEFT, typename RIGHT>
732inline
733void
734sc_big_multiply( RESULT& result, const LEFT& left, const RIGHT& right )
735{
736 if ( 0 == RESULT::HOD ) {
737 *result.get_digits() = *left.get_digits() * *right.get_digits();
738 }
739 else if ( 1 == RESULT::HOD ) {
740 const sc_digit* left_p = left.get_digits();
741 int64 left_value;
742 sc_digit* result_p = result.get_digits();
743 int64 result_value;
744 const sc_digit* right_p = right.get_digits();
745 int64 right_value;
746 if ( 1 == LEFT::HOD ) {
747 left_value = ( (int64)left_p[1] << BITS_PER_DIGIT ) | *left_p;
748 }
749 else if ( LEFT::SIGNED ) {
750 left_value = (int64)(int)*left_p;
751 }
752 else {
753 left_value = (int64)*left_p;
754 }
755 if ( 1 == RIGHT::HOD ) {
756 right_value = ( (int64)right_p[1] << BITS_PER_DIGIT ) | *right_p;
757 }
758 else if ( RIGHT::SIGNED ) {
759 right_value = (int64)(int)*right_p;
760 }
761 else {
762 right_value = (int64)*right_p;
763 }
764 result_value = left_value * right_value;
765 *result_p = (sc_digit)result_value;
766 result_p[1] = (result_value >> BITS_PER_DIGIT);
767 }
768 vector_multiply( LEFT::HOD, left.get_digits(),
769 RIGHT::HOD, right.get_digits(),
770 RESULT::HOD, result.get_digits() );
771}
772
773template<int WL, int WR>
774inline
776operator * ( const sc_bigint<WL>& left, const sc_bigint<WR>& right )
777{
779 sc_big_multiply(result, left, right);
780 return result;
781}
782
783template<int WL, int WR>
784inline
786operator * ( const sc_biguint<WL>& left, const sc_bigint<WR>& right )
787{
789 sc_big_multiply(result, left, right);
790 return result;
791}
792
793template<int WL, int WR>
794inline
796operator * ( const sc_bigint<WL>& left, const sc_biguint<WR>& right )
797{
799 sc_big_multiply(result, left, right);
800 return result;
801}
802
803template<int WL, int WR>
804inline
806operator * ( const sc_biguint<WL>& left, const sc_biguint<WR>& right )
807{
809 sc_big_multiply(result, left, right);
810 return result;
811}
812
813// +----------------------------------------------------------------------------
814// |"sc_big*int Subtract"
815// |
816// | These inline operators implement subtraction of sc_bigint and sc_biguint
817// | data types.
818// |
819// | Arguments:
820// | result = where to put the result of the subtraction.
821// | left = first operand of the subtraction.
822// | right = second operand of the subtraction.
823// | Result:
824// | Is subtraction of left and right.
825// +----------------------------------------------------------------------------
826template<typename RESULT, typename LEFT, typename RIGHT>
827inline
828void
829sc_big_subtract( RESULT& result, const LEFT& left, const RIGHT& right )
830{
831 if ( 0 == RESULT::HOD ) {
832 *result.get_digits() = *left.get_digits() - *right.get_digits();
833 }
834 else if ( 1 == RESULT::HOD ) {
835 const sc_digit* left_p = left.get_digits();
836 int64 left_value;
837 sc_digit* result_p = result.get_digits();
838 int64 result_value;
839 const sc_digit* right_p = right.get_digits();
840 int64 right_value;
841 if ( 1 == LEFT::HOD ) {
842 left_value = ( (int64)left_p[1] << BITS_PER_DIGIT ) | *left_p;
843 }
844 else if ( LEFT::SIGNED ) {
845 left_value = (int64)(int)*left_p;
846 }
847 else {
848 left_value = (int64)*left_p;
849 }
850 if ( 1 == RIGHT::HOD ) {
851 right_value = ( (int64)right_p[1] << BITS_PER_DIGIT ) | *right_p;
852 }
853 else if ( RIGHT::SIGNED ) {
854 right_value = (int64)(int)*right_p;
855 }
856 else {
857 right_value = (int64)*right_p;
858 }
859 result_value = left_value - right_value;
860 *result_p = (sc_digit)result_value;
861 result_p[1] = (result_value >> BITS_PER_DIGIT);
862 }
863 else if ( (const int)LEFT::HOD > (const int)RIGHT::HOD ) {
864 vector_subtract_shorter( LEFT::HOD,
865 left.get_digits(),
866 RIGHT::HOD,
867 right.get_digits(),
868 RESULT::HOD,
869 result.get_digits() );
870 }
871 else {
872 vector_subtract_longer( RIGHT::HOD,
873 right.get_digits(),
874 LEFT::HOD,
875 left.get_digits(),
876 RESULT::HOD,
877 result.get_digits() );
878 }
879}
880
881template<int WL, int WR>
882inline
884operator - ( const sc_bigint<WL>& left, const sc_bigint<WR>& right )
885{
887 sc_big_subtract(result, left, right);
888 return result;
889}
890
891template<int WL, int WR>
892inline
894operator - ( const sc_biguint<WL>& left, const sc_bigint<WR>& right )
895{
897 sc_big_subtract(result, left, right);
898 return result;
899}
900
901template<int WL, int WR>
902inline
904operator - ( const sc_bigint<WL>& left, const sc_biguint<WR>& right )
905{
907 sc_big_subtract(result, left, right);
908 return result;
909}
910
911template<int WL, int WR>
912inline
914operator - ( const sc_biguint<WL>& left, const sc_biguint<WR>& right )
915{
917 sc_big_subtract(result, left, right);
918 return result;
919}
920
921} // namespace sc_dt
922
923#undef SC_BIG_MAX
924#undef SC_BIG_MIN
925
926#endif // SC_BIG_OPS_H
#define BITS_PER_DIGIT
Definition: sc_nbdefs.h:164
#define SC_REPORT_ERROR(msg_type, msg)
Definition: sc_report.h:217
const char SC_ID_OPERATION_FAILED_[]
void sc_big_or(RESULT &result, const LEFT &left, const RIGHT &right)
Definition: sc_big_ops.h:287
void vector_subtract_shorter(const int longer_hod, const sc_digit *longer_p, const int shorter_hod, const sc_digit *shorter_p, const int result_hod, sc_digit *result_p)
sc_bit operator&(const sc_bit &a, const sc_bit &b)
Definition: sc_bit.h:331
sc_bit operator^(const sc_bit &a, const sc_bit &b)
Definition: sc_bit.h:337
const sc_big_op_info< WL, true, WR, true >::add_result operator+(const sc_bigint< WL > &left, const sc_bigint< WR > &right)
Definition: sc_big_ops.h:125
void sc_big_and(RESULT &result, const LEFT &left, const RIGHT &right)
Definition: sc_big_ops.h:181
void vector_add(const int longer_hod, const sc_digit *longer_p, const int shorter_hod, const sc_digit *shorter_p, const int result_hod, sc_digit *result_p)
sc_fxval operator/(const sc_fxnum &a, const sc_fxnum &b)
Definition: sc_fxnum.h:2849
const sc_big_op_info< WL, true, WR, true >::mod_result operator%(const sc_bigint< WL > &numer, const sc_bigint< WR > &denom)
Definition: sc_big_ops.h:680
void sc_big_add(RESULT &result, const LEFT &left, const RIGHT &right)
Definition: sc_big_ops.h:76
const sc_big_op_info< WL, true, WR, true >::sub_result operator-(const sc_bigint< WL > &left, const sc_bigint< WR > &right)
Definition: sc_big_ops.h:884
void sc_big_modulo(RESULT &result, const LEFT &left, const RIGHT &right)
Definition: sc_big_ops.h:616
void vector_dump(int source_hod, sc_digit *source_p)
Definition: sc_big_ops.h:51
void sc_big_divide(RESULT &result, const LEFT &left, const RIGHT &right)
Definition: sc_big_ops.h:500
void vector_multiply(int left_hod, const sc_digit *left_p, int right_hod, const sc_digit *right_p, int result_hod, sc_digit *result_p)
void sc_big_xor(RESULT &result, const LEFT &left, const RIGHT &right)
Definition: sc_big_ops.h:393
unsigned int sc_digit
Definition: sc_nbdefs.h:161
void sc_big_multiply(RESULT &result, const LEFT &left, const RIGHT &right)
Definition: sc_big_ops.h:734
const sc_big_op_info< WL, true, WR, true >::mul_result operator*(const sc_bigint< WL > &left, const sc_bigint< WR > &right)
Definition: sc_big_ops.h:776
void sc_big_subtract(RESULT &result, const LEFT &left, const RIGHT &right)
Definition: sc_big_ops.h:829
sc_bit operator|(const sc_bit &a, const sc_bit &b)
Definition: sc_bit.h:334
long long int64
Definition: sc_nbdefs.h:215
void vector_subtract_longer(const int longer_hod, const sc_digit *longer_p, const int shorter_hod, const sc_digit *shorter_p, const int result_hod, sc_digit *result_p)
sc_big_op_type< sub_bits, signed_result >::top_type sub_result
sc_big_op_type< mod_bits, signed_result >::top_type mod_result
sc_big_op_type< div_bits, signed_result >::top_type div_result
sc_big_op_type< add_bits, signed_result >::top_type add_result
sc_big_op_type< mul_bits, signed_result >::top_type mul_result
sc_big_op_type< bit_bits, signed_result >::top_type bit_result