SystemC 3.0.0
Accellera SystemC proof-of-concept library
sc_vector_utils.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#if !defined(SC_VECTOR_UTILS_H)
20#define SC_VECTOR_UTILS_H
21
22#include "sc_nbdefs.h"
23#include "sc_nbutils.h"
24
25namespace sc_dt {
26
27#define VEC_MIN(A,B) ( (A) <= (B) ? A : B )
28#define VEC_MAX(A,B) ( (A) >= (B) ? A : B )
29
30// External entities:
31
32template<int W> class sc_bigint;
33template<int W> class sc_biguint;
34class sc_signed;
35class sc_unsigned;
36
37// +============================================================================
38// |"sc_big_op_type<WIDTH,SIGNED>
39// |
40// | This templated class provides the operand type for big values with the
41// | supplied width and signedness.
42// +============================================================================
43template<int WIDTH, bool SIGNED>
45
46template<int WIDTH>
47class sc_big_op_type<WIDTH,true>
48{
49 public:
51 typedef int hod_type;
53};
54
55template<int WIDTH>
56class sc_big_op_type<WIDTH,false>
57{
58 public:
62};
63
64// +============================================================================
65// |"sc_big_op_info<WL,SL,WR,SR>
66// |
67// | This templated class provides information for operations involving two
68// | sc_bigint<W> and sc_biguint<W> operands.
69// |
70// | Template arguments:
71// | WL = width of left operand of the operation.
72// | SL = true if left operand is signed.
73// | WR = width of right operand of the operation.
74// | SR = true if right operand is signed.
75// +============================================================================
76template<int WL, bool SL, int WR, bool SR>
78{
79 public: // width calculations:
80 enum {
81 signed_result = SL || SR,
82
84 left_extra = !SL && SR,
86
88 right_extra = SL && !SR,
90
93 div_bits = WL+SR,
95 mul_bits = WL+WR,
97
104
111
112 shorter_length = SC_DIGIT_COUNT( VEC_MIN(WL+!SL,WR+!SR) )
113 };
114
115 public: // operand types:
120
121 public: // result types:
128};
129
130// +============================================================================
131// |"ScNativeDigits"
132// |
133// | This templated class contains the value of its template type as a vector
134// | of sc_digit values. It is overloaded for each native C++ data type.
135// +============================================================================
136template<typename T> class ScNativeDigits;
137
138template<>
140{
141 public:
142 enum {
143 ACTUAL_WIDTH = 8*sizeof(int64),
144 DIGITS_N = SC_DIGIT_COUNT(ACTUAL_WIDTH),
145 HOD = SC_DIGIT_INDEX(ACTUAL_WIDTH-1),
146 WIDTH = ACTUAL_WIDTH,
147 SIGNED = 1
148 };
149
150 public:
152 {
153 m_digits[0] = (sc_digit)init;
154 for ( int digit_i = 1; digit_i < DIGITS_N; ++digit_i ) {
155 init >>= BITS_PER_DIGIT;
156 m_digits[digit_i] = (sc_digit)init;
157 }
158 }
159 int get_actual_length() const { return ACTUAL_WIDTH; }
160 const sc_digit* get_digits() const { return m_digits; }
161 sc_digit* get_digits() { return m_digits; }
162 int get_digits_n() const { return DIGITS_N; }
163 int get_hod() const { return HOD; }
164 int is_signed() const { return SIGNED; }
165 int length() const { return WIDTH; }
166 protected:
167 sc_digit m_digits[DIGITS_N];
168};
169
170template<>
172{
173 public:
174 enum {
175 ACTUAL_WIDTH = 8*sizeof(uint64)+1,
176 DIGITS_N = SC_DIGIT_COUNT(ACTUAL_WIDTH),
177 HOD = SC_DIGIT_INDEX(ACTUAL_WIDTH-1),
178 WIDTH = ACTUAL_WIDTH-1,
179 SIGNED = 0
180 };
181
182 public:
184 {
185 m_digits[0] = (sc_digit)init;
186 for ( int digit_i = 1; digit_i < DIGITS_N; ++digit_i ) {
187 init >>= BITS_PER_DIGIT;
188 m_digits[digit_i] = (sc_digit)init;
189 }
190 }
191 int get_actual_length() const { return ACTUAL_WIDTH; }
192 const sc_digit* get_digits() const { return m_digits; }
193 sc_digit* get_digits() { return m_digits; }
194 int get_digits_n() const { return DIGITS_N; }
195 int get_hod() const { return HOD; }
196 int is_signed() const { return SIGNED; }
197 int length() const { return WIDTH; }
198 protected:
199 sc_digit m_digits[DIGITS_N];
200};
201
202template<>
203class ScNativeDigits<long>
204{
205 public:
206 enum {
207 ACTUAL_WIDTH = 8*sizeof(long),
208 DIGITS_N = SC_DIGIT_COUNT(ACTUAL_WIDTH),
209 HOD = SC_DIGIT_INDEX(ACTUAL_WIDTH-1),
210 WIDTH = ACTUAL_WIDTH,
211 SIGNED = 1
212 };
213
214 public:
215 ScNativeDigits( long init )
216 {
217 m_digits[0] = (sc_digit)init;
218 for ( int digit_i = 1; digit_i < DIGITS_N; ++digit_i ) {
219 init >>= (ACTUAL_WIDTH > BITS_PER_DIGIT) ? BITS_PER_DIGIT : 0;
220 m_digits[digit_i] = (sc_digit)init;
221 }
222 }
223 int get_actual_length() const { return ACTUAL_WIDTH; }
224 const sc_digit* get_digits() const { return m_digits; }
225 sc_digit* get_digits() { return m_digits; }
226 int get_digits_n() const { return DIGITS_N; }
227 int get_hod() const { return HOD; }
228 int is_signed() const { return SIGNED; }
229 int length() const { return WIDTH; }
230 protected:
231 sc_digit m_digits[DIGITS_N];
232};
233
234template<>
235class ScNativeDigits<unsigned long>
236{
237 public:
238 enum {
239 ACTUAL_WIDTH = 8*sizeof(unsigned long)+1,
240 DIGITS_N = SC_DIGIT_COUNT(ACTUAL_WIDTH),
241 HOD = SC_DIGIT_INDEX(ACTUAL_WIDTH-1),
242 WIDTH = ACTUAL_WIDTH-1,
243 SIGNED = 0
244 };
245
246 public:
247 ScNativeDigits( unsigned long init )
248 {
249 m_digits[0] = (sc_digit)init;
250 unsigned long long llinit = init;
251 for ( int digit_i = 1; digit_i < DIGITS_N; ++digit_i ) {
252 llinit >>= BITS_PER_DIGIT;
253 m_digits[digit_i] = (sc_digit)llinit;
254 }
255 }
256 int get_actual_length() const { return ACTUAL_WIDTH; }
257 const sc_digit* get_digits() const { return m_digits; }
258 sc_digit* get_digits() { return m_digits; }
259 int get_digits_n() const { return DIGITS_N; }
260 int get_hod() const { return HOD; }
261 int is_signed() const { return SIGNED; }
262 int length() const { return WIDTH; }
263 protected:
264 sc_digit m_digits[DIGITS_N];
265};
266
267template<>
269{
270 public:
271 enum {
272 ACTUAL_WIDTH = 8*sizeof(int),
273 DIGITS_N = SC_DIGIT_COUNT(ACTUAL_WIDTH),
274 HOD = SC_DIGIT_INDEX(ACTUAL_WIDTH-1),
275 WIDTH = ACTUAL_WIDTH,
276 SIGNED = 1
277 };
278
279 public:
280 ScNativeDigits( int init )
281 {
282 m_digits[0] = (sc_digit)init;
283 }
284 int get_actual_length() const { return ACTUAL_WIDTH; }
285 const sc_digit* get_digits() const { return m_digits; }
286 sc_digit* get_digits() { return m_digits; }
287 int get_digits_n() const { return DIGITS_N; }
288 int get_hod() const { return HOD; }
289 int length() const { return WIDTH; }
290 int is_signed() const { return SIGNED; }
291 protected:
292 sc_digit m_digits[DIGITS_N];
293};
294
295template<>
296class ScNativeDigits<unsigned int>
297{
298 public:
299 enum {
300 ACTUAL_WIDTH = 8*sizeof(unsigned int)+1,
301 DIGITS_N = SC_DIGIT_COUNT(ACTUAL_WIDTH),
302 HOD = SC_DIGIT_INDEX(ACTUAL_WIDTH-1),
303 WIDTH = ACTUAL_WIDTH-1,
304 SIGNED = 0
305 };
306
307 public:
308 ScNativeDigits( unsigned long init )
309 {
310 m_digits[0] = (sc_digit)init;
311 m_digits[1] = 0;
312 }
313 int get_actual_length() const { return ACTUAL_WIDTH; }
314 const sc_digit* get_digits() const { return m_digits; }
315 sc_digit* get_digits() { return m_digits; }
316 int get_digits_n() const { return DIGITS_N; }
317 int get_hod() { return HOD; }
318 int is_signed() { return SIGNED; }
319 int length() { return WIDTH; }
320 protected:
321 sc_digit m_digits[DIGITS_N];
322};
323
324// +----------------------------------------------------------------------------
325// |"vector_skip_leading_ones"
326// |
327// | This function returns the index of the highest order sc_digit in the
328// | supplied vector that is not all ones, or zero if all sc_digits are all
329// | ones.
330// |
331// | Arguments:
332// | hod = index of high order digit in 'digits_p'.
333// | digits_p = vector of digits to find the highest non-zero entry in.
334// | Result:
335// | index of the highest order non-all-ones entry in 'digits_p' or 0 if
336// | all the entries in 'digits_p' are all ones.
337// +----------------------------------------------------------------------------
338inline
339int
340vector_skip_leading_ones( const int hod, const sc_digit* digits_p )
341{
342 int digit_i; // digit now examining.
343 for ( digit_i = hod; (digit_i > 0) && (digits_p[digit_i] == ~0u); --digit_i )
344 continue;
345 return digit_i;
346}
347
348// +----------------------------------------------------------------------------
349// |"vector_skip_leading_zeros"
350// |
351// | This function returns the index of the highest order sc_digit in the
352// | supplied vector that is non-zero, or zero if there is not a non-zero
353// | sc_digit in the vector.
354// |
355// | Arguments:
356// | hod = index of high order digit in 'digits_p'.
357// | digits_p = vector of digits to find the highest non-zero entry in.
358// | Result:
359// | index of the highest order non-zero entry in 'digits_p' or 0 if
360// | all the entries in 'digits_p' are zero.
361// +----------------------------------------------------------------------------
362inline
363int
364vector_skip_leading_zeros( const int hod, const sc_digit* digits_p )
365{
366 int digit_i; // digit now examining.
367 for ( digit_i = hod; (digit_i > 0) && (digits_p[digit_i] == 0); --digit_i )
368 continue;
369 return digit_i;
370}
371
372// +------------------------------------------------------------------------------------------------
373// |"vector_find_significant_hod"
374// |
375// | This function finds the "significant" high order digit of the supplied vector. For a
376// | positive number leading zero digits are skipped, however, if the resultant high order
377// | digit would be negative one digit of zeroes is added back in.
378// | Similarly for a negative number leading all one digits are skipped, however, if the resultant
379// | high order digit would be positive one digit of all ones is added back in.
380// |
381// | Arguments:
382// | hod = high order digit of 'digits'.
383// | digits = digits to be examined.
384// | Result:
385// | index of significant order digit.
386// +------------------------------------------------------------------------------------------------
387inline int vector_find_significant_hod( int hod, const sc_digit* digits )
388{
389 int result_hod;
390 if ( (int)digits[hod] < 0 ) {
391 result_hod = vector_skip_leading_ones( hod, digits );
392 if ( (int)digits[result_hod] >= 0 ) { ++result_hod; }
393 }
394 else {
395 result_hod = vector_skip_leading_zeros( hod, digits );
396 if ( (int)digits[result_hod] < 0 ) { ++result_hod; }
397 }
398 return result_hod;
399}
400
401// +----------------------------------------------------------------------------
402// |"vector_add"
403// |
404// | This function adds two signed sc_digit vectors. The second vector must be
405// | shorter, or the same length, as the first one. The algorithm is from
406// | grade school:
407// | AS A5 A4 A3 A2 A1
408// | + BS B3 B2 B1
409// | --------------------
410// | R7 R6 R5 R4 R3 R2 R1
411// |
412// | Let BPD represent the number of bits per digit.
413// |
414// | Raw1 = A1 + B1
415// | Raw2 = (Raw1 >> BPD) + A2 + B2
416// | Raw3 = (Raw2 >> BPD) + A3 + B3
417// | Raw4 = (Raw3 >> BPD) + A4 + (signed)BS
418// | Raw5 = (Raw4 >> BPD) + A5
419// | Raw6 = (Raw5 >> BPD) + (signed)AS
420// | Raw7 = (Raw6 >> BPD)
421// |
422// | R1 = Raw1 % BPD
423// | R2 = Raw2 % BPD
424// | R3 = Raw3 % BPD
425// | R4 = Raw4 % BPD
426// | R5 = Raw5 % BPD
427// | R6 = Raw6 % BPD
428// | R7 = Raw7 % BPD
429// |
430// | Notes:
431// | (1) Either longer_p or shorter_p may also be result_p without
432// | consequences.
433// | Arguments:
434// | longer_hod = index of high order digit in 'longer_p'
435// | longer_p = digits in the longer operand.
436// | shorter_hod = index of high order digit in 'shorter_p'
437// | shorter_p = digits in the shorter operand
438// | result_hod = index of high order digit in 'result_p'
439// | result_p = digits to be filled in in the result.
440// +----------------------------------------------------------------------------
441inline
442void
443vector_add( const int longer_hod,
444 const sc_digit* longer_p,
445 const int shorter_hod,
446 const sc_digit* shorter_p,
447 const int result_hod,
448 sc_digit* result_p )
449{
450
451 if ( result_hod == 0 ) {
452 *result_p = *longer_p + *shorter_p;
453 return;
454 }
455
456 int64 carry = 0;
457 int digit_i;
458
459 // Add the low order unsigned parts of the operands:
460
461 for ( digit_i = 0; digit_i < shorter_hod; ++digit_i ) {
462 carry += *shorter_p++;
463 carry += *longer_p++;
464 *result_p++ = (sc_digit)carry;
465 carry >>= BITS_PER_DIGIT;
466 }
467
468 // The operands are the same length: add the high order digits as signed
469 // values:
470
471 if ( longer_hod == shorter_hod ) {
472 carry += (int64)(int)*shorter_p++;
473 carry += (int64)(int)*longer_p++;
474 *result_p++ = (sc_digit)carry;
475 carry >>= BITS_PER_DIGIT;
476 }
477
478 // The operands are different lengths:
479 // (a) Add the shorter operand's high order digit as a signed value.
480 // (b) Add the longer operand's values below its high order digit as
481 // unsigned.
482 // (c) Add the high order digit as signed.
483
484 else {
485 carry += (int64)(int)*shorter_p++;
486 carry += *longer_p++;
487 *result_p++ = (sc_digit)carry;
488 carry >>= BITS_PER_DIGIT;
489
490 for ( digit_i = shorter_hod+1; digit_i < longer_hod; ++digit_i ) {
491 carry += *longer_p++;
492 *result_p++ = (sc_digit)carry;
493 carry >>= BITS_PER_DIGIT;
494 }
495
496 carry += (int64)(int)*longer_p++;
497 *result_p++ = (sc_digit)carry;
498 carry >>= BITS_PER_DIGIT;
499 }
500
501
502 // If there is an additional high order digit in the result assign it the
503 // carry value:
504
505 if ( result_hod > longer_hod ) {
506 *result_p = (sc_digit)carry;
507 }
508}
509
510// +----------------------------------------------------------------------------
511// |"vector_and"
512// |
513// | This function ands two signed sc_digit vectors. The second vector must be
514// | shorter, or the same length, as the longer one.
515// |
516// | Template arguments:
517// | SL - true if longer operand is signed.
518// | SS - true if shorter operand is signed.
519// | Arguments:
520// | longer_hod = index of high order digit in 'longer_p' and 'result_p'.
521// | longer_p = digits in the longer operand.
522// | shorter_hod = index of high order digit in 'shorter_p'
523// | shorter_p = digits in the shorter operand
524// | result_p = digits to be filled in in the result, this is the same
525// | number of digits as the longer operand.
526// +----------------------------------------------------------------------------
527template<bool SL, bool SS>
528inline
529void
530vector_and( const int longer_hod,
531 const sc_digit* longer_p,
532 const int shorter_hod,
533 const sc_digit* shorter_p,
534 sc_digit* result_p )
535{
536 if ( 0 == longer_hod ) {
537 *result_p = *longer_p & *shorter_p;
538 return;
539 }
540
541 int digit_i;
542
543 // And the two operands to the length of the shorter operand:
544
545 for ( digit_i = 0; digit_i <= shorter_hod; ++digit_i ) {
546 *result_p++ = *longer_p++ & shorter_p[digit_i];
547 }
548
549 // If the shorter operand is negative fill out the remaining entries
550 // using the longer operand, otherwise fill it out with zeros.
551
552 if ( longer_hod > shorter_hod ) {
553 if ( SS && 0 > (int)shorter_p[shorter_hod] ) {
554 for ( ; digit_i <= longer_hod; ++digit_i ) {
555 *result_p++ = *longer_p++;
556 }
557 }
558 else {
559 for ( ; digit_i <= longer_hod; ++digit_i ) {
560 *result_p++ = 0;
561 }
562 }
563 }
564}
565
566// +----------------------------------------------------------------------------
567// |"vector_and_reduce"
568// |
569// | This function overload performs an "and reduction" on the supplied vector,
570// | returning the result.
571// |
572// | Arguments:
573// | bits_n = number of bits in the vector that are valid.
574// | target_p = digits containing the bits.
575// | Result:
576// | true if all bits are on in the vector, false if not.
577// +----------------------------------------------------------------------------
578inline
579bool
580vector_and_reduce( const int bits_n,
581 const sc_digit* target_p )
582{
583 const int hod = SC_DIGIT_INDEX(bits_n-1);
584
585 // First check the whole sc_digits:
586
587 for ( int digit_i = 0; digit_i < hod; ++digit_i ) {
588 if ( target_p[digit_i] != (sc_digit)-1 ) {
589 return false;
590 }
591 }
592
593 // Check the high order digit:
594
595 const sc_digit mask = ~( (std::numeric_limits<sc_digit>::max()-1)
596 << SC_BIT_INDEX(bits_n-1) );
597 if ( ( target_p[hod] & mask ) != mask ) {
598 return false;
599 }
600 return true;
601}
602
603// +----------------------------------------------------------------------------
604// |"vector_and_reduce"
605// |
606// | This function overload performs an "and reduction" on the requested range
607// | of bits in the supplied vector, returning the result.
608// |
609// | Arguments:
610// | target_p = digits containing the bits.
611// | left_i = left-most bit in the range to be checked.
612// | right_i = right-most bit in the range to be checked.
613// | Result:
614// | true if all bits are on in the vector, false if not.
615// +----------------------------------------------------------------------------
616inline
617bool
619 const int left_i,
620 const int right_i )
621{
622 const int left_hod = SC_DIGIT_INDEX(left_i);
623 const int right_hod = SC_DIGIT_INDEX(right_i);
624
625 // All the bits are in a single sc_digit:
626
627 if ( left_hod == right_hod ) {
628 const sc_digit mask =
629 ~((std::numeric_limits<sc_digit>::max()-1) << (left_i-right_i) );
630 return ( ( target_p[right_hod] & mask ) != mask ) ? false : true;
631 }
632
633 const int right_index = SC_BIT_INDEX(right_i);
634
635 // The low order bit is not on an sc_digit boundary, check the low
636 // order digit, then the whole sc_digits above it.
637
638 if ( right_index ) {
639 const sc_digit mask =
640 (std::numeric_limits<sc_digit>::max() << (right_index-1) );
641 if ( ( target_p[right_hod] & mask ) != mask ) {
642 return false;
643 }
644 for ( int digit_i = right_hod+1; digit_i < left_hod; ++digit_i ) {
645 if ( target_p[digit_i] != (sc_digit)-1 ) {
646 return false;
647 }
648 }
649 }
650
651 // The lower order bit is on an sc_digit boundary, check the whole
652 // sc_digits below the high order digit.
653
654 else {
655 for ( int digit_i = right_hod; digit_i < left_hod; ++digit_i ) {
656 if ( target_p[digit_i] != (sc_digit)-1 ) {
657 return false;
658 }
659 }
660 }
661
662 // Check the high order sc_digit:
663
664 const sc_digit mask =
665 ~( (std::numeric_limits<sc_digit>::max()-1) << SC_BIT_INDEX(left_i) );
666 if ( ( target_p[left_hod] & mask ) != mask ) {
667 return false;
668 }
669 return true;
670}
671
672// +----------------------------------------------------------------------------
673// |"vector_compare"
674// |
675// | This inline function compares the two supplied vectors, returing their
676// | relationship.
677// |
678// | Template arguments:
679// | SL = true if left argument is signed, false if not.
680// | SR = true if right argument is signed, false if not.
681// | Arguments:
682// | left_hod = index of the high order 'left' digit.
683// | left_p = vector of digits to be compared.
684// | right_hod = index of the high order 'right' digit.
685// | right_p = second vector of digits to be compared.
686// | Result:
687// | -1 if left < right.
688// | 0 if left == right.
689// | +1 if left > right.
690// +----------------------------------------------------------------------------
691template<int SL, int SR>
692inline
693int
694vector_compare( const int left_hod,
695 const sc_digit* left_p,
696 const int right_hod,
697 const sc_digit* right_p )
698{
699 int digit_i; // index into left_p and right_p.
700 int left_hod_value; // left hod value as an integer.
701 int right_hod_value; // right hod value as an integer.
702
703 // Left operand is negative, right operand is unsigned.:
704
705 left_hod_value = (int)left_p[left_hod];
706 if ( SL == true && SR == false && ( 0 > left_hod_value ) ) {
707 return -1;
708 }
709
710 // Right operand is negative, left operand is unsigned.:
711
712 right_hod_value = (int)right_p[right_hod];
713 if ( SL == false && SR == true && ( 0 > right_hod_value ) ) {
714 return 1;
715 }
716
717 // Both operands are signed and left operand is negative and right operand
718 // is not negative:
719
720 if ( SL == true && SR == true && (0 > left_hod_value) &&
721 (0 <= right_hod_value ) ) {
722 return -1;
723 }
724
725 // Both operands are signed and right operand is negative and left operand
726 // is not negative:
727
728 if ( SL == true && SR == true && (0 <= left_hod_value) &&
729 (0 > right_hod_value ) ) {
730 return 1;
731 }
732
733 // Both values are negative:
734
735 else if ( SL == true && SR == true && (0 > left_hod_value) ) {
736 if ( left_hod >= right_hod ) {
737 for ( digit_i = left_hod; digit_i > right_hod; --digit_i ) {
738 if ( left_p[digit_i] != (sc_digit)-1 ) {
739 return -1;
740 }
741 }
742 }
743 else {
744 for ( digit_i = right_hod; digit_i > left_hod; --digit_i ) {
745 if ( right_p[digit_i] != (sc_digit)-1 ) {
746 return 1;
747 }
748 }
749 }
750 for ( ; digit_i >= 0; --digit_i ) {
751 if ( left_p[digit_i] != right_p[digit_i] ) {
752 return ( left_p[digit_i] < right_p[digit_i] ) ? -1 : 1;
753 }
754 }
755 return 0;
756 }
757
758 // Neither value is negative:
759
760 else {
761 if ( left_hod >= right_hod ) {
762 for ( digit_i = left_hod; digit_i > right_hod; --digit_i ) {
763 if ( left_p[digit_i] != 0 ) {
764 return 1;
765 }
766 }
767 }
768 else {
769 for ( digit_i = right_hod; digit_i > left_hod; --digit_i ) {
770 if ( right_p[digit_i] != 0 ) {
771 return -1;
772 }
773 }
774 }
775 for ( ; digit_i >= 0; --digit_i ) {
776 if ( left_p[digit_i] != right_p[digit_i] ) {
777 return ( left_p[digit_i] < right_p[digit_i] ) ? -1 : 1;
778 }
779 }
780 return 0;
781 }
782}
783
784// +----------------------------------------------------------------------------
785// |"vector_copy"
786// |
787// | This inline function copies from one vector of sc_digits to another. The
788// | from vector is treated as "signed", so if its upper bit is one any
789// | extension will be ones, otherwise it will be zeros.
790// |
791// | Arguments:
792// | from_n = length of 'from_p'.
793// | from_p = vector of digits to be copied from.
794// | to_n = length of 'to_p'.
795// | to_p = vector of digits to be copied to.
796// +----------------------------------------------------------------------------
797inline
798void
799vector_copy( const int from_n,
800 const sc_digit* from_p,
801 const int to_n,
802 sc_digit* to_p )
803{
804 int digit_i; // digit now accessing.
805
806 if ( from_n < to_n ) {
807 for ( digit_i = 0; digit_i < from_n; ++digit_i ) {
808 to_p[digit_i] = from_p[digit_i];
809 }
810 sc_digit fill = 0 > (int)from_p[from_n-1] ? -1 : 0;
811 for ( ; digit_i < to_n; ++digit_i ) {
812 to_p[digit_i] = fill;
813 }
814 }
815 else {
816 for ( digit_i = 0; digit_i < to_n; ++digit_i ) {
817 to_p[digit_i] = from_p[digit_i];
818 }
819 }
820}
821
822// +----------------------------------------------------------------------------
823// |"vector_copy"
824// |
825// | This inline function copies from one vector of sc_digits to another of the
826// | exact same size.
827// |
828// | Arguments:
829// | digits_n = number of digits to be copied.
830// | from_p = vector of digits to be copied from.
831// | to_p = vector of digits to be copied to.
832// +----------------------------------------------------------------------------
833inline
834void
835vector_copy( int digits_n,
836 const sc_digit* from_p,
837 sc_digit* to_p )
838{
839 for ( int digit_i = 0; digit_i < digits_n; ++digit_i ) {
840 to_p[digit_i] = from_p[digit_i];
841 }
842}
843
844// +----------------------------------------------------------------------------
845// |"vector_extract"
846// |
847// | This inline function extracts the specified bits.
848// | (1) high_bit must be greater than or equal to low_bit.
849// | (2) any high order bits in the high order digit of destination_p that are not part
850// | of the the value from source_p will be zeroed.
851// | Arguments:
852// | source_p -> where to extract the bits from.
853// | destination_p -> where to place the extracted bits.
854// | high_bit = high order bit of the extraction.
855// | low_bit = low order bit of the extraction.
856// +----------------------------------------------------------------------------
857inline
858void
859vector_extract( const sc_digit* source_p,
860 sc_digit* destination_p,
861 const int high_bit,
862 const int low_bit )
863{
864 int dst_hob; // high order bit in destination_p to be moved to.
865 int lod; // low order digit containing data in source_p.
866 int hod; // high order digit containing data in source_p.
867 int right_shift; // index of bit within lod of the low order bit to moved.
868
869 dst_hob = high_bit-low_bit;
870 lod = SC_DIGIT_INDEX(low_bit);
871 hod = SC_DIGIT_INDEX(high_bit);
872 right_shift = SC_BIT_INDEX(low_bit);
873
874 // The extraction is on an sc_digit boundary, just move the digits.
875
876 if ( 0 == right_shift ) {
877 const sc_digit* src_p = &source_p[lod];
878 sc_digit* dst_p = destination_p;
879 for ( int digit_i = lod; digit_i <= hod; ++digit_i ) {
880 *dst_p++ = *src_p++;
881 }
882 }
883
884 // The extraction is within a single sc_digit, we just need to shift down.
885
886 else if ( hod == lod ) {
887 *destination_p = source_p[lod] >> right_shift;
888 }
889
890 // The extraction is not on an sc_digit boundary, we need to do shifting.
891
892 else {
893 sc_digit* dst_p = destination_p;
894 const int left_shift = BITS_PER_DIGIT - right_shift;
895 const sc_digit* src_p = &source_p[lod];
896 sc_digit carry = *src_p++ >> right_shift;
897
898 for ( int digit_i = lod+1; digit_i <= hod; ++digit_i ) {
899 sc_digit value = *src_p++;
900 *dst_p++ = (value << left_shift) | carry;
901 carry = (value >> right_shift);
902 }
903 const int dst_hod = SC_DIGIT_INDEX(dst_hob);
904 if ( dst_p == &destination_p[dst_hod] ) {
905 *dst_p = carry;
906 }
907 }
908
909 // Trim the upper sc_digit:
910
911 destination_p[SC_DIGIT_INDEX(dst_hob)] &= SC_BIT_MASK1(dst_hob);
912}
913
914// +----------------------------------------------------------------------------
915// |"vector_fill"
916// |
917// | This inline function fills the supplied vector of digits with the
918// | supplied value.
919// |
920// | Arguments:
921// | fill = value to be assigned.
922// | to_hod = index of the high order 'to' digit.
923// | to_p = vector of digits to be copied.
924// +----------------------------------------------------------------------------
925inline
926void
928 const int to_hod,
929 sc_digit* to_p )
930{
931 for ( int digit_i = 0; digit_i <= to_hod; ++digit_i ) {
932 to_p[digit_i] = fill;
933 }
934}
935
936// +----------------------------------------------------------------------------
937// |"vector_fill_bits"
938// |
939// | This inline function sets a range of bits to a value.
940// |
941// | Arguments:
942// | fill = value to set the bits to, either -1 or 0.
943// | target_p = vector to set bits in.
944// | high_bit = high order bit to be set.
945// | low_bit = low order bit to be set.
946// +----------------------------------------------------------------------------
947inline
948void
950 sc_digit* target_p,
951 const int high_bit,
952 const int low_bit )
953{
954 const int hob = SC_BIT_INDEX(high_bit);
955 const int hod = SC_DIGIT_INDEX(high_bit);
956 const int lob = SC_BIT_INDEX(low_bit);
957 const int lod = SC_DIGIT_INDEX(low_bit);
958
959 // Fill is all within a single digit:
960
961 if ( hod == lod ) {
962 const sc_digit mask = SC_BIT_MASK1(hob-lob) << lob;
963 target_p[lod] = ( target_p[lod] & ~mask ) | ( fill & mask );
964 }
965
966 // Fill is across digits perform it in three steps:
967 // (a) low order digit.
968 // (b) whole intermediate digits
969 // (c) high order digit
970
971 else {
972 const sc_digit low_mask = SC_BIT_MASK1(lob);
973 target_p[lod] = (target_p[lod] & low_mask ) | (fill & low_mask);
974 for ( int digit_i = lod+1; digit_i < hod; ++digit_i ) {
975 target_p[digit_i] = fill;
976 }
977 const sc_digit high_mask = SC_BIT_MASK1(hob);
978 target_p[hod] = (target_p[lod] & ~high_mask ) | (fill & high_mask);
979 }
980}
981
982// +----------------------------------------------------------------------------
983// |"vector_ones_complement"
984// |
985// | This inline function performs a ones complement on the value in the
986// | supplied vector.
987// |
988// | Arguments:
989// | target_hod = index of the high order 'target_p' digit.
990// | target_p = vector of digits to be complemented.
991// +----------------------------------------------------------------------------
992inline
993void
994vector_ones_complement( const int target_hod,
995 sc_digit* target_p )
996{
997 for ( int digit_i = 0; digit_i <= target_hod; ++digit_i ) {
998 target_p[digit_i] = ~target_p[digit_i];
999 }
1000}
1001
1002// +----------------------------------------------------------------------------
1003// |"vector_ones_complement"
1004// |
1005// | This inline function performs a ones complement on the value of the
1006// | supplied vector, placing it in the supplied destination vector.
1007// |
1008// | Arguments:
1009// | source_hod = index of the high order 'source_p' digit.
1010// | source_p = vector of digits to be complemented.
1011// | target_p = vector of digits to receive the complement.
1012// +----------------------------------------------------------------------------
1013inline
1014void
1015vector_ones_complement( const int source_hod,
1016 const sc_digit* source_p,
1017 sc_digit* target_p )
1018{
1019 for ( int digit_i = 0; digit_i <= source_hod; ++digit_i ) {
1020 *target_p++ = ~*source_p++;
1021 }
1022}
1023
1024// +----------------------------------------------------------------------------
1025// |"vector_reverse_bits"
1026// |
1027// | This function reverses the bits in the supplied bit range.
1028// |
1029// | Arguments:
1030// | target_p = vector the bits are to be reversed in.
1031// | high_i = bit index of high order bit that is be reversed.
1032// | low_i = bit index of low order bit that is be reversed.
1033// +----------------------------------------------------------------------------
1034inline
1035void
1037 int high_i,
1038 int low_i )
1039{
1040 for ( ; high_i > low_i; --high_i, ++low_i ) {
1041 const int hod = SC_DIGIT_INDEX(high_i);
1042 const int hom = 1 << SC_BIT_INDEX(high_i);
1043 const int lod = SC_DIGIT_INDEX(low_i);
1044 const int lom = 1 << SC_BIT_INDEX(low_i);
1045
1046 if ( hom & target_p[hod] ) {
1047 if ( !( lom & target_p[lod] ) ) {
1048 target_p[hod] &= ~hom;
1049 target_p[lod] |= lom;
1050 }
1051 }
1052 else if ( lom & target_p[lod] ) {
1053 target_p[hod] |= hom;
1054 target_p[lod] &= ~lom;
1055 }
1056 }
1057}
1058
1059
1060// +----------------------------------------------------------------------------
1061// |"vector_insert_bits"
1062// |
1063// | This inline function inserts the supplied value in the specified bit
1064// | range. It is assumed the target value has enough digits to accommodate
1065// | the range, and that the source data is large enough to provide data
1066// | for each bit in the range.
1067// | Arguments:
1068// | from_digits_n = number of digits in from_p.
1069// | from_p -> value to be inserted.
1070// | to_p -> vector the bits are to be inserted in.
1071// | high_bit_i = high order bit of the insertion.
1072// | low_bit_i = low order bit of the insertion.
1073// +----------------------------------------------------------------------------
1074inline
1075void
1076vector_insert_bits( const int from_digits_n,
1077 const sc_digit* from_p,
1078 sc_digit* to_p,
1079 const int high_bit_i,
1080 const int low_bit_i )
1081{
1082 const int debug=0; // set to non-zero to debug.
1083 int from_hod; // digit index of high order bit in the from_p.
1084 bool reverse; // true -> reverse the bits in the insertion.
1085 int to_hob; // bit index of high order bit in the insertion.
1086 int to_hod; // digit index of high order bit in the insertion.
1087 int to_lob; // bit index of lower order bit in the insertion.
1088 int to_lod; // digit index of low order bit in the insertion.
1089
1090 // Configure for big endian bit ordering:
1091
1092 if ( high_bit_i >= low_bit_i ) {
1093 reverse = false;
1094 to_lob = SC_BIT_INDEX(low_bit_i);
1095 to_lod = SC_DIGIT_INDEX(low_bit_i);
1096 to_hob = SC_BIT_INDEX(high_bit_i);
1097 to_hod = SC_DIGIT_INDEX(high_bit_i);
1098 }
1099
1100 // Configure for little endian bit ordering:
1101
1102 else {
1103 reverse = true;
1104 to_lob = SC_BIT_INDEX(high_bit_i);
1105 to_lod = SC_DIGIT_INDEX(high_bit_i);
1106 to_hob = SC_BIT_INDEX(low_bit_i);
1107 to_hod = SC_DIGIT_INDEX(low_bit_i);
1108 }
1109
1110 from_hod = from_digits_n - 1;
1111
1112 if ( debug ) {
1113 std::cout << "vector_insert_bits(" << from_hod << ", from_p, to_p, "
1114 << high_bit_i << ", " << low_bit_i << "):" << std::endl;
1115 std::cout << " to_lob = " << to_lob << std::endl;
1116 std::cout << " to_lod = " << to_lod << std::endl;
1117 std::cout << " to_hob = " << to_hob << std::endl;
1118 std::cout << " to_hod = " << to_hod << std::endl;
1119 }
1120
1121 // ALL THE BITS ARE IN A SINGLE sc_digit:
1122 //
1123 // We are guaranteed that the low order digit of from_p has valid data
1124 // through all its bits even if its the only digit because of sign
1125 // extension.
1126
1127 if ( to_hod == to_lod ) {
1128 sc_digit mask = SC_BIT_MASK1(to_hob-to_lob);
1129 to_p[to_lod] = ( to_p[to_lod] & ~(mask << to_lob) ) |
1130 ( ( *from_p & mask ) << to_lob) ;
1131
1132 }
1133
1134 // BITS ARE ACROSS MULTIPLE sc_digit VALUES:
1135
1136 else {
1137
1138 // We need to take into account that the source of the bits could be
1139 // smaller than the range to be filled. So we have the total amount
1140 // to be filled, full_hod, and the amount we can fill from the
1141 // source, src_hod.
1142
1143 const int full_hod = to_hod - to_lod;
1144 const int src_hod = full_hod > from_hod ? from_hod : full_hod;
1145 if ( debug ) {
1146 std::cout << " full_hod = " << full_hod << std::endl;
1147 std::cout << " src_hod = " << src_hod << std::endl;
1148 }
1149
1150
1151 // Low order bit is on an sc_digit boundary: no shifting is necessary,
1152 // just a mask on the high order digit.
1153
1154 if ( 0 == to_lob ) {
1155 int digit_i;
1156 sc_digit to_hob_mask = SC_BIT_MASK1(to_hob);
1157 sc_digit* dst_p = &to_p[to_lod];
1158 const sc_digit* src_p = from_p;
1159
1160 // Insert the bits below the high order digit, pad with a sign
1161 // extension if necessary.
1162
1163 if ( full_hod > src_hod ) {
1164 for ( digit_i = 0; digit_i <= src_hod; ++digit_i ) {
1165 *dst_p++ = *src_p++;
1166 }
1167 const sc_digit fill = 0 > (int)from_p[from_hod] ? -1 : 0;
1168 for ( ; digit_i < full_hod; ++digit_i ) {
1169 *dst_p++ = fill;
1170 }
1171 *dst_p = ( *dst_p & ~to_hob_mask ) | ( fill & to_hob_mask );
1172 }
1173 else {
1174 for ( digit_i = 0; digit_i < src_hod; ++digit_i ) {
1175 *dst_p++ = *src_p++;
1176 }
1177 *dst_p = ( *dst_p & ~to_hob_mask ) | ( *src_p & to_hob_mask );
1178 }
1179 }
1180
1181 // Low order bit is not on an sc_digit boundary: we will need to shift
1182 // pairs of digits.
1183
1184 else {
1185 int digit_i;
1186 sc_digit* dst_p = &to_p[to_lod];
1187 sc_digit to_hob_mask = SC_BIT_MASK1(to_hob);
1188 int left_shift = to_lob;
1189 sc_digit low_mask = SC_BIT_MASK(to_lob);
1190 int right_shift = BITS_PER_DIGIT - left_shift;
1191 const sc_digit* src_p = from_p;
1192
1193 sc_digit low_value = *dst_p & low_mask;
1194 if ( full_hod > src_hod ) {
1195 for ( digit_i = 0; digit_i <= src_hod; ++digit_i ) {
1196 sc_digit high_value = *src_p++;
1197 *dst_p++ = (high_value << left_shift) | low_value;
1198 low_value = high_value >> right_shift;
1199 }
1200 const sc_digit fill = 0 > (int)from_p[from_hod] ? -1 : 0;
1201 for ( ; digit_i < full_hod; ++digit_i ) {
1202 sc_digit high_value = fill;
1203 *dst_p++ = (high_value << left_shift) | low_value;
1204 low_value = high_value >> right_shift;
1205 }
1206 sc_digit highest_value = (fill << left_shift) | low_value;
1207 // *dst_p = (*dst_p & ~to_hob_mask) | (low_value & to_hob_mask);
1208 *dst_p = (*dst_p & ~to_hob_mask) | (highest_value & to_hob_mask);
1209 }
1210 else {
1211 for ( digit_i = 0; digit_i < src_hod; ++digit_i ) {
1212 sc_digit high_value = *src_p++;
1213 *dst_p++ = (high_value << left_shift) | low_value;
1214 low_value = high_value >> right_shift;
1215 }
1216 sc_digit highest_value = *src_p++;
1217 highest_value = highest_value << left_shift | low_value;
1218 *dst_p = (*dst_p & ~to_hob_mask) | (highest_value & to_hob_mask);
1219 }
1220 }
1221 }
1222
1223 // REVERSE THE BIT ORDER IF NECESSARY:
1224
1225 if ( reverse ) {
1226 vector_reverse_bits( to_p, high_bit_i, low_bit_i );
1227 }
1228}
1229
1230// +================================================================================================
1231// |"vector_mac"
1232// |
1233// | This class implements a multiply accumulator.
1234// |
1235// | (1) Each product is the multiplication of two 32-bit numbers.
1236// | (2) Each product is accumulated in a pair of 64-bit numbers, m_low_bits and m_high_bits.
1237// | (3) m_low_bits contains the addition of the low order 32 bits of each product.
1238// | (4) m_high_bits contains the addition of the high order 32 bits of each product.
1239// | (5) After a series of calls to add_product():
1240// | (a) m_low_bits will be a 64-bit value consisting of additions of the lower order 32 bits
1241// | of each product calculated. Its low order 32 bits are the current "digit" for the
1242// | additions, its high order 32 bits are the carry from those additions.
1243// | (b) Similarly m_high_bits will be a 64-bit value consisting of the additions of the high
1244// | order 32 bits of each product calculated by add_product. Its two 32-bit halves
1245// | are 'next digit' value and carry.
1246// |
1247// | m_high_order_bits m_low_order_bits
1248// | +-------------+-------------+ +-------------+-------------+
1249// | | next carry | next digit | |current carry|current digit|
1250// | +-------------+-------------+ +-------------+-------------+
1251// |
1252// | (6) The shift down operation yields the current digit and adjusts for the next digit:
1253// | (a) Returns the lower order 32 bits of m_low_bits, 'digit'.
1254// | (b) Calculates the current value of the next digit and carry by adding the high order
1255// | 32 bits(carry) of m_low_bits to m_high_bits.
1256// | (c) Sets m_low_bits to low order 32 bits of m_high_bits (this is the new 'digit'
1257// | value, awaiting additional low order adds.)
1258// | (d) sets m_high_bits to the upper 32 bits of m_high_bits, (this is the accumulated
1259// | high carry awaiting the addition of high-order adds.)
1260// |
1261// | X = (m_low_order >> 32) + m_high_order_bits
1262// |
1263// | m_high_order_bits m_low_order_bits
1264// | +-------------+-------------+ +-------------+-------------+
1265// | | 0 | high 32 of X| | 0 | low 32 of X |
1266// | +-------------+-------------+ +-------------+-------------+
1267// |
1268// +================================================================================================
1270{
1271 protected:
1272 int64 m_high_bits; // high bits of product.
1273 uint64 m_low_bits; // low bits of product.
1274
1275 public:
1277
1278 inline void add_product( int left, int right )
1279 {
1280 int64 product = (int64)left * (int64)right;
1281 m_low_bits += (unsigned int)product;
1282 m_high_bits += (product >> BITS_PER_DIGIT);
1283 }
1284
1285 inline void add_product( unsigned int left, int right )
1286 {
1287 int64 product = (uint64)left * (int64)right;
1288 m_low_bits += (unsigned int)product;
1289 m_high_bits += (product >> BITS_PER_DIGIT);
1290 }
1291
1292 inline void add_product( int left, unsigned int right )
1293 {
1294 int64 product = (int64)left * (uint64)right;
1295 m_low_bits += (unsigned int)product;
1296 m_high_bits += (product >> BITS_PER_DIGIT);
1297 }
1298
1299 inline void add_product( unsigned int left, unsigned int right )
1300 {
1301 uint64 product = (uint64)left * (uint64)right;
1302 m_low_bits += (unsigned int)product;
1303 m_high_bits += (product >> BITS_PER_DIGIT);
1304 }
1305
1306 void dump()
1307 {
1308 std::cout << " m_high_bits " << m_high_bits << " [0x" << std::hex
1309 << m_high_bits << "]" << std::endl;
1310 std::cout << " m_low_bits " << m_low_bits << " [0x" << std::hex
1311 << m_low_bits << "]" << std::endl;
1312 }
1313
1315
1317 {
1318 sc_digit result = (sc_digit)m_low_bits;
1322 return result;
1323 }
1324};
1325
1326// +----------------------------------------------------------------------------
1327// |"vector_multiply"
1328// |
1329// | This inline function will multiply two vectors of sc_digits representing
1330// | signed numbers. Some sign extension is left to the caller.
1331// |
1332// | Notes:
1333// | (1) We use standard long multiplication to generate the result, using
1334// |
1335// | Given two numbers, A and B:
1336// |
1337// | A: aS a5 a4 a3 a2 a1
1338// | B: bS b3 b2 b1
1339// |
1340// | Let BPD represent the number of bits per digit.
1341// |
1342// | The high-order digit variables for this example:
1343// | * shorter_hod is 4
1344// | * longer_hod is 6
1345// |
1346// | Long multiplication consists of calculating R from A and B:
1347// |
1348// | R: rS r6 r5 r4 r3 r2 r1
1349// |
1350// | The raw terms are:
1351// |
1352// | raw1 = a1 * b1
1353// | raw2 = (raw1 >> BPD) + a2 * b1 + a1 * b2
1354// | raw3 = (raw2 >> BPD) + a3 * b1 + a2 * b2 + a1 * b3
1355// | raw4 = (raw3 >> BPD) + a4 * b1 + a3 * b2 + a2 * b3 + a1 * bS
1356// | raw5 = (raw4 >> BPD) + a5 * b1 + a4 * b2 + a3 * b3 + a2 * bS
1357// | raw6 = (raw5 >> BPD) + aS * b1 + a5 * b2 + a4 * b3 + a3 * bS
1358// | raw7 = (raw6 >> BPD) + aS * b2 + a5 * b3 + a4 * bS
1359// | raw8 = (raw7 >> BPD) + aS * b3 + a5 * bS
1360// | raw9 = (raw8 >> BPD) + aS * bS
1361// | rawS = (raw9 >> BPD)
1362// |
1363// | The resultant digits are:
1364// | r1 = raw1 % BPD
1365// | r2 = raw2 % BPD
1366// | r3 = raw3 % BPD
1367// | r4 = raw4 % BPD
1368// | r5 = raw5 % BPD
1369// | r6 = raw6 % BPD
1370// | r7 = raw7 % BPD
1371// | r8 = raw8 % BPD
1372// | r9 = raw9 % BPD
1373// | rS = rawS % BPD
1374// |
1375// | (2) It is assumed that result_hod >= longer_hod+shorter_hod.
1376// |
1377// | Arguments:
1378// | left_hod = number of sc_digits in the left operand.
1379// | left_p -> vector of sc_digits representing the left operand.
1380// | right_hod = number of sc_digits in the right operand.
1381// | right_p -> vector of sc_digits representing the right operand.
1382// | result_hod = number of sc_digits in the result.
1383// | result_p -> vector of sc_digits representing the result.
1384// +----------------------------------------------------------------------------
1385inline
1386void
1387vector_multiply( int left_hod,
1388 const sc_digit* left_p,
1389 int right_hod,
1390 const sc_digit* right_p,
1391 int result_hod,
1392 sc_digit* result_p)
1393{
1394 int longer_hod;
1395 const sc_digit* longer_p;
1396 vector_mac mac;
1397 int result_i;
1398 int shorter_hod;
1399 const sc_digit* shorter_p;
1400
1401 // Trim leading zeros and all ones sc_digits to speed up the operation, and use the
1402 // shorter result operand is as the multiplier
1403
1404 if ( true ) {
1405 left_hod = vector_find_significant_hod( left_hod, left_p );
1406 right_hod = vector_find_significant_hod( right_hod, right_p );
1407 }
1408 if ( left_hod >= right_hod ) {
1409 longer_hod = left_hod;
1410 longer_p = left_p;
1411 shorter_hod = right_hod;
1412 shorter_p = right_p;
1413 }
1414 else {
1415 longer_hod = right_hod;
1416 longer_p = right_p;
1417 shorter_hod = left_hod;
1418 shorter_p = left_p;
1419 }
1420
1421
1422 // Set the low order digits in the result that are the product of unsigned digits from both
1423 // operands. For the example in note (1) this is:
1424 // raw1 = a1 * b1
1425 // r1 = raw1 % BPD
1426 // raw2 = a2 * b1 + a1 * b2 + (raw1 >> BPD)
1427 // r2 = raw2 % BPD
1428 // raw3 = a3 * b1 + a2 * b2 + a1 * b3 + (raw2 >> BPD)
1429 // r3 = raw3 % BPD
1430
1431 for (result_i=0; result_i < shorter_hod; ++result_i ) {
1432 for (int other_i=0; other_i <= result_i; ++other_i ) {
1433 mac.add_product( longer_p[result_i-other_i], shorter_p[other_i]);
1434 }
1435 result_p[result_i] = mac.shift_down();
1436 }
1437
1438 // Set the next higher order digits that are the result of unsigned
1439 // digits in the longer operand times all the digits in the shorter
1440 // operand. For example 1 at this point the mac contains raw3 shifted,
1441 // and the digits set will be:
1442 // raw4 = (raw3 >> BPD) + a4 * b1 + a3 * b2 + a2 * b3 + a1 * bS
1443 // r4 = raw4 % BPD
1444 // raw5 = (raw4 >> BPD) + a5 * b1 + a4 * b2 + a3 * b3 + a2 * bS
1445 // r5 = raw5 % BPD
1446 // raw6 = (raw5 >> BPD) + aS * b1 + a5 * b2 + a4 * b3 + a3 * bS
1447 // r6 = raw6 % BPD
1448 // raw7 = (raw6 >> BPD) + aS * b2 + a5 * b3 + a4 * bS
1449 // r7 = raw7 % BPD
1450 // raw8 = (raw7 >> BPD) + aS * b3 + a5 * bS
1451 // r8 = raw8 % BPD
1452
1453 for ( result_i = shorter_hod; result_i < longer_hod; ++result_i ) {
1454 mac.add_product( longer_p[result_i-shorter_hod],
1455 (int)shorter_p[shorter_hod] );
1456 for(int other_i=0; other_i < shorter_hod; ++other_i ) {
1457 mac.add_product( longer_p[result_i-other_i], shorter_p[other_i] );
1458 }
1459 result_p[result_i] = mac.shift_down();
1460 }
1461
1462 // Set the digits in the result that are the product of all the
1463 // longer operand digits times all the digits in the shorter operand.
1464 // In example 1 at this point the mac contains raw8 shifted and the
1465 // digit to be set will be r9:
1466 // raw9 = (raw8 >> BPD) + aS * bS
1467 // r9 = raw9 % BPD
1468
1469 for ( result_i=longer_hod; result_i < longer_hod+shorter_hod;
1470 ++result_i ) {
1471 mac.add_product( longer_p[result_i-shorter_hod],
1472 (int)shorter_p[shorter_hod] );
1473 for ( int other_i=result_i-(longer_hod-1); other_i < shorter_hod;
1474 other_i++ ) {
1475 mac.add_product( longer_p[result_i-other_i],
1476 shorter_p[other_i] );
1477 }
1478 mac.add_product( (int)longer_p[longer_hod],
1479 shorter_p[result_i-longer_hod] );
1480 result_p[result_i] = mac.shift_down();
1481 }
1482 mac.add_product((int)longer_p[longer_hod], (int)shorter_p[shorter_hod]);
1483 result_p[longer_hod+shorter_hod] = mac.shift_down();
1484
1485 // Set the next higher order digit to the signed product of the
1486 // operand's high order digits:
1487 //
1488 // If there are further digits in the result fill the first with the
1489 // remaining accumulation. Then fill any remaining digits based on the
1490 // on the sign of the accumulation.
1491 // rawS = (raw9 >> BPD)
1492 // rS = rawS % BPD
1493
1494 if ( (result_hod+1) >= longer_hod+shorter_hod+1) {
1495 if ( (result_hod) >= longer_hod+shorter_hod+1 ) {
1496 result_p[longer_hod+shorter_hod+1] = mac.low_bits(); // mac.shift_down();
1497 sc_digit fill = 0 > (int)result_p[longer_hod+shorter_hod+1] ? -1:0;
1498 for ( result_i = longer_hod+shorter_hod+2; result_i <= result_hod;
1499 ++result_i ) {
1500 result_p[result_i] = fill;
1501 }
1502 }
1503 }
1504}
1505
1506// +----------------------------------------------------------------------------
1507// |"vector_or"
1508// |
1509// | This function ors two signed sc_digit vectors. The second vector must be
1510// | shorter, or the same length, as the longer one.
1511// |
1512// | Template arguments:
1513// | SL - true if longer operand is signed.
1514// | SS - true if shorter operand is signed.
1515// | Arguments:
1516// | longer_hod = index of high order digit in 'longer_p' and 'result_p'.
1517// | longer_p = digits in the longer operand.
1518// | shorter_hod = index of high order digit in 'shorter_p'
1519// | shorter_p = digits in the shorter operand
1520// | result_p = digits to be filled in in the result, this is the same
1521// | number of digits as the longer operand.
1522// +----------------------------------------------------------------------------
1523template<bool SL, bool SS>
1524inline
1525void
1526vector_or( const int longer_hod,
1527 const sc_digit* longer_p,
1528 const int shorter_hod,
1529 const sc_digit* shorter_p,
1530 sc_digit* result_p )
1531{
1532 if ( 0 == longer_hod ) {
1533 *result_p = *longer_p | *shorter_p;
1534 return;
1535 }
1536
1537 int digit_i;
1538
1539 // And the two operands to the length of the shorter operand:
1540
1541 for ( digit_i = 0; digit_i <= shorter_hod; ++digit_i ) {
1542 *result_p++ = *longer_p++ | shorter_p[digit_i];
1543 }
1544
1545 // If the shorter operand is negative fill out the remaining entries
1546 // with ones, otherwise with the longer operand.
1547
1548 if ( longer_hod > shorter_hod ) {
1549 if ( SS && 0 > (int)shorter_p[shorter_hod] ) {
1550 for ( ; digit_i <= longer_hod; ++digit_i ) {
1551 *result_p++ = (sc_digit)-1;
1552 }
1553 }
1554 else {
1555 for ( ; digit_i <= longer_hod; ++digit_i ) {
1556 *result_p++ = *longer_p++;
1557 }
1558 }
1559 }
1560}
1561
1562// +----------------------------------------------------------------------------
1563// |"vector_or_reduce"
1564// |
1565// | This function overload performs an "or reduction" on the supplied vector,
1566// | returning the result.
1567// |
1568// | Arguments:
1569// | bits_n = number of bits in the vector that are valid.
1570// | target_p = digits containing the bits.
1571// | Result:
1572// | true if any bit is on in the vector, false if not.
1573// +----------------------------------------------------------------------------
1574inline
1575bool
1576vector_or_reduce( const int bits_n,
1577 const sc_digit* target_p )
1578{
1579 const int hod = SC_DIGIT_INDEX(bits_n-1);
1580
1581 // First check the whole sc_digits:
1582
1583 for ( int digit_i = 0; digit_i < hod; ++digit_i ) {
1584 if ( target_p[digit_i] != (sc_digit)0 ) {
1585 return true;
1586 }
1587 }
1588
1589 // Check the high order digit:
1590 const sc_digit mask =
1591 ~( (std::numeric_limits<sc_digit>::max()-1) << SC_BIT_INDEX(bits_n-1) );
1592 if ( ( target_p[hod] & mask ) != 0 ) {
1593 return true;
1594 }
1595 return false;
1596}
1597
1598// +----------------------------------------------------------------------------
1599// |"vector_or_reduce"
1600// |
1601// | This function overload performs an "or reduction" on the requested range
1602// | of bits in the supplied vector, returning the result.
1603// |
1604// | Arguments:
1605// | target_p = digits containing the bits.
1606// | left_i = left-most bit in the range to be checked.
1607// | right_i = right-most bit in the range to be checked.
1608// | Result:
1609// | true if any bit is on in the vector, false if not.
1610// +----------------------------------------------------------------------------
1611inline
1612bool
1614 const int left_i,
1615 const int right_i )
1616{
1617 const int left_hod = SC_DIGIT_INDEX(left_i);
1618 const int right_hod = SC_DIGIT_INDEX(right_i);
1619
1620 // All the bits are in a single sc_digit:
1621
1622 if ( left_hod == right_hod ) {
1623 const sc_digit mask =
1624 ~( (std::numeric_limits<sc_digit>::max()-1) << (left_i-right_i) );
1625 return ( ( target_p[right_hod] & mask ) != 0 ) ? true : false;
1626 }
1627
1628 const int right_index = SC_BIT_INDEX(right_i);
1629
1630 // The low order bit is not on an sc_digit boundary, check the low
1631 // order digit, then the whole sc_digits above it.
1632
1633 if ( right_index ) {
1634 const sc_digit mask =
1635 (std::numeric_limits<sc_digit>::max() << (right_index-1) );
1636 if ( ( target_p[right_hod] & mask ) != (sc_digit)0 ) {
1637 return true;
1638 }
1639 for ( int digit_i = right_hod+1; digit_i < left_hod; ++digit_i ) {
1640 if ( target_p[digit_i] != (sc_digit)0 ) {
1641 return true;
1642 }
1643 }
1644 }
1645
1646 // The lower order bit is on an sc_digit boundary, check the whole
1647 // sc_digits below the high order digit.
1648
1649 else {
1650 for ( int digit_i = right_hod; digit_i < left_hod; ++digit_i ) {
1651 if ( target_p[digit_i] != (sc_digit)0 ) {
1652 return true;
1653 }
1654 }
1655 }
1656
1657 // Check the high order sc_digit:
1658
1659 const sc_digit mask =
1660 ~( (std::numeric_limits<sc_digit>::max()-1) << SC_BIT_INDEX(left_i) );
1661 if ( ( target_p[left_hod] & mask ) != 0 ) {
1662 return true;
1663 }
1664 return false;
1665}
1666
1667// +----------------------------------------------------------------------------
1668// |"vector_shift_left"
1669// |
1670// | This function overload shifts the supplied vector left by the supplied
1671// | number of bits placing them at the appropriate offset in the supplied
1672// | target vector. The low order bits will be zeroed. The source will be
1673// | sign extended if extra bits are required for the target.
1674// |
1675// | Arguments:
1676// | from_digits_n = number of digits in 'from_p'
1677// | from_p -> digits of source.
1678// | to_digits_n = number of highest digits in 'to_p'
1679// | to_p -> digits in the target.
1680// | shift_n = number of bits to shift.
1681// +----------------------------------------------------------------------------
1682inline
1683void
1684vector_shift_left( const int from_digits_n,
1685 const sc_digit* from_p,
1686 const int to_digits_n,
1687 sc_digit* to_p,
1688 const int shift_n )
1689{
1690 // If the shift is not positive we are done:
1691
1692 if ( shift_n < 0 ) {
1693 return;
1694 }
1695
1696 int carry_shift_n; // amount to shift a carry down by when composing a to_p digit.
1697 int from_hod; // index of high order digit in 'from_p'.
1698 int from_i; // digit in from_p now accessing.
1699 int from_shift_n; // amount to shift a from_p digit down by when composing a to_p digit.
1700 sc_digit fill; // high order fill value, either zero or all ones.
1701 int to_hod; // index of high order digit in 'to_p'.
1702 int to_i; // digit in to_p now accessing.
1703 int to_start_hod; // first digit in to_p to receive a from_p digit.
1704 int to_end_hod; // last digit in to_p to recieve a from_p digit.
1705
1706 from_hod = from_digits_n-1;
1707 from_shift_n = SC_BIT_INDEX(shift_n);
1708 carry_shift_n = 32-from_shift_n;
1709 to_hod = to_digits_n-1;
1710 to_start_hod = VEC_MIN( SC_DIGIT_INDEX(shift_n), to_hod );
1711 to_end_hod = VEC_MIN( to_hod, to_start_hod+from_hod );
1712 fill = 0 > (int)from_p[from_hod] ? ~0u : 0;
1713
1714 if ( false ) {
1715 std::cout << "from_hod = " << std::dec << from_hod << std::endl;
1716 std::cout << "to_hod = " << to_hod << std::endl;
1717 std::cout << "shift_n = " << shift_n << std::endl;
1718 std::cout << "carry_shift_n = " << carry_shift_n << std::endl;
1719 std::cout << "from_shift_n = " << from_shift_n << std::endl;
1720 std::cout << "to_start_hod = " << to_start_hod << std::endl;
1721 std::cout << "to_end_hod = " << to_end_hod << std::endl;
1722 std::cout << "fill = " << std::hex << fill << std::dec << std::endl;
1723 }
1724
1725 // Zero any whole low order words below our transfer point:
1726
1727 for ( to_i = 0; to_i < to_start_hod; ++to_i ) {
1728 to_p[to_i] = 0;
1729 }
1730
1731 // If the shift is larger than the our target we are done:
1732
1733 if ( to_i > to_hod ) {
1734 std::cerr << "vector_shift_left: shift larger than target, word " << to_i << " > "
1735 << to_hod << std::endl;
1736 return;
1737 }
1738
1739 // Shift point is on an sc_digit boundary.
1740
1741 if ( 0 == from_shift_n ) {
1742 for ( from_i=0; to_i <= to_end_hod; ++from_i, ++to_i ) {
1743 to_p[to_i] = from_p[from_i];
1744 }
1745 if ( to_i <= to_hod ) {
1746 fill = 0 > (int)from_p[from_hod] ? -1 : 0;
1747 for ( ; to_i <= to_hod; ++to_i ) {
1748 to_p[to_i] = fill;
1749 }
1750 }
1751 }
1752
1753 // The messy case we need to shift within a digit:
1754
1755 else {
1756 from_i = 0;
1757 sc_digit carry = 0;
1758 for ( ; to_i <= to_end_hod; ++from_i, ++to_i ) {
1759 sc_digit from_digit = from_p[from_i];
1760 to_p[to_i] = (from_digit << from_shift_n) | carry;
1761 carry = from_digit >> carry_shift_n;
1762 }
1763 if ( to_i <= to_hod ) { to_p[to_i] = (fill << from_shift_n) | carry; }
1764 for ( to_i = to_i+1; to_i <= to_hod; ++to_i ) {
1765 to_p[to_i] = fill;
1766 }
1767 }
1768}
1769
1770// +----------------------------------------------------------------------------
1771// |"vector_shift_left"
1772// |
1773// | This function shifts left the supplied vector by the supplied number of
1774// | bits.
1775// | This function shifts left the supplied vector by the supplied number of
1776// | bits. Because the order of the digits in the array have the low order bits
1777// | at index 0 and the high order bits at index N, the actual shifting is to
1778// | the right from lower index to higher index.
1779// |
1780// |
1781// | Arguments:
1782// | target_n = number of digits in 'target_p'
1783// | target_p -> digits in the target.
1784// | shift_n = number of bits to shift.
1785// +----------------------------------------------------------------------------
1786inline
1787void
1788vector_shift_left( const int target_n,
1789 sc_digit* target_p,
1790 const int shift_n )
1791{
1792 if (shift_n <= 0) {
1793 if (shift_n < 0) {
1794 std::cerr << "vector_shift_left: negative shift encountered " << shift_n << std::endl;
1795 sc_assert(false);
1796 }
1797 return;
1798 }
1799 int shift_remaining = shift_n;
1800
1801 // Shift left whole digits if shift_n is large enough.
1802
1803 if (shift_n >= (int) BITS_PER_DIGIT) {
1804
1805 int digits_n;
1806
1807 if ( SC_BIT_INDEX(shift_n) == 0 ) {
1808 digits_n = SC_DIGIT_INDEX(shift_n);
1809 shift_remaining = 0;
1810 }
1811 else {
1812 digits_n = ( (shift_n+BITS_PER_DIGIT-1)/BITS_PER_DIGIT ) - 1;
1813 shift_remaining -= digits_n * BITS_PER_DIGIT;
1814 }
1815
1816 // Shift left for digits_n digits.
1817
1818 if (digits_n) {
1819
1820 for (int digit_i = target_n - 1; digit_i >= digits_n; --digit_i)
1821 target_p[digit_i] = target_p[digit_i - digits_n];
1822
1823 const int clear_n = VEC_MIN( digits_n, target_n );
1824 for (int digit_i = 0; digit_i < clear_n; ++digit_i ) {
1825 target_p[digit_i] = 0;
1826 }
1827
1828 }
1829
1830 if (shift_remaining == 0)
1831 return;
1832
1833 }
1834
1835 // Shift left if shift_remaining < BITS_PER_DIGIT.
1836
1837 sc_digit* target_iter_p = target_p;
1838 sc_digit* target_end_p = target_iter_p + target_n;
1839
1840 int carry_shift = BITS_PER_DIGIT - shift_remaining;
1841 sc_digit mask = (sc_digit)one_and_ones(carry_shift);
1842
1843 sc_carry carry = 0;
1844
1845 while (target_iter_p < target_end_p) {
1846 sc_digit target_value = (*target_iter_p);
1847 (*target_iter_p++) = (sc_digit)(((target_value & mask) << shift_remaining) | carry);
1848 carry = target_value >> carry_shift;
1849 }
1850}
1851
1852// +----------------------------------------------------------------------------
1853// |"vector_shift_right"
1854// |
1855// | This function shifts right the supplied vector by the supplied number of
1856// | bits. Because the order of the digits in the array have the low order bits
1857// | at index 0 and the high order bits at index N, the actual shifting is to
1858// | the left from higher index to lower index.
1859// |
1860// | Arguments:
1861// | target_n = number of digits in 'target_p'
1862// | target_p -> digits in the target.
1863// | bits_n = number of bits to shift.
1864// | fill = fill for high order bits.
1865// +----------------------------------------------------------------------------
1866inline
1867void
1868vector_shift_right( const int target_n,
1869 sc_digit* target_p,
1870 int bits_n,
1871 const sc_digit fill )
1872{
1873 if (bits_n <= 0) {
1874 return;
1875 }
1876
1877 // PERFORM INTER-DIGIT SHIFTING:
1878 //
1879 // (1) If the low order digit (target_p[0]) does not contain the intra-digit shift point move
1880 // all the digits in target_p down so that it does contain the shift point.
1881 // (2) In the degenerate case, where the shift is a multiple of the number of bits in a
1882 // digit we are done.
1883
1884 if (bits_n >= (int) BITS_PER_DIGIT) {
1885
1886 int nd;
1887
1888 if (SC_BIT_INDEX(bits_n) == 0) {
1889 nd = SC_DIGIT_INDEX(bits_n);
1890 bits_n = 0;
1891 }
1892 else {
1893 nd = DIV_CEIL(bits_n) - 1;
1894 bits_n -= nd * BITS_PER_DIGIT;
1895 }
1896
1897 if (nd) {
1898
1899 // Shift right for nd digits.
1900
1901 for (int digit_i = 0; digit_i < (target_n - nd); ++digit_i) {
1902 target_p[digit_i] = target_p[digit_i + nd];
1903 }
1904
1905 for (int digit_i = target_n - VEC_MIN( nd, target_n );
1906 digit_i < target_n; ++digit_i) {
1907 target_p[digit_i] = fill;
1908 }
1909
1910 if (bits_n == 0)
1911 return;
1912 }
1913 }
1914
1915 // PERFORM INTRA-DIGIT SHIFTING:
1916 //
1917 // (1) At this point target_p[0] contains the shift point. Roll through the digits in target_p
1918 // from top to bottom performing shifts smaller than BITS_PER_DIGIT bits.
1919 // (2) Each digit will contain it high order bits as low order bits, and the next digit's
1920 // low order bits as its high order bits.
1921
1922 int other_shift_n = BITS_PER_DIGIT - bits_n;
1923 sc_digit carry = fill << other_shift_n;
1924 sc_digit *target_iter_p = (target_p + target_n );
1925
1926 while (target_p < target_iter_p) {
1927 sc_digit target_val = *--target_iter_p;
1928 (*target_iter_p) = (target_val >> bits_n) | carry;
1929 carry = target_val << other_shift_n;
1930 }
1931}
1932
1933// +----------------------------------------------------------------------------
1934// |"vector_subtract_longer"
1935// |
1936// | This function subtracts the longer of two operands from the shorter. The
1937// | algorithm is basically that from grade school:
1938// |
1939// | BS B3 B2 B1
1940// | - AS A5 A4 A3 A2 A1
1941// | --------------------
1942// | R7 R6 R5 R4 R3 R2 R1
1943// |
1944// | Let BPD represent the number of bits per digit.
1945// |
1946// | Raw1 = B1 - A1
1947// | Raw2 = (Raw1 >> BPD) - A2 + B2
1948// | Raw3 = (Raw2 >> BPD) - A3 + B3
1949// | Raw4 = (Raw3 >> BPD) - A4 + (signed)BS
1950// | Raw5 = (Raw4 >> BPD) - A5
1951// | Raw6 = (Raw5 >> BPD) - (signed)AS
1952// | Raw7 = (Raw6 >> BPD)
1953// |
1954// | R1 = Raw1 % BPD
1955// | R2 = Raw2 % BPD
1956// | R3 = Raw3 % BPD
1957// | R4 = Raw4 % BPD
1958// | R5 = Raw5 % BPD
1959// | R6 = Raw6 % BPD
1960// | R7 = Raw7 % BPD
1961// |
1962// | Arguments:
1963// | longer_hod = index of high order digit in 'longer_p'
1964// | longer_p = digits in the longer operand.
1965// | shorter_hod = index of high order digit in 'shorter_p'
1966// | shorter_p = digits in the shorter operand
1967// | result_hod = index of high order digit in 'result_p'
1968// | result_p = digits to be filled in in the result.
1969// +----------------------------------------------------------------------------
1970inline
1971void
1972vector_subtract_longer( const int longer_hod,
1973 const sc_digit* longer_p,
1974 const int shorter_hod,
1975 const sc_digit* shorter_p,
1976 const int result_hod,
1977 sc_digit* result_p )
1978{
1979 if ( result_hod == 0 ) {
1980 *result_p = *shorter_p - *longer_p;
1981 return;
1982 }
1983
1984 int64 borrow = 0;
1985 int digit_i;
1986
1987 // Subtract the low-order unsigned parts of the operands:
1988
1989 for ( digit_i = 0; digit_i < shorter_hod; ++digit_i ) {
1990 borrow += *shorter_p++;
1991 borrow -= *longer_p++;
1992 *result_p++ = (sc_digit)borrow;
1993 borrow >>= BITS_PER_DIGIT;
1994 }
1995
1996 // The operands are the same length: process the high order digits as
1997 // signed values:
1998
1999 if ( longer_hod == shorter_hod ) {
2000 borrow += (int64)(int)*shorter_p++;
2001 borrow -= (int64)(int)*longer_p++;
2002 *result_p++ = (sc_digit)borrow;
2003 borrow >>= BITS_PER_DIGIT;
2004 }
2005
2006 // The operands are different lengths:
2007 // (a) Add the shorter operand's high order digit as a signed value.
2008 // (b) Subtract the longer operand's values below its high order digit as
2009 // unsigned.
2010 // (c) Subtract the high order digit as signed.
2011
2012 else {
2013 borrow += (int64)(int)*shorter_p++;
2014 borrow -= *longer_p++;
2015 *result_p++ = (sc_digit)borrow;
2016 borrow >>= BITS_PER_DIGIT;
2017
2018 for ( ++digit_i; digit_i < longer_hod; ++digit_i ) {
2019 borrow -= *longer_p++;
2020 *result_p++ = (sc_digit)borrow;
2021 borrow >>= BITS_PER_DIGIT;
2022 }
2023
2024 borrow -= (int64)(int)*longer_p++;
2025 *result_p++ = (sc_digit)borrow;
2026 borrow >>= BITS_PER_DIGIT;
2027 }
2028
2029 // If there is an additional high order digit in the result assign it the
2030 // borrow value:
2031
2032 if ( result_hod > longer_hod ) {
2033 *result_p = (sc_digit)borrow;
2034 }
2035}
2036
2037// +----------------------------------------------------------------------------
2038// |"vector_subtract_shorter"
2039// |
2040// | This function subtracts the shorter of two operands from the longer. The
2041// | algorithm is basically that from grade school:
2042// |
2043// | AS A5 A4 A3 A2 A1
2044// | - BS B3 B2 B1
2045// | --------------------
2046// | R7 R6 R5 R4 R3 R2 R1
2047// |
2048// | Let BPD represent the number of bits per digit.
2049// |
2050// | Raw1 = A1 - B1
2051// | Raw2 = (Raw1 >> BPD) + A2 - B2
2052// | Raw3 = (Raw2 >> BPD) + A3 - B3
2053// | Raw4 = (Raw3 >> BPD) + A4 - (signed)BS
2054// | Raw5 = (Raw4 >> BPD) + A5
2055// | Raw6 = (Raw5 >> BPD) + (signed)AS
2056// | Raw7 = (Raw6 >> BPD)
2057// |
2058// | R1 = Raw1 % BPD
2059// | R2 = Raw2 % BPD
2060// | R3 = Raw3 % BPD
2061// | R4 = Raw4 % BPD
2062// | R5 = Raw5 % BPD
2063// | R6 = Raw6 % BPD
2064// | R7 = Raw7 % BPD
2065// |
2066// |
2067// | Arguments:
2068// | longer_hod = index of high order digit in 'longer_p'
2069// | longer_p = digits in the longer operand.
2070// | shorter_hod = index of high order digit in 'shorter_p'
2071// | shorter_p = digits in the shorter operand
2072// | result_hod = index of high order digit in 'result_p'
2073// | result_p = digits to be filled in in the result.
2074// +----------------------------------------------------------------------------
2075inline
2076void
2077vector_subtract_shorter( const int longer_hod,
2078 const sc_digit* longer_p,
2079 const int shorter_hod,
2080 const sc_digit* shorter_p,
2081 const int result_hod,
2082 sc_digit* result_p )
2083{
2084 if ( result_hod == 0 ) {
2085 *result_p = *longer_p - *shorter_p;
2086 return;
2087 }
2088
2089 int64 borrow = 0;
2090 int digit_i;
2091
2092 // Subtract the low-order unsigned parts of the operands:
2093
2094 for ( digit_i = 0; digit_i < shorter_hod; ++digit_i ) {
2095 borrow -= *shorter_p++;
2096 borrow += *longer_p++;
2097 *result_p++ = (sc_digit)borrow;
2098 borrow >>= BITS_PER_DIGIT;
2099 }
2100
2101 // The operands are the same length: treat the high order digits as
2102 // signed values:
2103
2104 if ( longer_hod == shorter_hod ) {
2105 borrow -= (int64)(int)*shorter_p++;
2106 borrow += (int64)(int)*longer_p++;
2107 *result_p++ = (sc_digit)borrow;
2108 borrow >>= BITS_PER_DIGIT;
2109 }
2110
2111 // The operands are different lengths:
2112 // (a) Subtract the shorter operand's high order digit as a signed value.
2113 // (b) Add the longer operand's values below its high order digit as
2114 // unsigned.
2115 // (c) Add the high order digit as signed.
2116
2117 else {
2118 borrow -= (int64)(int)*shorter_p++;
2119 borrow += *longer_p++;
2120 *result_p++ = (sc_digit)borrow;
2121 borrow >>= BITS_PER_DIGIT;
2122
2123 for ( ++digit_i; digit_i < longer_hod; ++digit_i ) {
2124 borrow += *longer_p++;
2125 *result_p++ = (sc_digit)borrow;
2126 borrow >>= BITS_PER_DIGIT;
2127 }
2128
2129 borrow += (int64)(int)*longer_p++;
2130 *result_p++ = (sc_digit)borrow;
2131 borrow >>= BITS_PER_DIGIT;
2132 }
2133
2134 // If there is an additional high order digit in the result assign it the
2135 // borrow value:
2136
2137 if ( result_hod > longer_hod ) {
2138 *result_p = (sc_digit)borrow;
2139 }
2140}
2141
2142// +----------------------------------------------------------------------------
2143// |"vector_twos_complement"
2144// |
2145// | This inline function complements the value in the supplied vector.
2146// |
2147// | Arguments:
2148// | target_n = number of digits in 'target_p'
2149// | target_p = vector of digits to be complemented.
2150// +----------------------------------------------------------------------------
2151inline
2152void
2153vector_twos_complement( const int target_n,
2154 sc_digit* target_p )
2155{
2156 long long carry = 0;
2157 for ( int digit_i = 0; digit_i < target_n; ++digit_i ) {
2158 carry -= target_p[digit_i];
2159 target_p[digit_i] = (sc_digit)carry;
2160 carry >>= BITS_PER_DIGIT;
2161 }
2162}
2163
2164// +----------------------------------------------------------------------------
2165// |"vector_twos_complement"
2166// |
2167// | This inline function complements the value of the supplied vector,
2168// | placing it in the supplied destination vector.
2169// |
2170// | Arguments:
2171// | source_hod = index of the high order 'source_p' digit.
2172// | source_p = vector of digits to be complemented.
2173// | target_p = vector of digits to receive the complement.
2174// +----------------------------------------------------------------------------
2175inline
2176void
2177vector_twos_complement( const int source_hod,
2178 const sc_digit* source_p,
2179 sc_digit* target_p )
2180{
2181 long long carry = 0;
2182 for ( int digit_i = 0; digit_i <= source_hod; ++digit_i ) {
2183 carry -= *source_p++;
2184 *target_p++ = (sc_digit)carry;
2185 carry >>= BITS_PER_DIGIT;
2186 }
2187}
2188
2189// +----------------------------------------------------------------------------
2190// |"vector_divide"
2191// |
2192// | This function implements division of the supplied numerator by the
2193// | supplied denominator. Both are vectors of sc_digit (radix32) values, but
2194// | are accessed at times as if they were vectors of radix16 values. Either
2195// | the quotient of the division, or the remainder, or both may be returned
2196// | depending upon the caller's arguments.
2197// |
2198// |
2199// | Notes:
2200// | (1) The division is always performed using non-negative values.
2201// | Conversion of negative values, as well as conversion to negative
2202// | results is performed to allow the use of non-negative values.
2203// |
2204// | (2) The quotient and remainder values are treated as radix-16 values
2205// | at times.
2206// |
2207// | (3) The algorithm is basically "long division" from grade school:
2208// |
2209// | X Y Z
2210// | +--------------------
2211// | abc | A B C D E
2212// | - X*a X*b X*c
2213// | -----------
2214// | r1A r1B r1C D
2215// | - Y*a Y*b Y*c
2216// | ---------------
2217// | r2B r2C r2D E
2218// | - Z*a Z*b Z*c
2219// | ---------------
2220// | r3C r3D r3E
2221// |
2222// | The algorithm consists of:
2223// | (a) Creating a remainder vector that initially is the numerator
2224// | for the division operation.
2225// | (b) Calculating a potential quotient radix16 digit using 64-bit
2226// | native division hardware. So divide the high-order 4 radix16
2227// | digits of the current remainder by the the high-order 3
2228// | radix16 digits of the denominator.
2229// | (c) The potential quotient digit is then multiplied by the
2230// | denominator and that value is subtracted from the remainder.
2231// | (d) If the result is negative then the quotient digit was too
2232// | large by one, so adjust the remainder by adding the
2233// | denominator, and decrement the quotient digit by one.
2234// | (e) Store the quotient digit into the quotient vector.
2235// | (f) Steps (b) through (e) are repeated until all the digits in
2236// | the quotient have been calculated.
2237// |
2238// | Template arguments:
2239// | SN = true if numerator is signed, false if not.
2240// | SD = true if denominator is signed, false if not.
2241// | Arguments:
2242// | numerator_n = number of digits in numerator_p.
2243// | numerator_p = vector of digits containing the numerator.
2244// | denominator_n = number of digits in denominator_p.
2245// | denominator_p = vector of digits containing the denominator.
2246// | quotient_n = number of digits in 'quotient_p' or zero.
2247// | quotient_p = vector of digits to receive quotient of the divide.
2248// | remainder_n = number of digits in remainder_p or zero if no remainder is desired.
2249// | remainder_p = vector of digits to receive remainder of the divide, (NULL - none desired).
2250// | Result:
2251// | true if the operation was successful, false if a divide by zero was
2252// | detected.
2253// +----------------------------------------------------------------------------
2254template<bool SN, bool SD>
2255inline
2256bool
2257vector_divide( const int numerator_n,
2258 const sc_digit* numerator_p,
2259 const int denominator_n,
2260 const sc_digit* denominator_p,
2261 const int quotient_n,
2262 sc_digit* quotient_p,
2263 const int remainder_n,
2264 sc_digit* remainder_p )
2265{
2266 // Initialize the quotient to zero and the remainder to the numerator,
2267 // if their return is requested:
2268 if ( 0 != quotient_n ) {
2269 for( int quot_i=0; quot_i < quotient_n; ++quot_i) {
2270 quotient_p[quot_i] = 0;
2271 }
2272 }
2273 if ( 0 != remainder_n ) {
2274 for( int remain_i=0; remain_i < remainder_n; ++remain_i) {
2275 remainder_p[remain_i] = numerator_p[remain_i];
2276 }
2277 }
2278
2279 // CONVERT THE OPERANDS TO NON-NEGATIVE VALUES:
2280 //
2281 // If a complement is necessary use a temporary buffer, otherwise use
2282 // the vector that was passed in from the caller.
2283
2284 bool negative_numerator = false;
2285 bool negative = false;
2286
2287 if ( SN && ( 0 > (int)numerator_p[numerator_n-1] ) ) {
2288 sc_digit* numerator_complement_p = sc_temporary_digits.allocate(numerator_n+1);
2289 vector_twos_complement( numerator_n-1, numerator_p,
2290 numerator_complement_p );
2291 numerator_p = numerator_complement_p;
2292 negative = true;
2293 negative_numerator = true;
2294 }
2295
2296 if ( SD && (0 > (int)denominator_p[denominator_n-1]) ) {
2297 sc_digit* denominator_complement_p = sc_temporary_digits.allocate(denominator_n+1);
2298 vector_twos_complement( denominator_n-1, denominator_p,
2299 denominator_complement_p );
2300 denominator_p = denominator_complement_p;
2301 negative = !negative;
2302 }
2303
2304 // SET UP FOR THE CALCULATION:
2305 //
2306 // (1) Trim the numerator and denominator to highest order non-zero value.
2307 // (2) Create the denominator value to use in guesses at the quotient
2308 // digit.
2309 // (3) Initialize the remainder array to the value of the numerator.
2310
2311 int denom_32_hod; // high order radix32 denominator digit.
2312 int numer_32_hod; // most significant radix32 numerator digit.
2313
2314 denom_32_hod = vector_skip_leading_zeros( denominator_n-1, denominator_p );
2315 bool denom_16_hod_odd = (bool)(denominator_p[denom_32_hod] >> 16);
2316 int denom_16_hod= 2*denom_32_hod + denom_16_hod_odd;
2317
2318 for ( numer_32_hod = numerator_n-1;
2319 numer_32_hod > 0 && !numerator_p[numer_32_hod];
2320 --numer_32_hod ) {
2321 continue;
2322 }
2323 int numer_16_hod = 2*numer_32_hod + (bool)(numerator_p[numer_32_hod]>>16);
2324
2325 // If the denom is zero we are in trouble...
2326
2327 if ( !denom_32_hod && !denominator_p[0]) {
2328 return false;
2329 }
2330
2331 // If the numerator was smaller than the denominator return a zero
2332 // quotient and the numerator as the remainder:
2333
2334 if ( numer_16_hod < denom_16_hod ) {
2335 return true;
2336 }
2337
2338
2339 // We will estimate the quotient digits by dividing the the first four
2340 // radix-16 digits of the current "remainder" value by the first three
2341 // radix-16 digits of the denominator, so assemble those three denominator
2342 // digits as a value we can use over and over. Use zeros for any missing
2343 // low order digits so that we have three properly aligned radix-16 digits.
2344
2345 uint64 denom_value = (uint64)denominator_p[denom_32_hod] <<
2346 (16 << (int)!denom_16_hod_odd);
2347 if ( denom_32_hod ) {
2348 denom_value |= denominator_p[denom_32_hod-1] >>
2349 (denom_16_hod_odd ? 16 : 0);
2350 }
2351
2352 // Copy the numerator into the remainder to start off the division process
2353 // and zero the extra high order radix32 digit of the remainder:
2354
2355 sc_digit* remain_work_p = sc_temporary_digits.allocate( numerator_n+10 );
2356
2357 for (int remain_32_i = 0; remain_32_i <= numer_32_hod; ++remain_32_i ) {
2358 remain_work_p[remain_32_i] = numerator_p[remain_32_i];
2359 }
2360 remain_work_p[numer_32_hod+1] = 0;
2361
2362 // CALCULATE THE QUOTIENT AND REMAINDER:
2363 //
2364 // This is done with a pair of nested loops that are applied to the radix-16
2365 // representation of the numerator and denominator:
2366 // (a) The outer loop runs downwards from the most significant radix-16
2367 // digit in the numerator through the most significant radix-16 in
2368 // the denominator, effectively the values that will contribute to an
2369 // integer result (the quotient). It calculates the next guess at
2370 // a quotient radix16 digit.
2371 // (b) The inner loop runs upwards from the least significant radix32
2372 // digit in the denominator up through the most significant radix32
2373 // digit in the denominator. It subtracts the product of the
2374 // quotient digit times the denominator from the remainder.
2375
2376 for ( int quot_16_i = numer_16_hod - denom_16_hod; quot_16_i >= 0;
2377 --quot_16_i ) {
2378
2379 // Calculate some values we need to navigate our vectors:
2380
2381 bool quot_16_odd = quot_16_i & 1;
2382 int quot_32_i = quot_16_i >> 1;
2383 int remain_16_i = quot_16_i + denom_16_hod;
2384 int remain_32_i = remain_16_i >> 1;
2385 bool remain_16_odd = remain_16_i & 1;
2386
2387 // Make an educated guess at the next quotient digit by dividing
2388 // the current high-order 4 radix-16 digits of the remainder by the
2389 // 3 high-order radix-16 digits of the denominator. Potentially the
2390 // result can be larger than the radix, so adjust it down by 1
2391 // if necessary.
2392
2393 sc_digit low_order_bits = remain_32_i > 0 ? remain_work_p[remain_32_i-1] :
2394 (sc_digit) 0;
2395 uint64 numer_value;
2396 if ( remain_16_odd ) {
2397 numer_value = ( (uint64)remain_work_p[remain_32_i+1] << 48 ) |
2398 ( (uint64)remain_work_p[remain_32_i] << 16 ) |
2399 ( low_order_bits >> 16 );
2400 }
2401 else {
2402 numer_value = ( (uint64)remain_work_p[remain_32_i] << 32 ) |
2403 low_order_bits;
2404 }
2405
2406 sc_digit quot_guess = (sc_digit)(numer_value / denom_value);
2407 if ( quot_guess >> 16 ) {
2408 quot_guess--;
2409 }
2410
2411 // Subtract off the product of the current guess at the quotient
2412 // times the denominator vector from the remainder working vector.
2413
2414 int64 carry = 0;
2415 int64 product;
2416 uint64 quot_term = quot_guess << (quot_16_odd ? 16:0);
2417
2418 for ( int denom_32_i = 0; denom_32_i <= denom_32_hod; ++denom_32_i) {
2419 carry += remain_work_p[quot_32_i + denom_32_i];
2420 bool carry_was_minus = carry < 0;
2421 product = denominator_p[denom_32_i] * quot_term;
2422 bool product_hob_one = (product < 0);
2423 carry -= product;
2424 remain_work_p[quot_32_i + denom_32_i] = (sc_digit)carry;
2425 bool carry_is_minus = carry < 0;
2426 carry >>= 32;
2427
2428 // Because we are subtracting two 64-bit numbers to generate the
2429 // remainder values an overflow is possible. If an overflow does
2430 // occur the upper bits of the carry value will not be correct
2431 // after it was shifted down by 32 bits. There are two cases
2432 // requiring correction:
2433 // (1) If the carry is non-negative, and either it was negative
2434 // before the addition of the quotient-denominator product,
2435 // or the high order bit of the quotient-denominator product
2436 // is one, an overflow occurred and the high order bits of
2437 // the carry should have become ones when it was shifted down
2438 // by 32 bits, so set those bits to one.
2439 // (2) If the carry is negative, and it was negative before
2440 // the addition of the quotient-denominator product and the
2441 // high order bit of the quotient-denominator product is one,
2442 // then the low order bit of the shifted carry has the wrong
2443 // sense, so flip it.
2444
2445 if ( !carry_is_minus && (product_hob_one || carry_was_minus ) ) {
2446 carry |= (std::numeric_limits<uint64_t>::max() << 32);
2447 }
2448 else if ( carry_is_minus && product_hob_one && carry_was_minus ) {
2449 carry ^= (1LL << 32);
2450 }
2451 }
2452
2453 // If there are an odd number of digits in either the quotient or
2454 // denominator there is an extra digit to be processed, so add the
2455 // current carry to the remainder for that digit.
2456
2457 if ( quot_16_odd || denom_16_hod_odd ) {
2458 carry += remain_work_p[quot_32_i + denom_32_hod + 1];
2459 remain_work_p[quot_32_i + denom_32_hod + 1] = (sc_digit)carry;
2460 }
2461
2462 // If the carry is negative we overshot by one in our approximation
2463 // of the quotient digit, so add back in the denominator once and
2464 // decrement the quotient guess by one:
2465
2466 if(carry < 0) {
2467 carry = 0;
2468 for(int restore_i = 0; restore_i <= denom_32_hod; ++restore_i) {
2469 carry += (int64)denominator_p[restore_i] <<
2470 (quot_16_odd ? 16:0);
2471 carry += remain_work_p[quot_32_i + restore_i];
2472 remain_work_p[quot_32_i + restore_i] = (sc_digit)carry;
2473 carry >>= BITS_PER_DIGIT;
2474 }
2475 if ( quot_16_odd | denom_16_hod_odd ) {
2476 remain_work_p[quot_32_i+denom_32_hod+1] += (sc_digit)carry;
2477 }
2478 quot_guess--;
2479 }
2480
2481 // Assign the next quotient digit, if we are returning it:
2482
2483 if( quotient_n && quot_32_i < quotient_n ) {
2484 if(quot_16_odd) {
2485 quotient_p[quot_32_i] = quot_guess << 16;
2486 }
2487 else {
2488 quotient_p[quot_32_i] |= quot_guess;
2489 }
2490 }
2491 }
2492
2493 // RETURN THE QUOTIENT AND REMAINDER IF REQUESTED:
2494 //
2495 // (1) If the result is negative complement the quotient.
2496 // (2) If the numerator was negative complement the remainder.
2497
2498 if ( (SN || SD) && negative && quotient_n ) {
2499 vector_twos_complement( quotient_n, quotient_p );
2500 }
2501
2502 if ( remainder_n) {
2503 int remain_n = VEC_MIN(remainder_n-1, numer_32_hod);
2504 for ( int remain_i = 0; remain_i <= remain_n; ++remain_i) {
2505 remainder_p[remain_i] = remain_work_p[remain_i];
2506 }
2507 for (int remain_i = remain_n+1; remain_i < remainder_n; ++remain_i) {
2508 remainder_p[remain_i] = 0;
2509 }
2510 if ( SN && negative_numerator ) {
2511 vector_twos_complement( remainder_n, remainder_p );
2512 }
2513 }
2514 return true;
2515}
2516
2517// +----------------------------------------------------------------------------
2518// |"vector_xor"
2519// |
2520// | This function xors two signed sc_digit vectors. The second vector must be
2521// | shorter, or the same length, as the longer one.
2522// |
2523// | Template arguments:
2524// | SL - true if longer operand is signed.
2525// | SS - true if shorter operand is signed.
2526// | Arguments:
2527// | longer_hod = index of high order digit in 'longer_p' and 'result_p'.
2528// | longer_p = digits in the longer operand.
2529// | shorter_hod = index of high order digit in 'shorter_p'
2530// | shorter_p = digits in the shorter operand
2531// | result_p = digits to be filled in in the result, this is the same
2532// | number of digits as the longer operand.
2533// +----------------------------------------------------------------------------
2534template<int SL, int SS>
2535inline
2536void
2537vector_xor( const int longer_hod,
2538 const sc_digit* longer_p,
2539 const int shorter_hod,
2540 const sc_digit* shorter_p,
2541 sc_digit* result_p )
2542{
2543 if ( 0 == longer_hod ) {
2544 *result_p = *longer_p ^ *shorter_p;
2545 return;
2546 }
2547
2548 int digit_i;
2549
2550 // Xor the two operands to the length of the shorter operand:
2551
2552 for ( digit_i = 0; digit_i <= shorter_hod; ++digit_i ) {
2553 *result_p++ = *longer_p++ ^ shorter_p[digit_i];
2554 }
2555
2556 // If the shorter operand is negative fill out the remaining entries
2557 // with by xoring, otherwise with the longer operand.
2558
2559 if ( longer_hod > shorter_hod ) {
2560 if ( SS && 0 > (int)shorter_p[shorter_hod] ) {
2561 for ( ; digit_i <= longer_hod; ++digit_i ) {
2562 *result_p++ = *longer_p++ ^ (sc_digit)-1; // could use ~
2563 }
2564 }
2565 else {
2566 for ( ; digit_i <= longer_hod; ++digit_i ) {
2567 *result_p++ = *longer_p++;
2568 }
2569 }
2570 }
2571}
2572
2573// +----------------------------------------------------------------------------
2574// |"vector_xor_reduce"
2575// |
2576// | This function overload performs an "xor reduction" on the supplied vector,
2577// | returning the result.
2578// |
2579// | Arguments:
2580// | bits_n = number of bits in the vector that are valid.
2581// | target_p = digits containing the bits.
2582// | Result:
2583// | true if an odd number of bits are on in the vector, false if not.
2584// +----------------------------------------------------------------------------
2585inline
2586bool
2587vector_xor_reduce( const int bits_n,
2588 const sc_digit* target_p )
2589{
2590 const unsigned char* byte_p = (const unsigned char*)target_p;
2591 int count = 0;
2592 const int hod = SC_DIGIT_INDEX(bits_n-1);
2593
2594 // First count the bits in the whole sc_digits:
2595
2596 for ( int byte_i = 0; byte_i < 4*hod; ++byte_i ) {
2597 count += byte_one_bits[ byte_p[byte_i] ];
2598 }
2599
2600 // Check the high order digit:
2601
2602 const sc_digit mask =
2603 ~((std::numeric_limits<sc_digit>::max()-1) << SC_BIT_INDEX(bits_n-1));
2604 const sc_digit high_order_bits = target_p[hod] & mask;
2605 byte_p = (const unsigned char*)&high_order_bits;
2606 count += byte_one_bits[ byte_p[0] ];
2607 count += byte_one_bits[ byte_p[1] ];
2608 count += byte_one_bits[ byte_p[2] ];
2609 count += byte_one_bits[ byte_p[3] ];
2610 return count & 1;
2611}
2612
2613// +----------------------------------------------------------------------------
2614// |"vector_xor_reduce"
2615// |
2616// | This function overload performs an "xor reduction" on the requested range
2617// | of bits in the supplied vector, returning the result.
2618// |
2619// | Arguments:
2620// | target_p = digits containing the bits.
2621// | left_i = left-most bit in the range to be checked.
2622// | right_i = right-most bit in the range to be checked.
2623// | Result:
2624// | true if an odd number of bits are on in the vector, false if not.
2625// +----------------------------------------------------------------------------
2626inline
2627bool
2629 const int left_i,
2630 const int right_i )
2631{
2632 const unsigned char* byte_p = (const unsigned char*)target_p;
2633 int count = 0;
2634 const int left_hod = SC_DIGIT_INDEX(left_i);
2635 const int right_hod = SC_DIGIT_INDEX(right_i);
2636
2637 // All the bits are in a single sc_digit:
2638
2639 if ( left_hod == right_hod ) {
2640 const sc_digit mask =
2641 ~((std::numeric_limits<sc_digit>::max()-1) << (left_i-right_i) );
2642 const sc_digit digit_bits = target_p[right_hod] & mask;
2643 byte_p = (const unsigned char*)&digit_bits;
2644 count += byte_one_bits[ byte_p[0] ];
2645 count += byte_one_bits[ byte_p[1] ];
2646 count += byte_one_bits[ byte_p[2] ];
2647 count += byte_one_bits[ byte_p[3] ];
2648 return count & 1;
2649 }
2650
2651 const int right_index = SC_BIT_INDEX(right_i);
2652
2653 // The low order bit is not on an sc_digit boundary, check the low
2654 // order digit, then the whole sc_digits above it.
2655
2656 if ( right_index ) {
2657 const sc_digit mask =
2658 ( std::numeric_limits<sc_digit>::max() << (right_index-1) );
2659 const sc_digit digit_bits = target_p[right_hod] & mask;
2660 byte_p = (const unsigned char*)&digit_bits;
2661 count += byte_one_bits[ byte_p[0] ];
2662 count += byte_one_bits[ byte_p[1] ];
2663 count += byte_one_bits[ byte_p[2] ];
2664 count += byte_one_bits[ byte_p[3] ];
2665 byte_p = (const unsigned char*)target_p;
2666 for ( int byte_i = 4*(right_hod+1); byte_i < 4*left_hod; ++byte_i ) {
2667 count += byte_one_bits[ byte_p[byte_i] ];
2668 }
2669 }
2670
2671 // The lower order bit is on an sc_digit boundary, check the whole
2672 // sc_digits below the high order digit.
2673
2674 else {
2675 byte_p = (const unsigned char*)target_p;
2676 for ( int byte_i = 0; byte_i < 4*left_hod; ++byte_i ) {
2677 count += byte_one_bits[ byte_p[byte_i] ];
2678 }
2679 }
2680
2681 // Check the high order sc_digit:
2682
2683 const sc_digit mask =
2684 ~( (std::numeric_limits<sc_digit>::max()-1) << SC_BIT_INDEX(left_i) );
2685
2686 const sc_digit high_order_bits = target_p[left_hod] & mask;
2687 byte_p = (const unsigned char*)&high_order_bits;
2688 count += byte_one_bits[ byte_p[0] ];
2689 count += byte_one_bits[ byte_p[1] ];
2690 count += byte_one_bits[ byte_p[2] ];
2691 count += byte_one_bits[ byte_p[3] ];
2692
2693 return count & 1;
2694}
2695
2696// +------------------------------------------------------------------------------------------------
2697// |"vector_zero"
2698// |
2699// | This function sets a specified range of digits in the supplied vector to zero.
2700// |
2701// | Arguments:
2702// | from_i = first digit to be zeroed.
2703// | to_i = first digit NOT to be zeroed.
2704// | target_p = digit vector containing the digits to be zeroed..
2705// +------------------------------------------------------------------------------------------------
2706inline
2707void
2708vector_zero( int from_i, int to_i, sc_digit* target_p )
2709{
2710 for ( int digit_i = from_i; digit_i < to_i; ++digit_i ) { target_p[digit_i] = 0; }
2711}
2712
2713#undef VEC_MIN
2714#undef VEC_MAX
2715
2716} //namespace sc_dt
2717
2718#endif // !defined(SC_VECTOR_UTILS_H)
#define SC_DIGIT_INDEX(BIT_INDEX)
Definition: sc_nbdefs.h:186
#define DIV_CEIL(x)
Definition: sc_nbdefs.h:212
#define SC_BIT_INDEX(BIT)
Definition: sc_nbdefs.h:185
#define SC_BIT_MASK1(BITS)
Definition: sc_nbdefs.h:196
#define SC_DIGIT_COUNT(BIT_WIDTH)
Definition: sc_nbdefs.h:188
#define SC_BIT_MASK(BITS)
Definition: sc_nbdefs.h:195
#define BITS_PER_DIGIT
Definition: sc_nbdefs.h:164
#define VEC_MAX(A, B)
#define VEC_MIN(A, B)
#define sc_assert(expr)
Definition: sc_report.h:248
int vector_compare(const int left_hod, const sc_digit *left_p, const int right_hod, const sc_digit *right_p)
void vector_fill(const sc_digit fill, const int to_hod, sc_digit *to_p)
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)
int vector_skip_leading_zeros(const int hod, const sc_digit *digits_p)
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)
void vector_fill_bits(sc_digit fill, sc_digit *target_p, const int high_bit, const int low_bit)
sc_digit_heap SC_API sc_temporary_digits
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)
bool vector_and_reduce(const int bits_n, const sc_digit *target_p)
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)
void vector_extract(const sc_digit *source_p, sc_digit *destination_p, const int high_bit, const int low_bit)
void vector_ones_complement(const int target_hod, sc_digit *target_p)
int vector_skip_leading_ones(const int hod, const sc_digit *digits_p)
void vector_zero(int from_i, int to_i, sc_digit *target_p)
void vector_copy(const int from_n, const sc_digit *from_p, const int to_n, sc_digit *to_p)
constexpr int byte_one_bits[256]
Definition: sc_nbdefs.h:265
sc_carry one_and_ones(int n)
Definition: sc_nbutils.h:107
void vector_twos_complement(const int target_n, sc_digit *target_p)
bool vector_xor_reduce(const int bits_n, const sc_digit *target_p)
bool vector_or_reduce(const int bits_n, const sc_digit *target_p)
sc_lv_base reverse(const sc_proxy< X > &x)
Definition: sc_lv_base.h:852
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)
bool vector_divide(const int numerator_n, const sc_digit *numerator_p, const int denominator_n, const sc_digit *denominator_p, const int quotient_n, sc_digit *quotient_p, const int remainder_n, sc_digit *remainder_p)
void vector_reverse_bits(sc_digit *target_p, int high_i, int low_i)
int vector_find_significant_hod(int hod, const sc_digit *digits)
unsigned int sc_digit
Definition: sc_nbdefs.h:161
void vector_insert_bits(const int from_digits_n, const sc_digit *from_p, sc_digit *to_p, const int high_bit_i, const int low_bit_i)
void vector_shift_left(const int from_digits_n, const sc_digit *from_p, const int to_digits_n, sc_digit *to_p, const int shift_n)
void vector_shift_right(const int target_n, sc_digit *target_p, int bits_n, const sc_digit fill)
uint64 sc_carry
Definition: sc_nbdefs.h:225
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)
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_core::sc_signal_in_if< T > & value(const T &val)
Definition: sc_stub.h:217
sc_digit * allocate(size_t digits_n)
Definition: sc_nbutils.h:288
sc_big_op_type< sub_bits, signed_result >::top_type sub_result
sc_big_op_type< WL, SL >::top_type left_op
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< WL, SL >::base_type left_base
sc_big_op_type< WR, SR >::base_type right_base
sc_big_op_type< add_bits, signed_result >::top_type add_result
sc_big_op_type< WR, SR >::top_type right_op
sc_big_op_type< mul_bits, signed_result >::top_type mul_result
sc_big_op_type< bit_bits, signed_result >::top_type bit_result
const sc_digit * get_digits() const
const sc_digit * get_digits() const
const sc_digit * get_digits() const
const sc_digit * get_digits() const
const sc_digit * get_digits() const
void add_product(unsigned int left, int right)
void add_product(unsigned int left, unsigned int right)
void add_product(int left, unsigned int right)
void add_product(int left, int right)