SystemC 3.0.0
Accellera SystemC proof-of-concept library
sc_signed_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_signed_ops.h -- operator implementations for sc_signed and sc_unsigned
23 results
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_SIGNED_OPS_H
33#define SC_SIGNED_OPS_H
34
35namespace sc_dt {
36
37#define OPS_MIN(A,B) ( (A) <= (B) ? A : B )
38#define OPS_MAX(A,B) ( (A) >= (B) ? A : B )
39
40// +----------------------------------------------------------------------------
41// |"sc_signed/sc_unsigned addition operators"
42// |
43// | These are the operators for addition that involves at least one instance
44// | of sc_signed or sc_unsigned. The implementation is done using three macros:
45// | (a) ADD_BIG_BIG
46// | (b) ADD_BIG_NATIVE
47// | (c) ADD_NATIVE_BIG
48// +----------------------------------------------------------------------------
49
50#define ADD_BIG_BIG(RESULT_TYPE,LEFT_TYPE,RIGHT_TYPE) \
51 inline \
52 const RESULT_TYPE \
53 operator+(const LEFT_TYPE& left, const RIGHT_TYPE& right) \
54 { \
55 const int left_n = left.get_actual_length(); \
56 const int right_n = right.get_actual_length(); \
57 \
58 if ( left_n >= right_n ) { \
59 RESULT_TYPE result(left_n+1, false); \
60 vector_add( left.get_hod(), \
61 left.get_digits(), \
62 right.get_hod(), \
63 right.get_digits(), \
64 result.get_hod(), \
65 result.get_digits() ); \
66 return result; \
67 } \
68 else { \
69 RESULT_TYPE result(right_n+1, false); \
70 vector_add( right.get_hod(), \
71 right.get_digits(), \
72 left.get_hod(), \
73 left.get_digits(), \
74 result.get_hod(), \
75 result.get_digits() ); \
76 return result; \
77 } \
78 }
79
80#define ADD_BIG_NATIVE(RESULT_TYPE,BIG_TYPE,NATIVE_TYPE) \
81 inline \
82 const RESULT_TYPE \
83 operator+(const BIG_TYPE &left, NATIVE_TYPE native) \
84 { \
85 ScNativeDigits<NATIVE_TYPE> right( native ); \
86 const int left_n = left.get_actual_length(); \
87 const int right_n = right.get_actual_length(); \
88 \
89 if ( left_n > right_n ) { \
90 RESULT_TYPE result( left_n+1, false ); \
91 vector_add( left.get_hod(), \
92 left.get_digits(), \
93 right.get_hod(), \
94 right.get_digits(), \
95 result.get_hod(), \
96 result.get_digits() ); \
97 return result; \
98 } \
99 else { \
100 RESULT_TYPE result( right_n+1, false ); \
101 vector_add( right.get_hod(), \
102 right.get_digits(), \
103 left.get_hod(), \
104 left.get_digits(), \
105 result.get_hod(), \
106 result.get_digits() ); \
107 return result; \
108 } \
109 }
110
111#define ADD_NATIVE_BIG(RESULT_TYPE,NATIVE_TYPE,BIG_TYPE) \
112 inline \
113 const RESULT_TYPE \
114 operator+(NATIVE_TYPE native, const BIG_TYPE &right) \
115 { \
116 \
117 ScNativeDigits<NATIVE_TYPE> left(native); \
118 const int left_n = left.get_actual_length(); \
119 const int right_n = right.get_actual_length(); \
120 \
121 if ( left_n > right_n ) { \
122 RESULT_TYPE result( left_n+1, false ); \
123 vector_add( left.get_hod(), \
124 left.get_digits(), \
125 right.get_hod(), \
126 right.get_digits(), \
127 result.get_hod(), \
128 result.get_digits() ); \
129 return result; \
130 } \
131 else { \
132 RESULT_TYPE result( right_n+1, false ); \
133 vector_add( \
134 right.get_hod(), \
135 right.get_digits(), \
136 left.get_hod(), \
137 left.get_digits(), \
138 result.get_hod(), \
139 result.get_digits() ); \
140 return result; \
141 } \
142 }
143
144// big type + big type:
145
146ADD_BIG_BIG(sc_signed,sc_signed,sc_signed)
147ADD_BIG_BIG(sc_signed,sc_unsigned,sc_signed)
148ADD_BIG_BIG(sc_signed,sc_signed,sc_unsigned)
149ADD_BIG_BIG(sc_unsigned,sc_unsigned,sc_unsigned)
150
151// sc_signed + C++ native:
152
153ADD_BIG_NATIVE(sc_signed,sc_signed,int64)
154ADD_BIG_NATIVE(sc_signed,sc_signed,uint64)
155ADD_BIG_NATIVE(sc_signed,sc_signed,long)
156ADD_BIG_NATIVE(sc_signed,sc_signed,unsigned long)
157ADD_BIG_NATIVE(sc_signed,sc_signed,int)
158ADD_BIG_NATIVE(sc_signed,sc_signed,unsigned int)
159
160// C++ native + sc_signed:
161
162ADD_NATIVE_BIG(sc_signed,int64,sc_signed)
163ADD_NATIVE_BIG(sc_signed,uint64,sc_signed)
164ADD_NATIVE_BIG(sc_signed,long,sc_signed)
165ADD_NATIVE_BIG(sc_signed,unsigned long,sc_signed)
166ADD_NATIVE_BIG(sc_signed,int,sc_signed)
167ADD_NATIVE_BIG(sc_signed,unsigned int,sc_signed)
168
169// sc_unsigned + signed C++ native:
170
171ADD_BIG_NATIVE(sc_signed,sc_unsigned,int64)
172ADD_BIG_NATIVE(sc_signed,sc_unsigned,long)
173ADD_BIG_NATIVE(sc_signed,sc_unsigned,int)
174
175// signed C++ native + sc_unsigned:
176
177ADD_NATIVE_BIG(sc_signed,int64,sc_unsigned)
178ADD_NATIVE_BIG(sc_signed,long,sc_unsigned)
179ADD_NATIVE_BIG(sc_signed,int,sc_unsigned)
180
181// sc_unsigned + unsigned C++ native:
182
183ADD_BIG_NATIVE(sc_unsigned,sc_unsigned,uint64)
184ADD_BIG_NATIVE(sc_unsigned,sc_unsigned,unsigned long)
185ADD_BIG_NATIVE(sc_unsigned,sc_unsigned,unsigned int)
186
187// unsigned C++ native + sc_unsigned:
188
189ADD_NATIVE_BIG(sc_unsigned,uint64,sc_unsigned)
190ADD_NATIVE_BIG(sc_unsigned,unsigned long,sc_unsigned)
191ADD_NATIVE_BIG(sc_unsigned,unsigned int,sc_unsigned)
192
193// sc_int_base and sc_uint_base arguments:
194
195inline
196const sc_signed operator+( const sc_signed& left, const sc_int_base& right )
197 { return operator+(left, (int64)right); }
198
199inline
200const sc_signed operator+( const sc_signed& left, const sc_uint_base& right )
201 { return operator+(left, (uint64)right); }
202
203inline
204const sc_signed operator+( const sc_int_base& left, const sc_signed& right )
205 { return operator+((int64)left, right); }
206
207inline
208const sc_signed operator+( const sc_uint_base& left, const sc_signed& right )
209 { return operator+((uint64)left, right); }
210
211inline
212const sc_signed operator+( const sc_unsigned& left, const sc_int_base& right )
213 { return operator+(left, (int64)right); }
214
215inline
216const sc_signed operator+( const sc_int_base& left, const sc_unsigned& right )
217 { return operator+((int64)left, right); }
218
219inline
220const sc_unsigned operator+(const sc_unsigned& left, const sc_uint_base& right )
221 { return operator+(left, (uint64)right); }
222
223inline
224const sc_unsigned operator+(const sc_uint_base& left, const sc_unsigned& right )
225 { return operator+((uint64)left, right); }
226
227#undef ADD_BIG_BIG
228#undef ADD_BIG_NATIVE
229#undef ADD_NATIVE_BIG
230
231// +----------------------------------------------------------------------------
232// |"sc_signed/sc_unsigned division operators"
233// |
234// | These are the operators for division that involves at least one instance
235// | of sc_signed or sc_unsigned. The implementation is done using three macros:
236// | (a) DIVIDE_BIG_BIG
237// | (b) DIVIDE_BIG_NATIVE
238// | (c) DIVIDE_NATIVE_BIG
239// +----------------------------------------------------------------------------
240
241#define DIVIDE_BIG_BIG(RESULT_TYPE,LEFT_TYPE,RIGHT_TYPE) \
242inline \
243const RESULT_TYPE \
244operator/(const LEFT_TYPE& left, const RIGHT_TYPE& right) \
245 { \
246 int left_n = left.get_actual_length(); \
247 \
248 RESULT_TYPE quotient(left_n+right.SIGNED); \
249 bool ok = vector_divide<LEFT_TYPE::SIGNED,RIGHT_TYPE::SIGNED>( \
250 left.get_digits_n(), \
251 left.get_digits(), \
252 right.get_digits_n(), \
253 right.get_digits(), \
254 quotient.get_digits_n(), \
255 quotient.get_digits(), \
256 0, \
257 NULL ); \
258 if ( !ok ) { \
259 SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, \
260 "division by zero detected" ); \
261 } \
262 return quotient; \
263 }
264
265#define DIVIDE_BIG_NATIVE(RESULT_TYPE,BIG_TYPE,NATIVE_TYPE) \
266 inline \
267 const RESULT_TYPE \
268 operator/(const BIG_TYPE &left, NATIVE_TYPE native) \
269 { \
270 ScNativeDigits<NATIVE_TYPE> right( native ); \
271 const int left_n = left.get_actual_length(); \
272 \
273 RESULT_TYPE quotient(left_n+right.SIGNED, false); \
274 bool ok = \
275 vector_divide<BIG_TYPE::SIGNED,ScNativeDigits<NATIVE_TYPE>::SIGNED>( \
276 left.get_digits_n(), \
277 left.get_digits(), \
278 right.get_digits_n(), \
279 right.get_digits(), \
280 quotient.get_digits_n(), \
281 quotient.get_digits(), \
282 0, \
283 NULL ); \
284 if ( !ok ) { \
285 SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, \
286 "division by zero detected" ); \
287 } \
288 return quotient; \
289 }
290
291#define DIVIDE_NATIVE_BIG(RESULT_TYPE,NATIVE_TYPE,BIG_TYPE) \
292 inline \
293 const RESULT_TYPE \
294 operator/(NATIVE_TYPE native, const BIG_TYPE &right) \
295 { \
296 \
297 ScNativeDigits<NATIVE_TYPE> left(native); \
298 const int left_n = left.get_actual_length(); \
299 \
300 RESULT_TYPE quotient(left_n+right.SIGNED, false); \
301 bool ok = \
302 vector_divide<ScNativeDigits<NATIVE_TYPE>::SIGNED,BIG_TYPE::SIGNED>( \
303 left.get_digits_n(), \
304 left.get_digits(), \
305 right.get_digits_n(), \
306 right.get_digits(), \
307 quotient.get_digits_n(), \
308 quotient.get_digits(), \
309 0, \
310 NULL ); \
311 if ( !ok ) { \
312 SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, \
313 "division by zero detected" ); \
314 } \
315 return quotient; \
316 }
317
318// big type + big type:
319
320DIVIDE_BIG_BIG(sc_signed,sc_signed,sc_signed)
321DIVIDE_BIG_BIG(sc_signed,sc_unsigned,sc_signed)
322DIVIDE_BIG_BIG(sc_signed,sc_signed,sc_unsigned)
323DIVIDE_BIG_BIG(sc_unsigned,sc_unsigned,sc_unsigned)
324
325// sc_signed + C++ native:
326
327DIVIDE_BIG_NATIVE(sc_signed,sc_signed,int64)
328DIVIDE_BIG_NATIVE(sc_signed,sc_signed,uint64)
329DIVIDE_BIG_NATIVE(sc_signed,sc_signed,long)
330DIVIDE_BIG_NATIVE(sc_signed,sc_signed,unsigned long)
331DIVIDE_BIG_NATIVE(sc_signed,sc_signed,int)
332DIVIDE_BIG_NATIVE(sc_signed,sc_signed,unsigned int)
333
334// C++ native + sc_signed:
335
336DIVIDE_NATIVE_BIG(sc_signed,int64,sc_signed)
337DIVIDE_NATIVE_BIG(sc_signed,uint64,sc_signed)
338DIVIDE_NATIVE_BIG(sc_signed,long,sc_signed)
339DIVIDE_NATIVE_BIG(sc_signed,unsigned long,sc_signed)
340DIVIDE_NATIVE_BIG(sc_signed,int,sc_signed)
341DIVIDE_NATIVE_BIG(sc_signed,unsigned int,sc_signed)
342
343// sc_unsigned + signed C++ native:
344
345DIVIDE_BIG_NATIVE(sc_signed,sc_unsigned,int64)
346DIVIDE_BIG_NATIVE(sc_signed,sc_unsigned,long)
347DIVIDE_BIG_NATIVE(sc_signed,sc_unsigned,int)
348
349// signed C++ native + sc_unsigned:
350
351DIVIDE_NATIVE_BIG(sc_signed,int64,sc_unsigned)
352DIVIDE_NATIVE_BIG(sc_signed,long,sc_unsigned)
353DIVIDE_NATIVE_BIG(sc_signed,int,sc_unsigned)
354
355// sc_unsigned + unsigned C++ native:
356
357DIVIDE_BIG_NATIVE(sc_unsigned,sc_unsigned,uint64)
358DIVIDE_BIG_NATIVE(sc_unsigned,sc_unsigned,unsigned long)
359DIVIDE_BIG_NATIVE(sc_unsigned,sc_unsigned,unsigned int)
360
361// unsigned C++ native + sc_unsigned:
362
363DIVIDE_NATIVE_BIG(sc_unsigned,uint64,sc_unsigned)
364DIVIDE_NATIVE_BIG(sc_unsigned,unsigned long,sc_unsigned)
365DIVIDE_NATIVE_BIG(sc_unsigned,unsigned int,sc_unsigned)
366
367// sc_int_base and sc_uint_base arguments:
368
369inline
370const sc_signed operator/( const sc_signed& left, const sc_int_base& right )
371 { return operator/(left, (int64)right); }
372
373inline
374const sc_signed operator/( const sc_signed& left, const sc_uint_base& right )
375 { return operator/(left, (uint64)right); }
376
377inline
378const sc_signed operator/( const sc_int_base& left, const sc_signed& right )
379 { return operator/((int64)left, right); }
380
381inline
382const sc_signed operator/( const sc_uint_base& left, const sc_signed& right )
383 { return operator/((uint64)left, right); }
384
385inline
386const sc_signed operator/( const sc_unsigned& left, const sc_int_base& right )
387 { return operator/(left, (int64)right); }
388
389inline
390const sc_signed operator/( const sc_int_base& left, const sc_unsigned& right )
391 { return operator/((int64)left, right); }
392
393inline
394const sc_unsigned operator/(const sc_unsigned& left, const sc_uint_base& right )
395 { return operator/(left, (uint64)right); }
396
397inline
398const sc_unsigned operator/(const sc_uint_base& left, const sc_unsigned& right )
399 { return operator/((uint64)left, right); }
400
401#undef DIVIDE_BIG_BIG
402#undef DIVIDE_BIG_NATIVE
403#undef DIVIDE_NATIVE_BIG
404
405// +----------------------------------------------------------------------------
406// |"sc_signed/sc_unsigned modulus operators"
407// |
408// | These are the operators for modulo that involves at least one instance
409// | of sc_signed or sc_unsigned. The implementation is done using three macros:
410// | (a) MODULO_BIG_BIG
411// | (b) MODULO_BIG_NATIVE
412// | (c) MODULO_NATIVE_BIG
413// +----------------------------------------------------------------------------
414
415#define MODULO_BIG_BIG(RESULT_TYPE,LEFT_TYPE,RIGHT_TYPE) \
416inline \
417const RESULT_TYPE \
418operator%(const LEFT_TYPE& left, const RIGHT_TYPE& right) \
419 { \
420 const int left_n = left.get_actual_length(); \
421 const int right_n = right.get_actual_length(); \
422 const int width_n = OPS_MIN( left_n,right_n+right.SIGNED ); \
423 \
424 RESULT_TYPE result(width_n); \
425 vector_divide<LEFT_TYPE::SIGNED,RIGHT_TYPE::SIGNED>( \
426 left.get_digits_n(), \
427 left.get_digits(), \
428 right.get_digits_n(), \
429 right.get_digits(), \
430 0, \
431 NULL, \
432 result.get_digits_n(), \
433 result.get_digits() ); \
434 return result; \
435 }
436
437#define MODULO_BIG_NATIVE(RESULT_TYPE,BIG_TYPE,NATIVE_TYPE) \
438 inline \
439 const RESULT_TYPE \
440 operator%(const BIG_TYPE &left, NATIVE_TYPE native) \
441 { \
442 ScNativeDigits<NATIVE_TYPE> right( native ); \
443 const int left_n = left.get_actual_length(); \
444 const int right_n = right.get_actual_length(); \
445 const int width_n = OPS_MIN( left_n,right_n+right.SIGNED ); \
446 \
447 RESULT_TYPE result(width_n); \
448 vector_divide<BIG_TYPE::SIGNED,ScNativeDigits<NATIVE_TYPE>::SIGNED>(\
449 left.get_digits_n(), \
450 left.get_digits(), \
451 right.get_digits_n(), \
452 right.get_digits(), \
453 0, \
454 NULL, \
455 result.get_digits_n(), \
456 result.get_digits() ); \
457 return result; \
458 }
459
460#define MODULO_NATIVE_BIG(RESULT_TYPE,NATIVE_TYPE,BIG_TYPE) \
461 inline \
462 const RESULT_TYPE \
463 operator%(NATIVE_TYPE native, const BIG_TYPE &right) \
464 { \
465 \
466 ScNativeDigits<NATIVE_TYPE> left(native); \
467 const int left_n = left.get_actual_length(); \
468 const int right_n = right.get_actual_length(); \
469 const int width_n = OPS_MIN( left_n,right_n+right.SIGNED ); \
470 \
471 RESULT_TYPE result(width_n); \
472 vector_divide<ScNativeDigits<NATIVE_TYPE>::SIGNED,BIG_TYPE::SIGNED>(\
473 left.get_digits_n(), \
474 left.get_digits(), \
475 right.get_digits_n(), \
476 right.get_digits(), \
477 0, \
478 NULL, \
479 result.get_digits_n(), \
480 result.get_digits() ); \
481 return result; \
482 }
483
484// big type + big type:
485
486MODULO_BIG_BIG(sc_signed,sc_signed,sc_signed)
487MODULO_BIG_BIG(sc_signed,sc_unsigned,sc_signed)
488MODULO_BIG_BIG(sc_signed,sc_signed,sc_unsigned)
489MODULO_BIG_BIG(sc_unsigned,sc_unsigned,sc_unsigned)
490
491// sc_signed + C++ native:
492
493MODULO_BIG_NATIVE(sc_signed,sc_signed,int64)
494MODULO_BIG_NATIVE(sc_signed,sc_signed,uint64)
495MODULO_BIG_NATIVE(sc_signed,sc_signed,long)
496MODULO_BIG_NATIVE(sc_signed,sc_signed,unsigned long)
497MODULO_BIG_NATIVE(sc_signed,sc_signed,int)
498MODULO_BIG_NATIVE(sc_signed,sc_signed,unsigned int)
499
500// C++ native + sc_signed:
501
502MODULO_NATIVE_BIG(sc_signed,int64,sc_signed)
503MODULO_NATIVE_BIG(sc_signed,uint64,sc_signed)
504MODULO_NATIVE_BIG(sc_signed,long,sc_signed)
505MODULO_NATIVE_BIG(sc_signed,unsigned long,sc_signed)
506MODULO_NATIVE_BIG(sc_signed,int,sc_signed)
507MODULO_NATIVE_BIG(sc_signed,unsigned int,sc_signed)
508
509// sc_unsigned + signed C++ native:
510
511MODULO_BIG_NATIVE(sc_signed,sc_unsigned,int64)
512MODULO_BIG_NATIVE(sc_signed,sc_unsigned,long)
513MODULO_BIG_NATIVE(sc_signed,sc_unsigned,int)
514
515// signed C++ native + sc_unsigned:
516
517MODULO_NATIVE_BIG(sc_signed,int64,sc_unsigned)
518MODULO_NATIVE_BIG(sc_signed,long,sc_unsigned)
519MODULO_NATIVE_BIG(sc_signed,int,sc_unsigned)
520
521// sc_unsigned + unsigned C++ native:
522
523MODULO_BIG_NATIVE(sc_unsigned,sc_unsigned,uint64)
524MODULO_BIG_NATIVE(sc_unsigned,sc_unsigned,unsigned long)
525MODULO_BIG_NATIVE(sc_unsigned,sc_unsigned,unsigned int)
526
527// unsigned C++ native + sc_unsigned:
528
529MODULO_NATIVE_BIG(sc_unsigned,uint64,sc_unsigned)
530MODULO_NATIVE_BIG(sc_unsigned,unsigned long,sc_unsigned)
531MODULO_NATIVE_BIG(sc_unsigned,unsigned int,sc_unsigned)
532
533// sc_int_base and sc_uint_base arguments:
534
535inline
536const sc_signed operator%( const sc_signed& left, const sc_int_base& right )
537 { return operator%(left, (int64)right); }
538
539inline
540const sc_signed operator%( const sc_signed& left, const sc_uint_base& right )
541 { return operator%(left, (uint64)right); }
542
543inline
544const sc_signed operator%( const sc_int_base& left, const sc_signed& right )
545 { return operator%((int64)left, right); }
546
547inline
548const sc_signed operator%( const sc_uint_base& left, const sc_signed& right )
549 { return operator%((uint64)left, right); }
550
551inline
552const sc_signed operator%( const sc_unsigned& left, const sc_int_base& right )
553 { return operator%(left, (int64)right); }
554
555inline
556const sc_signed operator%( const sc_int_base& left, const sc_unsigned& right )
557 { return operator%((int64)left, right); }
558
559inline
560const sc_unsigned operator%(const sc_unsigned& left, const sc_uint_base& right )
561 { return operator%(left, (uint64)right); }
562
563inline
564const sc_unsigned operator%(const sc_uint_base& left, const sc_unsigned& right )
565 { return operator%((uint64)left, right); }
566
567#undef MODULO_BIG_BIG
568#undef MODULO_BIG_NATIVE
569#undef MODULO_NATIVE_BIG
570
571// +----------------------------------------------------------------------------
572// |"sc_signed/sc_unsigned multiplication operators"
573// |
574// | These are the operators for multiplication that involves at least one
575// | instance of sc_signed or sc_unsigned. The implementation is done using
576// | three macros:
577// | (a) MULTIPLY_BIG_BIG
578// | (b) MULTIPLY_BIG_NATIVE
579// | (c) MULTIPLY_NATIVE_BIG
580// +----------------------------------------------------------------------------
581
582#define MULTIPLY_BIG_BIG(RESULT_TYPE,LEFT_TYPE,RIGHT_TYPE) \
583inline \
584const RESULT_TYPE \
585operator*(const LEFT_TYPE& left, const RIGHT_TYPE& right) \
586 { \
587 int left_n = left.get_actual_length(); \
588 int right_n = right.get_actual_length(); \
589 \
590 RESULT_TYPE result(left_n+right_n, false); \
591 vector_multiply( left.get_hod(), \
592 left.get_digits(), \
593 right.get_hod(), \
594 right.get_digits(), \
595 result.get_hod(), \
596 result.get_digits() ); \
597 return result; \
598 }
599
600#define MULTIPLY_BIG_NATIVE(RESULT_TYPE,BIG_TYPE,NATIVE_TYPE) \
601 inline \
602 const RESULT_TYPE \
603 operator*(const BIG_TYPE &left, NATIVE_TYPE native) \
604 { \
605 ScNativeDigits<NATIVE_TYPE> right( native ); \
606 const int left_n = left.get_actual_length(); \
607 const int right_n = right.get_actual_length(); \
608 \
609 RESULT_TYPE result(left_n+right_n, false); \
610 vector_multiply( left.get_hod(), \
611 left.get_digits(), \
612 right.get_hod(), \
613 right.get_digits(), \
614 result.get_hod(), \
615 result.get_digits() ); \
616 return result; \
617 }
618
619#define MULTIPLY_NATIVE_BIG(RESULT_TYPE,NATIVE_TYPE,BIG_TYPE) \
620 inline \
621 const RESULT_TYPE \
622 operator*(NATIVE_TYPE native, const BIG_TYPE &right) \
623 { \
624 \
625 ScNativeDigits<NATIVE_TYPE> left(native); \
626 const int left_n = left.get_actual_length(); \
627 const int right_n = right.get_actual_length(); \
628 \
629 RESULT_TYPE result(left_n+right_n, false); \
630 vector_multiply( left.get_hod(), \
631 left.get_digits(), \
632 right.get_hod(), \
633 right.get_digits(), \
634 result.get_hod(), \
635 result.get_digits() ); \
636 return result; \
637 }
638
639// big type + big type:
640
641MULTIPLY_BIG_BIG(sc_signed,sc_signed,sc_signed)
642MULTIPLY_BIG_BIG(sc_signed,sc_unsigned,sc_signed)
643MULTIPLY_BIG_BIG(sc_signed,sc_signed,sc_unsigned)
644MULTIPLY_BIG_BIG(sc_unsigned,sc_unsigned,sc_unsigned)
645
646// sc_signed + C++ native:
647
648MULTIPLY_BIG_NATIVE(sc_signed,sc_signed,int64)
649MULTIPLY_BIG_NATIVE(sc_signed,sc_signed,uint64)
650MULTIPLY_BIG_NATIVE(sc_signed,sc_signed,long)
651MULTIPLY_BIG_NATIVE(sc_signed,sc_signed,unsigned long)
652MULTIPLY_BIG_NATIVE(sc_signed,sc_signed,int)
653MULTIPLY_BIG_NATIVE(sc_signed,sc_signed,unsigned int)
654
655// C++ native + sc_signed:
656
657MULTIPLY_NATIVE_BIG(sc_signed,int64,sc_signed)
658MULTIPLY_NATIVE_BIG(sc_signed,uint64,sc_signed)
659MULTIPLY_NATIVE_BIG(sc_signed,long,sc_signed)
660MULTIPLY_NATIVE_BIG(sc_signed,unsigned long,sc_signed)
661MULTIPLY_NATIVE_BIG(sc_signed,int,sc_signed)
662MULTIPLY_NATIVE_BIG(sc_signed,unsigned int,sc_signed)
663
664// sc_unsigned + signed C++ native:
665
666MULTIPLY_BIG_NATIVE(sc_signed,sc_unsigned,int64)
667MULTIPLY_BIG_NATIVE(sc_signed,sc_unsigned,long)
668MULTIPLY_BIG_NATIVE(sc_signed,sc_unsigned,int)
669
670// signed C++ native + sc_unsigned:
671
672MULTIPLY_NATIVE_BIG(sc_signed,int64,sc_unsigned)
673MULTIPLY_NATIVE_BIG(sc_signed,long,sc_unsigned)
674MULTIPLY_NATIVE_BIG(sc_signed,int,sc_unsigned)
675
676// sc_unsigned + unsigned C++ native:
677
678MULTIPLY_BIG_NATIVE(sc_unsigned,sc_unsigned,uint64)
679MULTIPLY_BIG_NATIVE(sc_unsigned,sc_unsigned,unsigned long)
680MULTIPLY_BIG_NATIVE(sc_unsigned,sc_unsigned,unsigned int)
681
682// unsigned C++ native + sc_unsigned:
683
684MULTIPLY_NATIVE_BIG(sc_unsigned,uint64,sc_unsigned)
685MULTIPLY_NATIVE_BIG(sc_unsigned,unsigned long,sc_unsigned)
686MULTIPLY_NATIVE_BIG(sc_unsigned,unsigned int,sc_unsigned)
687
688// sc_int_base and sc_uint base arguments:
689
690inline
691const sc_signed operator*( const sc_signed& left, const sc_int_base& right )
692 { return operator*(left, (int64)right); }
693
694inline
695const sc_signed operator*( const sc_signed& left, const sc_uint_base& right )
696 { return operator*(left, (uint64)right); }
697
698inline
699const sc_signed operator*( const sc_int_base& left, const sc_signed& right )
700 { return operator*((int64)left, right); }
701
702inline
703const sc_signed operator*( const sc_uint_base& left, const sc_signed& right )
704 { return operator*((uint64)left, right); }
705
706inline
707const sc_signed operator*( const sc_unsigned& left, const sc_int_base& right )
708 { return operator*(left, (int64)right); }
709
710inline
711const sc_signed operator*( const sc_int_base& left, const sc_unsigned& right )
712 { return operator*((int64)left, right); }
713
714inline
715const sc_unsigned operator*(const sc_unsigned& left, const sc_uint_base& right )
716 { return operator*(left, (uint64)right); }
717
718inline
719const sc_unsigned operator*(const sc_uint_base& left, const sc_unsigned& right )
720 { return operator*((uint64)left, right); }
721
722#undef MULTIPLY_BIG_BIG
723#undef MULTIPLY_BIG_NATIVE
724#undef MULTIPLY_NATIVE_BIG
725
726// +----------------------------------------------------------------------------
727// |"sc_signed/sc_unsigned subtraction operators"
728// |
729// | These are the operators for subtraction that involves at least one instance
730// | of sc_signed or sc_unsigned. The implementation is done using three macros:
731// | (a) SUBTRACT_BIG_BIG
732// | (b) SUBTRACT_BIG_NATIVE
733// | (c) SUBTRACT_NATIVE_BIG
734// +----------------------------------------------------------------------------
735
736#define SUBTRACT_BIG_BIG(LEFT_TYPE,RIGHT_TYPE) \
737inline \
738const sc_signed \
739operator-(const LEFT_TYPE& left, const RIGHT_TYPE& right) \
740 { \
741 int left_n = left.get_actual_length(); \
742 int right_n = right.get_actual_length(); \
743 \
744 if ( left_n >= right_n ) { \
745 sc_signed result(left_n+1, false); \
746 vector_subtract_shorter( left.get_hod(), \
747 left.get_digits(), \
748 right.get_hod(), \
749 right.get_digits(), \
750 result.get_hod(), \
751 result.get_digits() ); \
752 return result; \
753 } \
754 else { \
755 sc_signed result(right_n+1, false); \
756 vector_subtract_longer( right.get_hod(), \
757 right.get_digits(), \
758 left.get_hod(), \
759 left.get_digits(), \
760 result.get_hod(), \
761 result.get_digits() ); \
762 return result; \
763 } \
764 }
765
766#define SUBTRACT_BIG_NATIVE(BIG_TYPE,NATIVE_TYPE) \
767 inline \
768 const sc_signed \
769 operator-(const BIG_TYPE &left, NATIVE_TYPE native) \
770 { \
771 ScNativeDigits<NATIVE_TYPE> right( native ); \
772 const int left_n = left.get_actual_length(); \
773 const int right_n = right.get_actual_length(); \
774 \
775 if ( left_n > right_n ) { \
776 sc_signed result( left_n+1, false ); \
777 vector_subtract_shorter( left.get_hod(), \
778 left.get_digits(), \
779 right.get_hod(), \
780 right.get_digits(), \
781 result.get_hod(), \
782 result.get_digits() ); \
783 return result; \
784 } \
785 else { \
786 sc_signed result( right_n+1, false ); \
787 vector_subtract_longer( right.get_hod(), \
788 right.get_digits(), \
789 left.get_hod(), \
790 left.get_digits(), \
791 result.get_hod(), \
792 result.get_digits() ); \
793 return result; \
794 } \
795 }
796
797#define SUBTRACT_NATIVE_BIG(NATIVE_TYPE,BIG_TYPE) \
798 inline \
799 const sc_signed \
800 operator-(NATIVE_TYPE native, const BIG_TYPE &right) \
801 { \
802 \
803 ScNativeDigits<NATIVE_TYPE> left(native); \
804 const int left_n = left.get_actual_length(); \
805 const int right_n = right.get_actual_length(); \
806 \
807 if ( left_n > right_n ) { \
808 sc_signed result( left_n+1, false ); \
809 vector_subtract_shorter( left.get_hod(), \
810 left.get_digits(), \
811 right.get_hod(), \
812 right.get_digits(), \
813 result.get_hod(), \
814 result.get_digits() ); \
815 return result; \
816 } \
817 else { \
818 sc_signed result( right_n+1, false ); \
819 vector_subtract_longer( \
820 right.get_hod(), \
821 right.get_digits(), \
822 left.get_hod(), \
823 left.get_digits(), \
824 result.get_hod(), \
825 result.get_digits() ); \
826 return result; \
827 } \
828 }
829
830// big type - big type:
831
832SUBTRACT_BIG_BIG(sc_signed,sc_signed)
833SUBTRACT_BIG_BIG(sc_unsigned,sc_signed)
834SUBTRACT_BIG_BIG(sc_signed,sc_unsigned)
835SUBTRACT_BIG_BIG(sc_unsigned,sc_unsigned)
836
837// sc_signed - C++ native:
838
839SUBTRACT_BIG_NATIVE(sc_signed,int64)
841SUBTRACT_BIG_NATIVE(sc_signed,long)
842SUBTRACT_BIG_NATIVE(sc_signed,unsigned long)
843SUBTRACT_BIG_NATIVE(sc_signed,int)
844SUBTRACT_BIG_NATIVE(sc_signed,unsigned int)
845
846// C++ native - sc_signed:
847
848SUBTRACT_NATIVE_BIG(int64,sc_signed)
850SUBTRACT_NATIVE_BIG(long,sc_signed)
851SUBTRACT_NATIVE_BIG(unsigned long,sc_signed)
852SUBTRACT_NATIVE_BIG(int,sc_signed)
853SUBTRACT_NATIVE_BIG(unsigned int,sc_signed)
854
855// sc_unsigned - C++ native:
856
857SUBTRACT_BIG_NATIVE(sc_unsigned,int64)
858SUBTRACT_BIG_NATIVE(sc_unsigned,uint64)
859SUBTRACT_BIG_NATIVE(sc_unsigned,long)
860SUBTRACT_BIG_NATIVE(sc_unsigned,unsigned long)
861SUBTRACT_BIG_NATIVE(sc_unsigned,int)
862SUBTRACT_BIG_NATIVE(sc_unsigned,unsigned int)
863
864// C++ native - sc_unsigned:
865
866SUBTRACT_NATIVE_BIG(int64,sc_unsigned)
867SUBTRACT_NATIVE_BIG(uint64,sc_unsigned)
868SUBTRACT_NATIVE_BIG(long,sc_unsigned)
869SUBTRACT_NATIVE_BIG(unsigned long,sc_unsigned)
870SUBTRACT_NATIVE_BIG(int,sc_unsigned)
871SUBTRACT_NATIVE_BIG(unsigned int,sc_unsigned)
872
873// sc_int_base and sc_uint_base arguments:
874
875inline
876const sc_signed operator-( const sc_signed& left, const sc_int_base& right )
877 { return operator-(left, (int64)right); }
878
879inline
880const sc_signed operator-( const sc_signed& left, const sc_uint_base& right )
881 { return operator-(left, (uint64)right); }
882
883inline
884const sc_signed operator-( const sc_int_base& left, const sc_signed& right )
885 { return operator-((int64)left, right); }
886
887inline
888const sc_signed operator-( const sc_uint_base& left, const sc_signed& right )
889 { return operator-((uint64)left, right); }
890
891inline
892const sc_signed operator-( const sc_unsigned& left, const sc_int_base& right )
893 { return operator-(left, (int64)right); }
894
895inline
896const sc_signed operator-( const sc_int_base& left, const sc_unsigned& right )
897 { return operator-((int64)left, right); }
898
899inline
900const sc_signed operator-(const sc_unsigned& left, const sc_uint_base& right )
901 { return operator-(left, (uint64)right); }
902
903inline
904const sc_signed operator-(const sc_uint_base& left, const sc_unsigned& right )
905 { return operator-((uint64)left, right); }
906
907#undef SUBTRACT_BIG_BIG
908#undef SUBTRACT_BIG_NATIVE
909#undef SUBTRACT_NATIVE_BIG
910
911// +----------------------------------------------------------------------------
912// |"sc_signed/sc_unsigned bit-wise logic operators"
913// |
914// | These are the operators for bit-wise logic that involves at least one
915// | instance of sc_signed or sc_unsigned. The implementation is done using
916// | three macros:
917// | (a) BIT_OP_BIG_BIG
918// | (b) BIT_OP_BIG_NATIVE
919// | (c) BIT_OP_NATIVE_BIG
920// +----------------------------------------------------------------------------
921#define BIT_OP_BIG_BIG(OP,BIT_OP_RTN,RESULT_TYPE,LEFT_TYPE,RIGHT_TYPE) \
922inline \
923const RESULT_TYPE \
924operator OP (const LEFT_TYPE& left, const RIGHT_TYPE& right) \
925 { \
926 int left_n; \
927 int right_n; \
928 if ( RESULT_TYPE::SIGNED ) { \
929 left_n = left.get_actual_length(); \
930 right_n = right.get_actual_length(); \
931 } \
932 else { \
933 left_n = left.length(); \
934 right_n = right.length(); \
935 } \
936 \
937 if ( left_n >= right_n ) { \
938 RESULT_TYPE result(left_n, false); \
939 BIT_OP_RTN<LEFT_TYPE::SIGNED,RIGHT_TYPE::SIGNED>( \
940 left.get_hod(), \
941 left.get_digits(), \
942 right.get_hod(), \
943 right.get_digits(), \
944 result.get_digits() ); \
945 result.adjust_hod(); \
946 return result; \
947 } \
948 else { \
949 RESULT_TYPE result(right_n, false); \
950 BIT_OP_RTN<RIGHT_TYPE::SIGNED,LEFT_TYPE::SIGNED>( \
951 right.get_hod(), \
952 right.get_digits(), \
953 left.get_hod(), \
954 left.get_digits(), \
955 result.get_digits() ); \
956 result.adjust_hod(); \
957 return result; \
958 } \
959 }
960
961#define BIT_OP_BIG_NATIVE(OP,BIT_OP_RTN,RESULT_TYPE,BIG_TYPE,NATIVE_TYPE) \
962 inline \
963 const RESULT_TYPE \
964 operator OP (const BIG_TYPE &left, NATIVE_TYPE native) \
965 { \
966 int left_n; \
967 ScNativeDigits<NATIVE_TYPE> right( native ); \
968 int right_n; \
969 if ( RESULT_TYPE::SIGNED ) { \
970 left_n = left.get_actual_length(); \
971 right_n = right.get_actual_length(); \
972 } \
973 else { \
974 left_n = left.length(); \
975 right_n = right.length(); \
976 } \
977 \
978 if ( left_n > right_n ) { \
979 RESULT_TYPE result( left_n, false ); \
980 BIT_OP_RTN<BIG_TYPE::SIGNED,ScNativeDigits<NATIVE_TYPE>::SIGNED>( \
981 result.get_hod() < left.get_hod() ? result.get_hod() : left.get_hod(), \
982 left.get_digits(), \
983 result.get_hod() < right.get_hod() ? result.get_hod() : right.get_hod(), \
984 right.get_digits(), \
985 result.get_digits() ); \
986 result.adjust_hod(); \
987 return result; \
988 } \
989 else { \
990 RESULT_TYPE result( right_n, false ); \
991 BIT_OP_RTN<ScNativeDigits<NATIVE_TYPE>::SIGNED,BIG_TYPE::SIGNED>( \
992 result.get_hod() < right.get_hod() ? result.get_hod() : right.get_hod(), \
993 right.get_digits(), \
994 result.get_hod() < left.get_hod() ? result.get_hod() : left.get_hod(), \
995 left.get_digits(), \
996 result.get_digits() ); \
997 result.adjust_hod(); \
998 return result; \
999 } \
1000 }
1001
1002#define BIT_OP_NATIVE_BIG(OP,BIT_OP_RTN,RESULT_TYPE,NATIVE_TYPE,BIG_TYPE) \
1003 inline \
1004 const RESULT_TYPE \
1005 operator OP (NATIVE_TYPE native, const BIG_TYPE &right) \
1006 { \
1007 \
1008 ScNativeDigits<NATIVE_TYPE> left(native); \
1009 int left_n; \
1010 int right_n; \
1011 if ( RESULT_TYPE::SIGNED ) { \
1012 left_n = left.get_actual_length(); \
1013 right_n = right.get_actual_length(); \
1014 } \
1015 else { \
1016 left_n = left.length(); \
1017 right_n = right.length(); \
1018 } \
1019 \
1020 if ( left_n > right_n ) { \
1021 RESULT_TYPE result( left_n, false ); \
1022 BIT_OP_RTN<ScNativeDigits<NATIVE_TYPE>::SIGNED,BIG_TYPE::SIGNED>( \
1023 result.get_hod() < left.get_hod() ? result.get_hod() : left.get_hod(), \
1024 left.get_digits(), \
1025 result.get_hod() < right.get_hod() ? result.get_hod() : right.get_hod(), \
1026 right.get_digits(), \
1027 result.get_digits() ); \
1028 result.adjust_hod(); \
1029 return result; \
1030 } \
1031 else { \
1032 RESULT_TYPE result( right_n, false ); \
1033 BIT_OP_RTN<BIG_TYPE::SIGNED,ScNativeDigits<NATIVE_TYPE>::SIGNED>( \
1034 result.get_hod() < right.get_hod() ? result.get_hod() : right.get_hod(), \
1035 right.get_digits(), \
1036 result.get_hod() < left.get_hod() ? result.get_hod() : left.get_hod(), \
1037 left.get_digits(), \
1038 result.get_digits() ); \
1039 result.adjust_hod(); \
1040 return result; \
1041 } \
1042 }
1043
1044#define BIT_OPS_BIG(OPER,BIT_OP_RTN) \
1045 \
1046/* big type OPER big type: */ \
1047 \
1048BIT_OP_BIG_BIG(OPER,BIT_OP_RTN,sc_signed,sc_signed,sc_signed) \
1049BIT_OP_BIG_BIG(OPER,BIT_OP_RTN,sc_signed,sc_unsigned,sc_signed) \
1050BIT_OP_BIG_BIG(OPER,BIT_OP_RTN,sc_signed,sc_signed,sc_unsigned) \
1051BIT_OP_BIG_BIG(OPER,BIT_OP_RTN,sc_unsigned,sc_unsigned,sc_unsigned) \
1052 \
1053/* sc_signed OPER C++ native: */ \
1054 \
1055BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_signed,sc_signed,int64) \
1056BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_signed,sc_signed,uint64) \
1057BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_signed,sc_signed,long) \
1058BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_signed,sc_signed,unsigned long) \
1059BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_signed,sc_signed,int) \
1060BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_signed,sc_signed,unsigned int) \
1061 \
1062/* C++ native OPER sc_signed: */ \
1063 \
1064BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_signed,int64,sc_signed) \
1065BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_signed,uint64,sc_signed) \
1066BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_signed,long,sc_signed) \
1067BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_signed,unsigned long,sc_signed) \
1068BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_signed,int,sc_signed) \
1069BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_signed,unsigned int,sc_signed) \
1070 \
1071/* sc_unsigned OPER signed C++ native: */ \
1072 \
1073BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_signed,sc_unsigned,int64) \
1074BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_signed,sc_unsigned,long) \
1075BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_signed,sc_unsigned,int) \
1076 \
1077/* signed C++ native OPER sc_unsigned: */ \
1078 \
1079BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_signed,int64,sc_unsigned) \
1080BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_signed,long,sc_unsigned) \
1081BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_signed,int,sc_unsigned) \
1082 \
1083/* sc_unsigned OPER unsigned C++ native: */ \
1084 \
1085BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_unsigned,sc_unsigned,uint64) \
1086BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_unsigned,sc_unsigned,unsigned long) \
1087BIT_OP_BIG_NATIVE(OPER,BIT_OP_RTN,sc_unsigned,sc_unsigned,unsigned int) \
1088 \
1089/* unsigned C++ native OPER sc_unsigned: */ \
1090 \
1091BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_unsigned,uint64,sc_unsigned) \
1092BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_unsigned,unsigned long,sc_unsigned) \
1093BIT_OP_NATIVE_BIG(OPER,BIT_OP_RTN,sc_unsigned,unsigned int,sc_unsigned)
1094
1096
1097// sc_int_base and sc_uint_base arguments:
1098
1099inline
1100const sc_signed operator&( const sc_signed& left, const sc_int_base& right )
1101 { return operator&(left, (int64)right); }
1102
1103inline
1104const sc_signed operator&( const sc_signed& left, const sc_uint_base& right )
1105 { return operator&(left, (uint64)right); }
1106
1107inline
1108const sc_signed operator&( const sc_int_base& left, const sc_signed& right )
1109 { return operator&((int64)left, right); }
1110
1111inline
1112const sc_signed operator&( const sc_uint_base& left, const sc_signed& right )
1113 { return operator&((uint64)left, right); }
1114
1115inline
1116const sc_signed operator&( const sc_unsigned& left, const sc_int_base& right )
1117 { return operator&(left, (int64)right); }
1118
1119inline
1120const sc_signed operator&( const sc_int_base& left, const sc_unsigned& right )
1121 { return operator&((int64)left, right); }
1122
1123inline
1124const sc_unsigned operator&(const sc_unsigned& left, const sc_uint_base& right )
1125 { return operator&(left, (uint64)right); }
1126
1127inline
1128const sc_unsigned operator&(const sc_uint_base& left, const sc_unsigned& right )
1129 { return operator&((uint64)left, right); }
1130
1132
1133inline
1134const sc_signed operator|( const sc_signed& left, const sc_int_base& right )
1135 { return operator|(left, (int64)right); }
1136
1137inline
1138const sc_signed operator|( const sc_signed& left, const sc_uint_base& right )
1139 { return operator|(left, (uint64)right); }
1140
1141inline
1142const sc_signed operator|( const sc_int_base& left, const sc_signed& right )
1143 { return operator|((int64)left, right); }
1144
1145inline
1146const sc_signed operator|( const sc_uint_base& left, const sc_signed& right )
1147 { return operator|((uint64)left, right); }
1148
1149inline
1150const sc_signed operator|( const sc_unsigned& left, const sc_int_base& right )
1151 { return operator|(left, (int64)right); }
1152
1153inline
1154const sc_signed operator|( const sc_int_base& left, const sc_unsigned& right )
1155 { return operator|((int64)left, right); }
1156
1157inline
1158const sc_unsigned operator|(const sc_unsigned& left, const sc_uint_base& right )
1159 { return operator|(left, (uint64)right); }
1160
1161inline
1162const sc_unsigned operator|(const sc_uint_base& left, const sc_unsigned& right )
1163 { return operator|((uint64)left, right); }
1164
1165// sc_int_base and sc_uint_base arguments:
1166
1168
1169
1170// sc_int_base and sc_uint_base arguments:
1171
1172inline
1173const sc_signed operator^( const sc_signed& left, const sc_int_base& right )
1174 { return operator^(left, (int64)right); }
1175
1176inline
1177const sc_signed operator^( const sc_signed& left, const sc_uint_base& right )
1178 { return operator^(left, (uint64)right); }
1179
1180inline
1181const sc_signed operator^( const sc_int_base& left, const sc_signed& right )
1182 { return operator^((int64)left, right); }
1183
1184inline
1185const sc_signed operator^( const sc_uint_base& left, const sc_signed& right )
1186 { return operator^((uint64)left, right); }
1187
1188inline
1189const sc_signed operator^( const sc_unsigned& left, const sc_int_base& right )
1190 { return operator^(left, (int64)right); }
1191
1192inline
1193const sc_signed operator^( const sc_int_base& left, const sc_unsigned& right )
1194 { return operator^((int64)left, right); }
1195
1196inline
1197const sc_unsigned operator^(const sc_unsigned& left, const sc_uint_base& right )
1198 { return operator^(left, (uint64)right); }
1199
1200inline
1201const sc_unsigned operator^(const sc_uint_base& left, const sc_unsigned& right )
1202 { return operator^((uint64)left, right); }
1203
1204
1205#undef BIT_OP_BIG_BIG
1206#undef BIT_OP_BIG_NATIVE
1207#undef BIT_OP_NATIVE_BIG
1208#undef BIT_OPS_BIG
1209
1210// +----------------------------------------------------------------------------
1211// |"sc_signed auto increment/decrement operators"
1212// |
1213// | These are the auto increment and auto decrement operators for sc_signed.
1214// +----------------------------------------------------------------------------
1215
1216inline
1217sc_signed&
1219{
1220 *this = *this + 1;
1221 return *this;
1222}
1223
1224
1225inline
1228{
1229 // Make a copy before incrementing and return it.
1230
1231 sc_signed result(*this);
1232
1233 *this = *this + 1;
1234
1235 return result;
1236}
1237
1238inline
1239sc_signed&
1241{
1242 *this = *this - 1;
1243 return *this;
1244}
1245
1246
1247inline
1250{
1251 // Make a copy before decrementing and return it.
1252
1253 sc_signed result(*this);
1254
1255 *this = *this - 1;
1256
1257 return result;
1258}
1259
1260// +----------------------------------------------------------------------------
1261// |"sc_signed/sc_unsigned comparison operators"
1262// |
1263// | These operators perform comparisons between sc_signed and sc_unsigned
1264// | variables and another type.
1265// +----------------------------------------------------------------------------
1266#define COMPARE_BIG_BIG(OP,LEFT_TYPE,RIGHT_TYPE) \
1267 inline \
1268 bool \
1269 operator OP(const LEFT_TYPE& left, const RIGHT_TYPE& right) \
1270 { \
1271 \
1272 return vector_compare<LEFT_TYPE::SIGNED,RIGHT_TYPE::SIGNED>( \
1273 left.get_hod(), \
1274 left.get_digits(), \
1275 right.get_hod(), \
1276 right.get_digits() ) OP 0; \
1277 }
1278
1279#define COMPARE_BIG_NATIVE(OP,BIG_TYPE,NATIVE_TYPE) \
1280 inline \
1281 bool \
1282 operator OP(const BIG_TYPE &left, NATIVE_TYPE native) \
1283 { \
1284 ScNativeDigits<NATIVE_TYPE> right( native ); \
1285 \
1286 return \
1287 vector_compare<BIG_TYPE::SIGNED,ScNativeDigits<NATIVE_TYPE>::SIGNED>( \
1288 left.get_hod(), \
1289 left.get_digits(), \
1290 right.get_hod(), \
1291 right.get_digits() ) OP 0; \
1292 } \
1293
1294#define COMPARE_NATIVE_BIG(OP,NATIVE_TYPE,BIG_TYPE) \
1295 inline \
1296 bool \
1297 operator OP(NATIVE_TYPE native, const BIG_TYPE &right) \
1298 { \
1299 \
1300 ScNativeDigits<NATIVE_TYPE> left(native); \
1301 \
1302 return \
1303 vector_compare<ScNativeDigits<NATIVE_TYPE>::SIGNED,BIG_TYPE::SIGNED>( \
1304 left.get_hod(), \
1305 left.get_digits(), \
1306 right.get_hod(), \
1307 right.get_digits() ) OP 0; \
1308 }
1309
1310#define COMPARE_BIG_OPS(OP) \
1311 \
1312 /* big type + big type: */ \
1313 \
1314 COMPARE_BIG_BIG(OP,sc_signed,sc_signed) \
1315 COMPARE_BIG_BIG(OP,sc_unsigned,sc_signed) \
1316 COMPARE_BIG_BIG(OP,sc_signed,sc_unsigned) \
1317 COMPARE_BIG_BIG(OP,sc_unsigned,sc_unsigned) \
1318 \
1319 /* sc_signed + C++ native: */ \
1320 \
1321 COMPARE_BIG_NATIVE(OP,sc_signed,int64) \
1322 COMPARE_BIG_NATIVE(OP,sc_signed,uint64) \
1323 COMPARE_BIG_NATIVE(OP,sc_signed,long) \
1324 COMPARE_BIG_NATIVE(OP,sc_signed,unsigned long) \
1325 COMPARE_BIG_NATIVE(OP,sc_signed,int) \
1326 COMPARE_BIG_NATIVE(OP,sc_signed,unsigned int) \
1327 \
1328 /* C++ native + sc_signed: */ \
1329 \
1330 COMPARE_NATIVE_BIG(OP,int64,sc_signed) \
1331 COMPARE_NATIVE_BIG(OP,uint64,sc_signed) \
1332 COMPARE_NATIVE_BIG(OP,long,sc_signed) \
1333 COMPARE_NATIVE_BIG(OP,unsigned long,sc_signed) \
1334 COMPARE_NATIVE_BIG(OP,int,sc_signed) \
1335 COMPARE_NATIVE_BIG(OP,unsigned int,sc_signed) \
1336 \
1337 /* sc_unsigned + signed C++ native: */ \
1338 \
1339 COMPARE_BIG_NATIVE(OP,sc_unsigned,int64) \
1340 COMPARE_BIG_NATIVE(OP,sc_unsigned,long) \
1341 COMPARE_BIG_NATIVE(OP,sc_unsigned,int) \
1342 \
1343 /* signed C++ native + sc_unsigned: */ \
1344 \
1345 COMPARE_NATIVE_BIG(OP,int64,sc_unsigned) \
1346 COMPARE_NATIVE_BIG(OP,long,sc_unsigned) \
1347 COMPARE_NATIVE_BIG(OP,int,sc_unsigned) \
1348 \
1349 /* sc_unsigned + unsigned C++ native: */ \
1350 \
1351 COMPARE_BIG_NATIVE(OP,sc_unsigned,uint64) \
1352 COMPARE_BIG_NATIVE(OP,sc_unsigned,unsigned long) \
1353 COMPARE_BIG_NATIVE(OP,sc_unsigned,unsigned int) \
1354 \
1355 /* unsigned C++ native + sc_unsigned: */ \
1356 \
1357 COMPARE_NATIVE_BIG(OP,uint64,sc_unsigned) \
1358 COMPARE_NATIVE_BIG(OP,unsigned long,sc_unsigned) \
1359 COMPARE_NATIVE_BIG(OP,unsigned int,sc_unsigned) \
1360 \
1361 /* sc_int_base and sc_uint_base arguments: */ \
1362 \
1363 inline \
1364 bool operator OP( const sc_signed& left, const sc_int_base& right ) \
1365 { return (left OP (int64)right); } \
1366 \
1367 inline \
1368 bool operator OP( const sc_signed& left, const sc_uint_base& right ) \
1369 { return (left OP (uint64)right); } \
1370 \
1371 inline \
1372 bool operator OP( const sc_int_base& left, const sc_signed& right ) \
1373 { return ((int64)left OP right); } \
1374 \
1375 inline \
1376 bool operator OP( const sc_uint_base& left, const sc_signed& right ) \
1377 { return ((uint64)left OP right); } \
1378 \
1379 inline \
1380 bool operator OP( const sc_unsigned& left, const sc_int_base& right ) \
1381 { return (left OP (int64)right); } \
1382 \
1383 inline \
1384 bool operator OP( const sc_int_base& left, const sc_unsigned& right ) \
1385 { return ((int64)left OP right); } \
1386 \
1387 inline \
1388 bool operator OP(const sc_unsigned& left, const sc_uint_base& right ) \
1389 { return (left OP (uint64)right); } \
1390 \
1391 inline \
1392 bool operator OP(const sc_uint_base& left, const sc_unsigned& right ) \
1393 { return ((uint64)left OP right); }
1394
1401
1402#undef COMPARE_BIG_BIG
1403#undef COMPARE_BIG_NATIVE
1404#undef COMPARE_NATIVE_BIG
1405#undef COMPARE_BIG_OPS
1406
1407// +----------------------------------------------------------------------------
1408// |"sc_unsigned auto increment/decrement operators"
1409// |
1410// | These are the auto increment and auto decrement operators for sc_unsigned.
1411// +----------------------------------------------------------------------------
1412
1413inline
1414sc_unsigned&
1416{
1417 *this = *this + 1;
1418 return *this;
1419}
1420
1421
1422inline
1425{
1426 // Make copy to return before incrementing.
1427
1428 sc_unsigned result(*this);
1429
1430 *this = *this + 1;
1431
1432 return result;
1433}
1434
1435inline
1438{
1439 *this = *this - 1;
1440 return *this;
1441}
1442
1443
1444inline
1447{
1448 // Make copy to return before decrementing.
1449
1450 sc_unsigned result(*this);
1451
1452 *this = *this - 1;
1453
1454 return result;
1455}
1456
1457// +----------------------------------------------------------------------------
1458// |"op equals between sc_signed/sc_unsigned"
1459// |
1460// | This can't be done like ADD_BIT_NATIVE because we end up with
1461// | redundant definitions.
1462// +----------------------------------------------------------------------------
1463
1464#define BIG_OP_EQUALS(OPEQ,OP,BASE_TYPE,OTHER_TYPE) \
1465inline \
1466BASE_TYPE& \
1467BASE_TYPE::operator OPEQ (OTHER_TYPE right) \
1468{ \
1469 *this = *this OP right; \
1470 return *this; \
1471}
1472
1473#define BIG_OPS_EQUALS(OPEQ,OP) \
1474 BIG_OP_EQUALS(OPEQ,OP,sc_signed,const sc_signed&) \
1475 BIG_OP_EQUALS(OPEQ,OP,sc_signed,const sc_unsigned&) \
1476 BIG_OP_EQUALS(OPEQ,OP,sc_signed,int64) \
1477 BIG_OP_EQUALS(OPEQ,OP,sc_signed,long) \
1478 BIG_OP_EQUALS(OPEQ,OP,sc_signed,int) \
1479 BIG_OP_EQUALS(OPEQ,OP,sc_signed,uint64) \
1480 BIG_OP_EQUALS(OPEQ,OP,sc_signed,unsigned long) \
1481 BIG_OP_EQUALS(OPEQ,OP,sc_signed,unsigned int) \
1482 BIG_OP_EQUALS(OPEQ,OP,sc_unsigned,const sc_signed&) \
1483 BIG_OP_EQUALS(OPEQ,OP,sc_unsigned,const sc_unsigned&) \
1484 BIG_OP_EQUALS(OPEQ,OP,sc_unsigned,int64) \
1485 BIG_OP_EQUALS(OPEQ,OP,sc_unsigned,long) \
1486 BIG_OP_EQUALS(OPEQ,OP,sc_unsigned,int) \
1487 BIG_OP_EQUALS(OPEQ,OP,sc_unsigned,uint64) \
1488 BIG_OP_EQUALS(OPEQ,OP,sc_unsigned,unsigned long) \
1489 BIG_OP_EQUALS(OPEQ,OP,sc_unsigned,unsigned int) \
1490 inline sc_signed& sc_signed::operator OPEQ (const sc_int_base& right) \
1491 { return *this OPEQ (int64)right; } \
1492 inline sc_signed& sc_signed::operator OPEQ (const sc_uint_base& right) \
1493 { return *this OPEQ (uint64)right; } \
1494 inline sc_unsigned& sc_unsigned::operator OPEQ (const sc_int_base& right) \
1495 { return *this OPEQ (int64)right; } \
1496 inline sc_unsigned& sc_unsigned::operator OPEQ (const sc_uint_base& right) \
1497 { return *this OPEQ (uint64)right; }
1498
1499BIG_OPS_EQUALS(+=,+)
1500BIG_OPS_EQUALS(/=,/)
1501BIG_OPS_EQUALS(%=,%)
1502BIG_OPS_EQUALS(*=,*)
1503BIG_OPS_EQUALS(-=,-)
1504BIG_OPS_EQUALS(&=,&)
1505BIG_OPS_EQUALS(|=,|)
1506BIG_OPS_EQUALS(^=,^)
1507
1508// +----------------------------------------------------------------------------
1509// |"operator ~"
1510// |
1511// | These operators return the one's complement of the supplied object
1512// | instance.
1513// |
1514// | Arguments:
1515// | u = object instance to return the one's complement of.
1516// | Result:
1517// | one's complement of 'u'.
1518// +----------------------------------------------------------------------------
1519inline
1520sc_signed
1521operator~(const sc_signed& u)
1522{
1523 sc_signed result( u.length() );
1524 sc_digit* result_p = result.get_digits();
1525 sc_digit* source_p = u.get_digits();
1526 int hod = u.get_hod();
1527 for ( int digit_i = 0; digit_i <= hod; ++digit_i ) {
1528 result_p[digit_i] = ~source_p[digit_i];
1529 }
1530 return result;
1531}
1532
1533inline
1536{
1537 sc_signed result( u.length()+1 );
1538 sc_digit* result_p = result.get_digits();
1539 sc_digit* source_p = u.get_digits();
1540 int hod = u.get_hod();
1541 for ( int digit_i = 0; digit_i <= hod; ++digit_i ) {
1542 result_p[digit_i] = ~source_p[digit_i];
1543 }
1544 if ( result.get_hod() > hod ) {
1545 result_p[hod] = (sc_digit)-1;
1546 }
1547 return result;
1548}
1549
1550#undef BIG_OP_EQUALS
1551#undef BIG_OPS_EQUAL
1552
1553#undef OPS_MIN
1554#undef OPS_MAX
1555
1556} // namespace sc_dt
1557
1558#endif // SC_SIGNED_OPS_H
1559
#define BIG_OPS_EQUALS(OPEQ, OP)
#define SUBTRACT_NATIVE_BIG(NATIVE_TYPE, BIG_TYPE)
#define DIVIDE_NATIVE_BIG(RESULT_TYPE, NATIVE_TYPE, BIG_TYPE)
#define DIVIDE_BIG_BIG(RESULT_TYPE, LEFT_TYPE, RIGHT_TYPE)
#define ADD_NATIVE_BIG(RESULT_TYPE, NATIVE_TYPE, BIG_TYPE)
#define COMPARE_BIG_OPS(OP)
#define SUBTRACT_BIG_NATIVE(BIG_TYPE, NATIVE_TYPE)
#define SUBTRACT_BIG_BIG(LEFT_TYPE, RIGHT_TYPE)
#define MULTIPLY_BIG_NATIVE(RESULT_TYPE, BIG_TYPE, NATIVE_TYPE)
#define MODULO_NATIVE_BIG(RESULT_TYPE, NATIVE_TYPE, BIG_TYPE)
#define MULTIPLY_BIG_BIG(RESULT_TYPE, LEFT_TYPE, RIGHT_TYPE)
#define MODULO_BIG_NATIVE(RESULT_TYPE, BIG_TYPE, NATIVE_TYPE)
#define MODULO_BIG_BIG(RESULT_TYPE, LEFT_TYPE, RIGHT_TYPE)
#define MULTIPLY_NATIVE_BIG(RESULT_TYPE, NATIVE_TYPE, BIG_TYPE)
#define DIVIDE_BIG_NATIVE(RESULT_TYPE, BIG_TYPE, NATIVE_TYPE)
#define BIT_OPS_BIG(OPER, BIT_OP_RTN)
#define ADD_BIG_BIG(RESULT_TYPE, LEFT_TYPE, RIGHT_TYPE)
Definition: sc_signed_ops.h:50
#define ADD_BIG_NATIVE(RESULT_TYPE, BIG_TYPE, NATIVE_TYPE)
Definition: sc_signed_ops.h:80
sc_bit operator&(const sc_bit &a, const sc_bit &b)
Definition: sc_bit.h:331
void vector_xor(const int longer_hod, const sc_digit *longer_p, const int shorter_hod, const sc_digit *shorter_p, sc_digit *result_p)
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
sc_fxval operator/(const sc_fxnum &a, const sc_fxnum &b)
Definition: sc_fxnum.h:2849
unsigned long long uint64
Definition: sc_nbdefs.h:216
void vector_or(const int longer_hod, const sc_digit *longer_p, const int shorter_hod, const sc_digit *shorter_p, sc_digit *result_p)
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
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
unsigned int sc_digit
Definition: sc_nbdefs.h:161
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 vector_and(const int longer_hod, const sc_digit *longer_p, const int shorter_hod, const sc_digit *shorter_p, sc_digit *result_p)
sc_bit operator~(const sc_bit &a)
Definition: sc_bit.h:312
sc_bit operator|(const sc_bit &a, const sc_bit &b)
Definition: sc_bit.h:334
long long int64
Definition: sc_nbdefs.h:215
sc_signed & operator++()
int get_hod() const
Definition: sc_signed.h:1201
sc_digit * get_digits() const
Definition: sc_signed.h:1198
sc_signed & operator--()
sc_digit * get_digits() const
Definition: sc_unsigned.h:1186
sc_unsigned & operator++()
int get_hod() const
Definition: sc_unsigned.h:1189
int length() const
Definition: sc_unsigned.h:808
sc_unsigned & operator--()