sc_nbutils.cc revision 13160:1e959d3afc64
1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22  sc_nbutils.cpp -- External and friend functions for both sc_signed and
23                    sc_unsigned classes.
24
25  Original Author: Ali Dasdan, Synopsys, Inc.
26
27 *****************************************************************************/
28
29/*****************************************************************************
30
31  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
32  changes you are making here.
33
34      Name, Affiliation, Date:
35  Description of Modification:
36
37 *****************************************************************************/
38
39
40// $Log: sc_nbutils.cpp,v $
41// Revision 1.4  2011/08/24 22:05:46  acg
42//  Torsten Maehne: initialization changes to remove warnings.
43//
44// Revision 1.3  2011/02/18 20:19:15  acg
45//  Andy Goodrich: updating Copyright notice.
46//
47// Revision 1.2  2007/11/04 21:26:40  acg
48//  Andy Goodrich: added a buffer to the allocation of the q array to address
49//  an issue with references outside the array by 1 byte detected by valgrind.
50//
51// Revision 1.1.1.1  2006/12/15 20:20:05  acg
52// SystemC 2.3
53//
54// Revision 1.3  2006/01/13 18:49:32  acg
55// Added $Log command so that CVS check in comments are reproduced in the
56// source.
57//
58
59#include <cctype>
60#include <cstdio>
61#include <cstring>
62#include <sstream>
63
64#include "systemc/ext/dt/int/sc_nbutils.hh"
65#include "systemc/ext/utils/functions.hh"
66
67namespace sc_dt
68{
69
70// only used within vec_from_str (non-standard, deprecated)
71static inline void
72is_valid_base(sc_numrep base)
73{
74    switch (base) {
75      case SC_NOBASE: case SC_BIN:
76      case SC_OCT: case SC_DEC:
77      case SC_HEX:
78        break;
79      case SC_BIN_US: case SC_BIN_SM:
80      case SC_OCT_US: case SC_OCT_SM:
81      case SC_HEX_US: case SC_HEX_SM:
82      case SC_CSD:
83        SC_REPORT_ERROR("not implemented",
84                        "is_valid_base( sc_numrep base ) : "
85                        "bases SC_CSD, or ending in _US and _SM are "
86                        "not supported");
87        break;
88      default:
89        std::stringstream msg;
90        msg << "is_valid_base( sc_numrep base ) : base = " << base <<
91               " is not valid";
92        SC_REPORT_ERROR("(E204) value is not valid", msg.str().c_str() );
93    }
94}
95
96// ----------------------------------------------------------------------------
97//  ENUM : sc_numrep
98//
99//  Enumeration of number representations for character string conversion.
100// ----------------------------------------------------------------------------
101
102const std::string
103to_string(sc_numrep numrep)
104{
105    switch (numrep) {
106#define CASE_ENUM2STR(Value) case Value: return #Value
107
108      CASE_ENUM2STR(SC_DEC);
109
110      CASE_ENUM2STR(SC_BIN);
111      CASE_ENUM2STR(SC_BIN_US);
112      CASE_ENUM2STR(SC_BIN_SM);
113
114      CASE_ENUM2STR(SC_OCT);
115      CASE_ENUM2STR(SC_OCT_US);
116      CASE_ENUM2STR(SC_OCT_SM);
117
118      CASE_ENUM2STR(SC_HEX);
119      CASE_ENUM2STR(SC_HEX_US);
120      CASE_ENUM2STR(SC_HEX_SM);
121
122      CASE_ENUM2STR(SC_CSD);
123
124#undef CASE_ENUM2STR
125
126      default:
127        return "unknown";
128    }
129}
130
131// ----------------------------------------------------------------------------
132//  SECTION: General utility functions.
133// ----------------------------------------------------------------------------
134
135// Return the number of characters to advance the source of c.  This
136// function implements one move of the FSM to parse the following
137// regular expressions. Error checking is done in the caller.
138
139small_type
140fsm_move(char c, small_type &b, small_type &s, small_type &state)
141{
142    // Possible regular expressions (REs):
143    // Let N = any digit depending on the base.
144    //    1. [0|1|..|9]N*
145    //    2. [+|-][0|1|..|9]N*
146    //    3. 0[b|B|d|D|o|O|x|X][0|1|..|F]N*
147    //    4. [+|-]?0[b|B|d|D|o|O|x|X][0|1|..|F]N*
148    //
149    // The finite state machine (FMS) to parse these regular expressions
150    // has 4 states, 0 to 3. 0 is the initial state and 3 is the final
151    // state.
152    //
153    // Default sign = SC_POS, default base = NB_DEFAULT_BASE.
154
155    switch (state) {
156      case 0: // The initial state.
157        switch (c) {
158          case '0': s = SC_POS; state = 1; return 0; // RE 1 or 3
159          case '+': s = SC_POS; state = 2; return 1; // RE 2
160          case '-': s = SC_NEG; state = 2; return 1; // RE 2
161          default:
162            s = SC_POS; b = NB_DEFAULT_BASE; state = 3; return 0; // RE 1
163        }
164        // break; //unreachable code
165      case 1: // 0...
166        switch (c) {
167          case 'x': case 'X': b = SC_HEX; state = 3; return 2; // RE 3 or 4
168          case 'd': case 'D': b = SC_DEC; state = 3; return 2; // RE 3 or 4
169          case 'o': case 'O': b = SC_OCT; state = 3; return 2; // RE 3 or 4
170          case 'b': case 'B': b = SC_BIN; state = 3; return 2; // RE 3 or 4
171          default: b = NB_DEFAULT_BASE; state = 3; return 0; // RE 1
172        }
173        // break; //unreachable code
174      case 2: // +... or -...
175        switch (c) {
176          case '0': state = 1; return 0; // RE 2 or 4
177          default: b = NB_DEFAULT_BASE; state = 3; return 0; // RE 2
178        }
179        // break; //unreachable code
180      case 3: // The final state.
181        break;
182      default:
183        // Any other state is not possible.
184        sc_assert((0 <= state) && (state <= 3));
185    } // switch
186    return 0;
187}
188
189
190// Get base b and sign s of the number in the char string v. Return a
191// pointer to the first char after the point where b and s are
192// determined or where the end of v is reached. The input string v has
193// to be null terminated.
194const char *
195get_base_and_sign(const char *v, small_type &b, small_type &s)
196{
197#ifdef DEBUG_SYSTEMC
198    sc_assert(v != NULL);
199#endif
200    const small_type STATE_START = 0;
201    const small_type STATE_FINISH = 3;
202
203    // Default sign = SC_POS, default base = 10.
204    s = SC_POS;
205    b = NB_DEFAULT_BASE;
206
207    small_type state = STATE_START;
208    small_type nskip = 0; // Skip that many chars.
209    const char *u = v;
210
211    while (*u) {
212        if (isspace(*u)) { // Skip white space.
213            ++u;
214        } else {
215            nskip += fsm_move(*u, b, s, state);
216            if (state == STATE_FINISH)
217              break;
218            else
219              ++u;
220        }
221    }
222
223    // Test to see if the above loop executed more than it should
224    // have. The max number of skipped chars is equal to the length of
225    // the longest format specifier, e.g., "-0x".
226    sc_assert(nskip <= 3);
227
228    v += nskip;
229
230    // Handles empty strings or strings without any digits after the
231    // base or base and sign specifier.
232    if (*v == '\0') {
233        static const char msg[] =
234            "get_base_and_sign( const char* v, small_type&, small_type& ) : "
235            "v = \"\" is not valid";
236        SC_REPORT_ERROR("conversion failed", msg);
237    }
238    return v;
239}
240
241//-----------------------------------------------------------------------------
242//"parse_binary_bits"
243//
244// This function parses the supplied string into the supplied vector as a
245// right justified bit value.
246//    src_p  -> character string representing the bits to be parsed.
247//    dst_n  =  number of words in data_p and ctrl_p.
248//    data_p -> words w/BITS_PER_DIGIT bits to receive the value's data bits.
249//    ctrl_p -> words w/BITS_PER_DIGIT bits to receive the value's control
250//              bits, or zero.
251// Result is true if value was non-zero.
252//-----------------------------------------------------------------------------
253void
254parse_binary_bits(const char *src_p, int dst_n,
255                  sc_digit *data_p, sc_digit *ctrl_p)
256{
257    int bit_i; // Number of bit now processing.
258    sc_digit ctrl; // Control word now assembling.
259    sc_digit data; // Data word now assembling.
260    int delta_n; // src_n - dst_n*BITS_PER_DIGIT.
261    int src_i; // Index in src_p now accessing (left to right).
262    int src_n; // Length of source that is left in bits.
263    int word_i; // Bit within word now accessing (left to right).
264
265    // MAKE SURE WE HAVE A STRING TO PARSE:
266    if (src_p == 0) {
267        SC_REPORT_ERROR("conversion failed",
268                        "character string is zero");
269        return;
270    }
271    if (*src_p == 0) {
272        SC_REPORT_ERROR("conversion failed",
273                        "character string is empty");
274        return;
275    }
276
277
278    // INDEX INTO THE SOURCE TO A DEPTH THAT WILL ACCOMODATE OUR SIZE:
279    //
280    // If the source is smaller than our value initialize our value to zero.
281
282    src_n = strlen(src_p);
283    delta_n = src_n - (dst_n*BITS_PER_DIGIT);
284    if (delta_n > 0) {
285        src_p = &src_p[delta_n];
286        src_n -= delta_n;
287    } else {
288        for (word_i = 0; word_i < dst_n; word_i++)
289            data_p[word_i] = 0;
290        if (ctrl_p)
291            for (word_i = 0; word_i < dst_n; word_i++)
292                ctrl_p[word_i] = 0;
293    }
294
295    // LOOP OVER THE SOURCE ASSEMBLING WORDS AND PLACING THEM IN OUR VALUE:
296    //
297    // We stride right to left through the source in BITS_PER_DIGIT chunks.
298    // Each of those chunks is processed from left to right a bit at a time.
299    // We process the high order word specially, since there are less bits.
300    src_n = src_n - BITS_PER_DIGIT;
301    for (word_i=0; word_i < dst_n; word_i++) {
302        src_i = src_n;
303
304        // PARTIAL LAST WORD TO ASSEMBLE:
305        if (src_i < 0) {
306            src_n += BITS_PER_DIGIT;
307            data = 0;
308            ctrl = 0;
309            for (src_i = 0; src_i < src_n; src_i++) {
310                ctrl = ctrl << 1;
311                data = data << 1;
312                switch (src_p[src_i]) {
313                  case 'X':
314                  case 'x': ctrl = ctrl | 1; data = data | 1; break;
315                  case '1': data = data | 1; break;
316                  case 'Z':
317                  case 'z': ctrl = ctrl | 1; break;
318                  case '0': break;
319                  default:
320                    {
321                        std::stringstream msg;
322                        msg << "character string '" << src_p <<
323                               "' is not valid";
324                        SC_REPORT_ERROR("conversion failed",
325                                        msg.str().c_str());
326                        return;
327                    }
328                    break;
329                }
330            }
331            if (ctrl_p)
332                ctrl_p[word_i] = ctrl;
333            data_p[word_i] = data;
334            break;
335        }
336
337        // FULL WORD TO BE ASSEMBLED:
338        ctrl = 0;
339        data = 0;
340        for (bit_i = 0; bit_i < BITS_PER_DIGIT; bit_i++) {
341            ctrl = ctrl << 1;
342            data = data << 1;
343            switch (src_p[src_i++]) {
344              case 'X':
345              case 'x': ctrl = ctrl | 1; data = data | 1; break;
346              case '1': data = data | 1; break;
347              case 'Z':
348              case 'z': ctrl = ctrl | 1; break;
349              case '0': break;
350              default:
351                {
352                    std::stringstream msg;
353                    msg << "character string '" << src_p <<
354                           "' is not valid";
355                    SC_REPORT_ERROR("conversion failed",
356                                    msg.str().c_str());
357                    return;
358                }
359                break;
360            }
361        }
362        if (ctrl_p)
363            ctrl_p[word_i] = ctrl;
364        data_p[word_i] = data;
365        src_n = src_n - BITS_PER_DIGIT;
366    }
367}
368
369
370//-----------------------------------------------------------------------------
371//"parse_hex_bits"
372//
373// This function parses the supplied string into the supplied vector as a
374// right justified bit value.
375//    src_p  -> character string representing the bits to be parsed.
376//    dst_n  =  number of words in data_p and ctrl_p.
377//    data_p -> words w/32 bits to receive the value's data bits.
378//    ctrl_p -> words w/32 bits to receive the value's control bits,
379//              or zero.
380// Result is true if value was non-zero.
381//-----------------------------------------------------------------------------
382void
383parse_hex_bits(const char *src_p, int dst_n,
384               sc_digit *data_p, sc_digit *ctrl_p)
385{
386    sc_digit ctrl; // Control word now assembling.
387    sc_digit data; // Data word now assembling.
388    int delta_n; // src_n - dst_n*BITS_PER_DIGIT.
389    int digit_i; // Number of digit now processing.
390    int src_i; // Index in src_p now accessing (left to right).
391    int src_n; // Length of source that is left in bits.
392    int word_i; // Bit within word now accessing (left to right).
393
394    // MAKE SURE WE HAVE A STRING TO PARSE:
395    if (src_p == 0) {
396        SC_REPORT_ERROR("conversion failed",
397                        "character string is zero");
398        return;
399    }
400    if (*src_p == 0) {
401        SC_REPORT_ERROR("conversion failed",
402                        "character string is empty");
403        return;
404    }
405
406    // INDEX INTO THE SOURCE TO A DEPTH THAT WILL ACCOMODATE OUR SIZE:
407    //
408    // If the source is smaller than our value initialize our value to zero.
409    src_n = strlen(src_p);
410    delta_n = src_n - (dst_n*8);
411    if (delta_n > 0) {
412        src_p = &src_p[delta_n];
413        src_n -= delta_n;
414    } else {
415        for (word_i = 0; word_i < dst_n; word_i++)
416            data_p[word_i] = 0;
417        if (ctrl_p)
418            for (word_i = 0; word_i < dst_n; word_i++)
419                ctrl_p[word_i] = 0;
420    }
421
422    // LOOP OVER THE SOURCE ASSEMBLING WORDS AND PLACING THEM IN OUR VALUE:
423    //
424    // We stride right to left through the source in BITS_PER_DIGIT chunks.
425    // Each of those chunks is processed from left to right a bit at a time.
426    // We process the high order word specially, since there are less bits.
427    src_n = src_n - 8;
428    for (word_i = 0; word_i < dst_n; word_i++) {
429        src_i = src_n;
430
431        // PARTIAL LAST WORD TO ASSEMBLE:
432        if (src_i < 0) {
433            src_n += 8;
434            data = 0;
435            ctrl = 0;
436            for (src_i = 0; src_i < src_n; src_i++) {
437                ctrl = ctrl << 4;
438                data = data << 4;
439                switch (src_p[src_i]) {
440                  case 'X':
441                  case 'x': ctrl = ctrl | 15; data = data | 15; break;
442                  case 'F':
443                  case 'f': data = data | 15; break;
444                  case 'E':
445                  case 'e': data = data | 14; break;
446                  case 'D':
447                  case 'd': data = data | 13; break;
448                  case 'C':
449                  case 'c': data = data | 12; break;
450                  case 'B':
451                  case 'b': data = data | 11; break;
452                  case 'A':
453                  case 'a': data = data | 10; break;
454                  case '9': data = data |  9; break;
455                  case '8': data = data |  8; break;
456                  case '7': data = data |  7; break;
457                  case '6': data = data |  6; break;
458                  case '5': data = data |  5; break;
459                  case '4': data = data |  4; break;
460                  case '3': data = data |  3; break;
461                  case '2': data = data |  2; break;
462                  case '1': data = data |  1; break;
463                  case '0': break;
464                  case 'Z':
465                  case 'z': ctrl = ctrl | 15; break;
466                  default:
467                    {
468                        std::stringstream msg;
469                        msg << "character string '" << src_p <<
470                               "' is not valid";
471                        SC_REPORT_ERROR("conversion failed",
472                                        msg.str().c_str());
473                        return;
474                    }
475                    break;
476                }
477            }
478            if (ctrl_p)
479                ctrl_p[word_i] = ctrl;
480            data_p[word_i] = data;
481            break;
482        }
483
484        // FULL WORD TO BE ASSEMBLED:
485        ctrl = 0;
486        data = 0;
487        for (digit_i = 0; digit_i < 8; digit_i++) {
488            ctrl = ctrl << 4;
489            data = data << 4;
490            switch (src_p[src_i++]) {
491              case 'X':
492              case 'x': ctrl = ctrl | 15; data = data | 15; break;
493              case 'F':
494              case 'f': data = data | 15; break;
495              case 'E':
496              case 'e': data = data | 14; break;
497              case 'D':
498              case 'd': data = data | 13; break;
499              case 'C':
500              case 'c': data = data | 12; break;
501              case 'B':
502              case 'b': data = data | 11; break;
503              case 'A':
504              case 'a': data = data | 10; break;
505              case '9': data = data |  9; break;
506              case '8': data = data |  8; break;
507              case '7': data = data |  7; break;
508              case '6': data = data |  6; break;
509              case '5': data = data |  5; break;
510              case '4': data = data |  4; break;
511              case '3': data = data |  3; break;
512              case '2': data = data |  2; break;
513              case '1': data = data |  1; break;
514              case '0': break;
515              case 'Z':
516              case 'z': ctrl = ctrl | 15; break;
517              default:
518                {
519                    std::stringstream msg;
520                    msg << "character string '" << src_p << "' is not valid";
521                    SC_REPORT_ERROR("conversion failed",
522                                    msg.str().c_str() );
523                    return;
524                }
525                break;
526            }
527        }
528        if (ctrl_p)
529            ctrl_p[word_i] = ctrl;
530        data_p[word_i] = data;
531        src_n = src_n - BITS_PER_DIGIT;
532    }
533}
534
535
536// ----------------------------------------------------------------------------
537//  SECTION: Utility functions involving unsigned vectors.
538// ----------------------------------------------------------------------------
539
540// Read u from a null terminated char string v. Note that operator>>
541// in sc_nbcommon.cpp is similar to this function.
542small_type
543vec_from_str(int unb, int und, sc_digit *u, const char *v, sc_numrep base)
544{
545
546#ifdef DEBUG_SYSTEMC
547    sc_assert((unb > 0) && (und > 0) && (u != NULL));
548    sc_assert(v != NULL);
549#endif
550    is_valid_base(base);
551
552    small_type b, s; // base and sign.
553
554    v = get_base_and_sign(v, b, s);
555
556    if (base != SC_NOBASE) {
557        if (b == NB_DEFAULT_BASE) {
558            b = base;
559        } else {
560            std::stringstream msg;
561            msg << "vec_from_str( int, int, sc_digit*, const char*, " <<
562                   "sc_numrep base ) : base = " << base <<
563                   " does not match the default base";
564            SC_REPORT_ERROR("conversion failed",
565                            msg.str().c_str());
566            return 0;
567        }
568    }
569
570    vec_zero(und, u);
571
572    char c;
573    for (; (c = *v); ++v) {
574        if (isalnum(c)) {
575            small_type val;  // Numeric value of a char.
576
577            if (isalpha(c)) // Hex digit.
578                val = toupper(c) - 'A' + 10;
579            else
580                val = c - '0';
581
582            if (val >= b) {
583                std::stringstream msg;
584                msg << "vec_from_str( int, int, sc_digit*, const char*, " <<
585                       "sc_numrep base ) : '" << *v << "' is not a valid " <<
586                       "digit in base " << b;
587                SC_REPORT_ERROR("conversion failed",
588                                msg.str().c_str());
589                return 0;
590            }
591
592            // digit = digit * b + val;
593            vec_mul_small_on(und, u, b);
594
595            if (val)
596                vec_add_small_on(und, u, val);
597        } else {
598            std::stringstream msg;
599            msg << "vec_from_str( int, int, sc_digit*, const char*, " <<
600                   "sc_numrep base ) : '" << *v << "' is not a valid " <<
601                   "digit in base " << b;
602            SC_REPORT_ERROR("conversion failed",
603                            msg.str().c_str());
604            return 0;
605        }
606    }
607
608    return convert_signed_SM_to_2C_to_SM(s, unb, und, u);
609}
610
611
612// All vec_ functions assume that the vector to hold the result,
613// called w, has sufficient length to hold the result. For efficiency
614// reasons, we do not test whether or not we are out of bounds.
615
616// Compute w = u + v, where w, u, and v are vectors.
617// - ulen >= vlen
618// - wlen >= sc_max(ulen, vlen) + 1
619void
620vec_add(int ulen, const sc_digit *u, int vlen, const sc_digit *v, sc_digit *w)
621{
622#ifdef DEBUG_SYSTEMC
623    sc_assert((ulen > 0) && (u != NULL));
624    sc_assert((vlen > 0) && (v != NULL));
625    sc_assert(w != NULL);
626    sc_assert(ulen >= vlen);
627#endif
628
629    const sc_digit *uend = (u + ulen);
630    const sc_digit *vend = (v + vlen);
631
632    sc_digit carry = 0; // Also used as sum to save space.
633
634    // Add along the shorter v.
635    while (v < vend) {
636        carry += (*u++) + (*v++);
637        (*w++) = carry & DIGIT_MASK;
638        carry >>= BITS_PER_DIGIT;
639    }
640
641    // Propagate the carry.
642    while (carry && (u < uend)) {
643        carry = (*u++) + 1;
644        (*w++) = carry & DIGIT_MASK;
645        carry >>= BITS_PER_DIGIT;
646    }
647
648    // Copy the rest of u to the result.
649    while (u < uend)
650        (*w++) = (*u++);
651
652    // Propagate the carry if it is still 1.
653    if (carry)
654        (*w) = 1;
655}
656
657
658// Compute u += v, where u and v are vectors.
659// - ulen >= vlen
660void
661vec_add_on(int ulen, sc_digit *ubegin, int vlen, const sc_digit *v)
662{
663#ifdef DEBUG_SYSTEMC
664    sc_assert((ulen > 0) && (ubegin != NULL));
665    sc_assert((vlen > 0) && (v != NULL));
666    sc_assert(ulen >= vlen);
667#endif
668
669    sc_digit *u = ubegin;
670    const sc_digit *uend = (u + ulen);
671    const sc_digit *vend = (v + vlen);
672
673    sc_digit carry = 0; // Also used as sum to save space.
674
675    // Add along the shorter v.
676    while (v < vend) {
677        carry += (*u) + (*v++);
678        (*u++) = carry & DIGIT_MASK;
679        carry >>= BITS_PER_DIGIT;
680    }
681
682    // Propagate the carry.
683    while (carry && (u < uend)) {
684        carry = (*u) + 1;
685        (*u++) = carry & DIGIT_MASK;
686        carry >>= BITS_PER_DIGIT;
687    }
688
689#ifdef   DEBUG_SYSTEMC
690    if (carry != 0) {
691        SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_,
692                          "vec_add_on( int, sc_digit*, int, const "
693                          "sc_digit* ) : "
694                          "result of addition is wrapped around");
695    }
696#endif
697}
698
699
700// Compute u += v, where u and v are vectors.
701// - ulen < vlen
702void
703vec_add_on2(int ulen, sc_digit *ubegin, int,
704#ifdef DEBUG_SYSTEMC
705            vlen,
706#endif
707            const sc_digit *v)
708{
709#ifdef DEBUG_SYSTEMC
710    sc_assert((ulen > 0) && (ubegin != NULL));
711    sc_assert((vlen > 0) && (v != NULL));
712    sc_assert(ulen < vlen);
713#endif
714
715    sc_digit *u = ubegin;
716    const sc_digit *uend = (u + ulen);
717
718    sc_digit carry = 0; // Also used as sum to save space.
719
720    // Add along the shorter u.
721    while (u < uend) {
722        carry += (*u) + (*v++);
723        (*u++) = carry & DIGIT_MASK;
724        carry >>= BITS_PER_DIGIT;
725    }
726
727#ifdef   DEBUG_SYSTEMC
728    if (carry != 0) {
729        SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_,
730                          "vec_add_on2( int, sc_digit*, int, const "
731                          "sc_digit* ) : "
732                          "result of addition is wrapped around");
733    }
734#endif
735}
736
737
738// Compute w = u + v, where w and u are vectors, and v is a scalar.
739void
740vec_add_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *w)
741{
742#ifdef DEBUG_SYSTEMC
743    sc_assert((ulen > 0) && (u != NULL));
744    sc_assert(w != NULL);
745#endif
746
747    const sc_digit *uend = (u + ulen);
748
749    // Add along the shorter v.
750    sc_digit carry = (*u++) + v;
751    (*w++) = carry & DIGIT_MASK;
752    carry >>= BITS_PER_DIGIT;
753
754    // Propagate the carry.
755    while (carry && (u < uend)) {
756        carry = (*u++) + 1;
757        (*w++) = carry & DIGIT_MASK;
758        carry >>= BITS_PER_DIGIT;
759    }
760
761    // Copy the rest of u to the result.
762    while (u < uend)
763        (*w++) = (*u++);
764
765    // Propagate the carry if it is still 1.
766    if (carry)
767        (*w) = 1;
768}
769
770// Compute u += v, where u is vectors, and v is a scalar.
771void
772vec_add_small_on(int ulen, sc_digit *u, sc_digit v)
773{
774#ifdef DEBUG_SYSTEMC
775    sc_assert((ulen > 0) && (u != NULL));
776#endif
777
778    int i = 0;
779
780    while (v && (i < ulen)) {
781        v += u[i];
782        u[i++] = v & DIGIT_MASK;
783        v >>= BITS_PER_DIGIT;
784    }
785
786#ifdef   DEBUG_SYSTEMC
787    if (v != 0) {
788        SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_,
789                          "vec_add_small_on( int, sc_digit*, unsigned "
790                          "long ) : "
791                          "result of addition is wrapped around");
792    }
793#endif
794}
795
796// Compute w = u - v, where w, u, and v are vectors.
797// - ulen >= vlen
798// - wlen >= sc_max(ulen, vlen)
799void
800vec_sub(int ulen, const sc_digit *u, int vlen, const sc_digit *v, sc_digit *w)
801{
802#ifdef DEBUG_SYSTEMC
803    sc_assert((ulen > 0) && (u != NULL));
804    sc_assert((vlen > 0) && (v != NULL));
805    sc_assert(w != NULL);
806    sc_assert(ulen >= vlen);
807#endif
808
809    const sc_digit *uend = (u + ulen);
810    const sc_digit *vend = (v + vlen);
811
812    sc_digit borrow = 0; // Also used as diff to save space.
813
814    // Subtract along the shorter v.
815    while (v < vend) {
816        borrow = ((*u++) + DIGIT_RADIX) - (*v++) - borrow;
817        (*w++) = borrow & DIGIT_MASK;
818        borrow = 1 - (borrow >> BITS_PER_DIGIT);
819    }
820
821    // Propagate the borrow.
822    while (borrow && (u < uend)) {
823        borrow = ((*u++) + DIGIT_RADIX) - 1;
824        (*w++) = borrow & DIGIT_MASK;
825        borrow = 1 - (borrow >> BITS_PER_DIGIT);
826    }
827
828#ifdef DEBUG_SYSTEMC
829    sc_assert(borrow == 0);
830#endif
831
832    // Copy the rest of u to the result.
833    while (u < uend)
834        (*w++) = (*u++);
835}
836
837// Compute u = u - v, where u and v are vectors.
838// - u > v
839// - ulen >= vlen
840void
841vec_sub_on(int ulen, sc_digit *ubegin, int vlen, const sc_digit *v)
842{
843#ifdef DEBUG_SYSTEMC
844    sc_assert((ulen > 0) && (ubegin != NULL));
845    sc_assert((vlen > 0) && (v != NULL));
846    sc_assert(ulen >= vlen);
847#endif
848
849    sc_digit *u = ubegin;
850    const sc_digit *uend = (u + ulen);
851    const sc_digit *vend = (v + vlen);
852
853    sc_digit borrow = 0;   // Also used as diff to save space.
854
855    // Subtract along the shorter v.
856    while (v < vend) {
857        borrow = ((*u) + DIGIT_RADIX) - (*v++) - borrow;
858        (*u++) = borrow & DIGIT_MASK;
859        borrow = 1 - (borrow >> BITS_PER_DIGIT);
860    }
861
862    // Propagate the borrow.
863    while (borrow && (u < uend)) {
864        borrow = ((*u) + DIGIT_RADIX) - 1;
865        (*u++) = borrow & DIGIT_MASK;
866        borrow = 1 - (borrow >> BITS_PER_DIGIT);
867    }
868
869#ifdef DEBUG_SYSTEMC
870    sc_assert(borrow == 0);
871#endif
872}
873
874// Compute u = v - u, where u and v are vectors.
875// - v > u
876// - ulen <= vlen or ulen > ulen
877void
878vec_sub_on2(int ulen, sc_digit *ubegin, int vlen, const sc_digit *v)
879{
880#ifdef DEBUG_SYSTEMC
881    sc_assert((ulen > 0) && (ubegin != NULL));
882    sc_assert((vlen > 0) && (v != NULL));
883#endif
884
885    sc_digit *u = ubegin;
886    const sc_digit *uend = (u + sc_min(ulen, vlen));
887
888    sc_digit borrow = 0;   // Also used as diff to save space.
889
890    // Subtract along the shorter u.
891    while (u < uend) {
892        borrow = ((*v++) + DIGIT_RADIX) - (*u) - borrow;
893        (*u++) = borrow & DIGIT_MASK;
894        borrow = 1 - (borrow >> BITS_PER_DIGIT);
895    }
896
897#ifdef DEBUG_SYSTEMC
898    if (borrow != 0) {
899        SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_,
900                          "vec_sub_on2( int, sc_digit*, int, const "
901                          "sc_digit* ) : "
902                          "result of subtraction is wrapped around");
903    }
904#endif
905}
906
907// Compute w = u - v, where w and u are vectors, and v is a scalar.
908void
909vec_sub_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *w)
910{
911#ifdef DEBUG_SYSTEMC
912    sc_assert(ulen > 0);
913    sc_assert(u != NULL);
914#endif
915
916    const sc_digit *uend = (u + ulen);
917
918    // Add along the shorter v.
919    sc_digit borrow = ((*u++) + DIGIT_RADIX) - v;
920    (*w++) = borrow & DIGIT_MASK;
921    borrow = 1 - (borrow >> BITS_PER_DIGIT);
922
923    // Propagate the borrow.
924    while (borrow && (u < uend)) {
925        borrow = ((*u++) + DIGIT_RADIX) - 1;
926        (*w++) = borrow & DIGIT_MASK;
927        borrow = 1 - (borrow >> BITS_PER_DIGIT);
928    }
929
930#ifdef   DEBUG_SYSTEMC
931    sc_assert(borrow == 0);
932#endif
933
934    // Copy the rest of u to the result.
935    while (u < uend)
936        (*w++) = (*u++);
937}
938
939
940// Compute u -= v, where u is vectors, and v is a scalar.
941void
942vec_sub_small_on(int ulen, sc_digit *u, sc_digit v)
943{
944#ifdef DEBUG_SYSTEMC
945    sc_assert((ulen > 0) && (u != NULL));
946#endif
947
948    for (int i = 0; i < ulen; ++i) {
949      v = (u[i] + DIGIT_RADIX) - v;
950      u[i] = v & DIGIT_MASK;
951      v = 1 - (v >> BITS_PER_DIGIT);
952    }
953
954#ifdef DEBUG_SYSTEMC
955    sc_assert(v == 0);
956#endif
957}
958
959// Compute w = u * v, where w, u, and v are vectors.
960void
961vec_mul(int ulen, const sc_digit *u, int vlen, const sc_digit *vbegin,
962        sc_digit *wbegin)
963{
964
965  /* Consider u = Ax + B and v = Cx + D where x is equal to
966     HALF_DIGIT_RADIX. In other words, A is the higher half of u and
967     B is the lower half of u. The interpretation for v is
968     similar. Then, we have the following picture:
969
970              u_h     u_l
971     u: -------- --------
972               A        B
973
974              v_h     v_l
975     v: -------- --------
976               C        D
977
978     result (d):
979     carry_before:                           -------- --------
980                                              carry_h  carry_l
981     result_before:        -------- -------- -------- --------
982                               R1_h     R1_l     R0_h     R0_l
983                                             -------- --------
984                                                 BD_h     BD_l
985                                    -------- --------
986                                        AD_h     AD_l
987                                    -------- --------
988                                        BC_h     BC_l
989                           -------- --------
990                               AC_h     AC_l
991     result_after:         -------- -------- -------- --------
992                              R1_h'    R1_l'    R0_h'    R0_l'
993
994     prod_l = R0_h|R0_l + B * D  + 0|carry_l
995            = R0_h|R0_l + BD_h|BD_l + 0|carry_l
996
997     prod_h = A * D + B * C + high_half(prod_l) + carry_h
998            = AD_h|AD_l + BC_h|BC_l + high_half(prod_l) + 0|carry_h
999
1000     carry = A * C + high_half(prod_h)
1001           = AC_h|AC_l + high_half(prod_h)
1002
1003     R0_l' = low_half(prod_l)
1004
1005     R0_h' = low_half(prod_h)
1006
1007     R0 = high_half(prod_h)|low_half(prod_l)
1008
1009     where '|' is the concatenation operation and the suffixes 0 and 1
1010     show the iteration number, i.e., 0 is the current iteration and 1
1011     is the next iteration.
1012
1013     NOTE: sc_max(prod_l, prod_h, carry) <= 2 * x^2 - 1, so any
1014     of these numbers can be stored in a digit.
1015
1016     NOTE: low_half(u) returns the lower BITS_PER_HALF_DIGIT of u,
1017     whereas high_half(u) returns the rest of the bits, which may
1018     contain more bits than BITS_PER_HALF_DIGIT.
1019  */
1020
1021#ifdef DEBUG_SYSTEMC
1022    sc_assert((ulen > 0) && (u != NULL));
1023    sc_assert((vlen > 0) && (vbegin != NULL));
1024    sc_assert(wbegin != NULL);
1025#endif
1026
1027#define prod_h carry
1028    const sc_digit *uend = (u + ulen);
1029    const sc_digit *vend = (vbegin + vlen);
1030
1031    while (u < uend) {
1032        sc_digit u_h = (*u++); // A|B
1033        sc_digit u_l = low_half(u_h); // B
1034        u_h = high_half(u_h); // A
1035
1036#ifdef DEBUG_SYSTEMC
1037        // The overflow bits must be zero.
1038        sc_assert(u_h == (u_h & HALF_DIGIT_MASK));
1039#endif
1040        sc_digit carry = 0;
1041        sc_digit *w = (wbegin++);
1042        const sc_digit *v = vbegin;
1043
1044        while (v < vend) {
1045            sc_digit v_h = (*v++); // C|D
1046            sc_digit v_l = low_half(v_h); // D
1047
1048            v_h = high_half(v_h); // C
1049
1050#ifdef   DEBUG_SYSTEMC
1051            // The overflow bits must be zero.
1052            sc_assert(v_h == (v_h & HALF_DIGIT_MASK));
1053#endif
1054
1055            sc_digit prod_l = (*w) + u_l * v_l + low_half(carry);
1056            prod_h = u_h * v_l + u_l * v_h +
1057                high_half(prod_l) + high_half(carry);
1058            (*w++) = concat(low_half(prod_h), low_half(prod_l));
1059            carry = u_h * v_h + high_half(prod_h);
1060        }
1061        (*w) = carry;
1062    }
1063#undef prod_h
1064}
1065
1066// Compute w = u * v, where w and u are vectors, and v is a scalar.
1067// - 0 < v < HALF_DIGIT_RADIX.
1068void
1069vec_mul_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *w)
1070{
1071#ifdef DEBUG_SYSTEMC
1072    sc_assert((ulen > 0) && (u != NULL));
1073    sc_assert(w != NULL);
1074    sc_assert((0 < v) && (v < HALF_DIGIT_RADIX));
1075#endif
1076
1077#define prod_h carry
1078
1079    const sc_digit *uend = (u + ulen);
1080    sc_digit carry = 0;
1081    while (u < uend) {
1082        sc_digit u_AB = (*u++);
1083#ifdef DEBUG_SYSTEMC
1084        // The overflow bits must be zero.
1085        sc_assert(high_half(u_AB) == high_half_masked(u_AB));
1086#endif
1087        sc_digit prod_l = v * low_half(u_AB) + low_half(carry);
1088        prod_h = v * high_half(u_AB) + high_half(prod_l) + high_half(carry);
1089        (*w++) = concat(low_half(prod_h), low_half(prod_l));
1090        carry = high_half(prod_h);
1091    }
1092    (*w) = carry;
1093#undef prod_h
1094}
1095
1096// Compute u = u * v, where u is a vector, and v is a scalar.
1097// - 0 < v < HALF_DIGIT_RADIX.
1098void
1099vec_mul_small_on(int ulen, sc_digit *u, sc_digit v)
1100{
1101#ifdef DEBUG_SYSTEMC
1102    sc_assert((ulen > 0) && (u != NULL));
1103    sc_assert((0 < v) && (v < HALF_DIGIT_RADIX));
1104#endif
1105
1106#define   prod_h carry
1107    sc_digit carry = 0;
1108    for (int i = 0; i < ulen; ++i) {
1109#ifdef DEBUG_SYSTEMC
1110        // The overflow bits must be zero.
1111        sc_assert(high_half(u[i]) == high_half_masked(u[i]));
1112#endif
1113        sc_digit prod_l = v * low_half(u[i]) + low_half(carry);
1114        prod_h = v * high_half(u[i]) + high_half(prod_l) + high_half(carry);
1115        u[i] = concat(low_half(prod_h), low_half(prod_l));
1116        carry = high_half(prod_h);
1117    }
1118#undef   prod_h
1119
1120#ifdef   DEBUG_SYSTEMC
1121    if (carry != 0) {
1122        SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_,
1123                          "vec_mul_small_on( int, sc_digit*, unsigned "
1124                          "long ) : "
1125                          "result of multiplication is wrapped around");
1126    }
1127#endif
1128}
1129
1130// Compute w = u / v, where w, u, and v are vectors.
1131// - u and v are assumed to have at least two digits as uchars.
1132void
1133vec_div_large(int ulen, const sc_digit *u, int vlen, const sc_digit *v,
1134              sc_digit *w)
1135{
1136#ifdef DEBUG_SYSTEMC
1137    sc_assert((ulen > 0) && (u != NULL));
1138    sc_assert((vlen > 0) && (v != NULL));
1139    sc_assert(w != NULL);
1140    sc_assert(BITS_PER_DIGIT >= 3 * BITS_PER_BYTE);
1141#endif
1142
1143    // We will compute q = x / y where x = u and y = v. The reason for
1144    // using x and y is that x and y are BYTE_RADIX copies of u and v,
1145    // respectively. The use of BYTE_RADIX radix greatly simplifies the
1146    // complexity of the division operation. These copies are also
1147    // needed even when we use DIGIT_RADIX representation.
1148
1149    int xlen = BYTES_PER_DIGIT * ulen + 1;
1150    int ylen = BYTES_PER_DIGIT * vlen;
1151
1152#ifdef SC_MAX_NBITS
1153    uchar x[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];
1154    uchar y[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];
1155    uchar q[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];
1156#else
1157    uchar *x = new uchar[xlen];
1158    uchar *y = new uchar[ylen];
1159    // valgrind complains about us accessing too far to so leave a buffer.
1160    uchar *q = new uchar[(xlen - ylen) + 10];
1161#endif
1162
1163    // q corresponds to w.
1164
1165    // Set (uchar) x = (sc_digit) u.
1166    xlen = vec_to_char(ulen, u, xlen, x);
1167
1168    // Skip all the leading zeros in x.
1169    while ((--xlen >= 0) && (! x[xlen]))
1170        continue;
1171    xlen++;
1172
1173    // Set (uchar) y = (sc_digit) v.
1174    ylen = vec_to_char(vlen, v, ylen, y);
1175
1176    // Skip all the leading zeros in y.
1177    while ((--ylen >= 0) && (! y[ylen]))
1178        continue;
1179    ylen++;
1180
1181#ifdef DEBUG_SYSTEMC
1182    sc_assert(xlen > 1);
1183    sc_assert(ylen > 1);
1184#endif
1185
1186    // At this point, all the leading zeros are eliminated from x and y.
1187
1188    // Zero the last digit of x.
1189    x[xlen] = 0;
1190
1191    // The first two digits of y.
1192    sc_digit y2 = (y[ylen - 1] << BITS_PER_BYTE) + y[ylen - 2];
1193
1194    const sc_digit DOUBLE_BITS_PER_BYTE = 2 * BITS_PER_BYTE;
1195
1196    // Find each q[k].
1197    for (int k = (xlen - ylen); k >= 0; --k) {
1198        // qk is a guess for q[k] such that q[k] = qk or qk - 1.
1199        sc_digit qk;
1200
1201        // Find qk by just using 2 digits of y and 3 digits of x. The
1202        // following code assumes that sizeof(sc_digit) >= 3 BYTEs.
1203        int k2 = k + ylen;
1204
1205        qk = ((x[k2] << DOUBLE_BITS_PER_BYTE) +
1206              (x[k2 - 1] << BITS_PER_BYTE) + x[k2 - 2]) / y2;
1207
1208        if (qk >= BYTE_RADIX) // qk cannot be larger than the largest
1209            qk = BYTE_RADIX - 1; // digit in BYTE_RADIX.
1210
1211        // q[k] = qk or qk - 1. The following if-statement determines which:
1212        if (qk) {
1213            uchar *xk = (x + k);  // A shortcut for x[k].
1214
1215            // x = x - y * qk :
1216            sc_digit carry = 0;
1217
1218            for (int i = 0; i < ylen; ++i) {
1219                carry += y[i] * qk;
1220                sc_digit diff = (xk[i] + BYTE_RADIX) - (carry & BYTE_MASK);
1221                xk[i] = (uchar)(diff & BYTE_MASK);
1222                carry = (carry >> BITS_PER_BYTE) +
1223                    (1 - (diff >> BITS_PER_BYTE));
1224            }
1225
1226            // If carry, qk may be one too large.
1227            if (carry) {
1228                // 2's complement the last digit.
1229                carry = (xk[ylen] + BYTE_RADIX) - carry;
1230                xk[ylen] = (uchar)(carry & BYTE_MASK);
1231                carry = 1 - (carry >> BITS_PER_BYTE);
1232
1233                if (carry) {
1234
1235                  // qk was one too large, so decrement it.
1236                  --qk;
1237
1238                  // Since qk was decreased by one, y must be added to x:
1239                  // x = x - y * (qk - 1) = x - y * qk + y = x_above + y.
1240                  carry = 0;
1241
1242                  for (int i = 0; i < ylen; ++i) {
1243                      carry += xk[i] + y[i];
1244                      xk[i] = (uchar)(carry & BYTE_MASK);
1245                      carry >>= BITS_PER_BYTE;
1246                  }
1247
1248                  if (carry)
1249                      xk[ylen] = (uchar)((xk[ylen] + 1) & BYTE_MASK);
1250
1251                }  // second if carry
1252            }  // first if carry
1253        }  // if qk
1254        q[k] = (uchar)qk;
1255    }  // for k
1256
1257    // Set (sc_digit) w = (uchar) q.
1258    vec_from_char(xlen - ylen + 1, q, ulen, w);
1259
1260#ifndef SC_MAX_NBITS
1261    delete [] x;
1262    delete [] y;
1263    delete [] q;
1264#endif
1265
1266}
1267
1268// Compute w = u / v, where u and w are vectors, and v is a scalar.
1269// - 0 < v < HALF_DIGIT_RADIX. Below, we rename w to q.
1270void
1271vec_div_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *q)
1272{
1273    // Given (u = u_1u_2...u_n)_b = (q = q_1q_2...q_n) * v + r, where b
1274    // is the base, and 0 <= r < v. Then, the algorithm is as follows:
1275    //
1276    // r = 0;
1277    // for (j = 1; j <= n; j++) {
1278    //   q_j = (r * b + u_j) / v;
1279    //   r = (r * b + u_j) % v;
1280    // }
1281    //
1282    // In our case, b = DIGIT_RADIX, and u = Ax + B and q = Cx + D where
1283    // x = HALF_DIGIT_RADIX. Note that r < v < x and b = x^2. Then, a
1284    // typical situation is as follows:
1285    //
1286    // ---- ----
1287    // 0    r
1288    //           ---- ----
1289    //           A    B
1290    //      ---- ---- ----
1291    //      r    A    B     = r * b + u
1292    //
1293    // Hence, C = (r|A) / v.
1294    //        D = (((r|A) % v)|B) / v
1295    //        r = (((r|A) % v)|B) % v
1296
1297#ifdef DEBUG_SYSTEMC
1298    sc_assert((ulen > 0) && (u != NULL));
1299    sc_assert(q != NULL);
1300    sc_assert((0 < v) && (v < HALF_DIGIT_RADIX));
1301#endif
1302
1303#define q_h r
1304    sc_digit r = 0;
1305    const sc_digit *ubegin = u;
1306
1307    u += ulen;
1308    q += ulen;
1309
1310    while (ubegin < u) {
1311        sc_digit u_AB = (*--u); // A|B
1312
1313#ifdef DEBUG_SYSTEMC
1314        // The overflow bits must be zero.
1315        sc_assert(high_half(u_AB) == high_half_masked(u_AB));
1316#endif
1317
1318        sc_digit num = concat(r, high_half(u_AB)); // num = r|A
1319        q_h = num / v; // C
1320        num = concat((num % v), low_half(u_AB)); // num = (((r|A) % v)|B)
1321        (*--q) = concat(q_h, num / v); // q = C|D
1322        r = num % v;
1323    }
1324#undef q_h
1325}
1326
1327// Compute w = u % v, where w, u, and v are vectors.
1328// - u and v are assumed to have at least two digits as uchars.
1329void
1330vec_rem_large(int ulen, const sc_digit *u, int vlen, const sc_digit *v,
1331              sc_digit *w)
1332{
1333#ifdef DEBUG_SYSTEMC
1334    sc_assert((ulen > 0) && (u != NULL));
1335    sc_assert((vlen > 0) && (v != NULL));
1336    sc_assert(w != NULL);
1337    sc_assert(BITS_PER_DIGIT >= 3 * BITS_PER_BYTE);
1338#endif
1339
1340    // This function is adapted from vec_div_large.
1341    int xlen = BYTES_PER_DIGIT * ulen + 1;
1342    int ylen = BYTES_PER_DIGIT * vlen;
1343
1344#ifdef SC_MAX_NBITS
1345    uchar x[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];
1346    uchar y[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];
1347#else
1348    uchar *x = new uchar[xlen];
1349    uchar *y = new uchar[ylen];
1350#endif
1351
1352    // r corresponds to w.
1353
1354    // Set (uchar) x = (sc_digit) u.
1355    xlen = vec_to_char(ulen, u, xlen, x);
1356
1357    // Skip all the leading zeros in x.
1358    while ((--xlen >= 0) && (!x[xlen]))
1359        continue;
1360    xlen++;
1361
1362    // Set (uchar) y = (sc_digit) v.
1363    ylen = vec_to_char(vlen, v, ylen, y);
1364
1365    // Skip all the leading zeros in y.
1366    while ((--ylen >= 0) && (!y[ylen]))
1367        continue;
1368    ylen++;
1369
1370#ifdef DEBUG_SYSTEMC
1371    sc_assert(xlen > 1);
1372    sc_assert(ylen > 1);
1373#endif
1374
1375    // At this point, all the leading zeros are eliminated from x and y.
1376
1377    // Zero the last digit of x.
1378    x[xlen] = 0;
1379
1380    // The first two digits of y.
1381    sc_digit y2 = (y[ylen - 1] << BITS_PER_BYTE) + y[ylen - 2];
1382
1383    const sc_digit DOUBLE_BITS_PER_BYTE = 2 * BITS_PER_BYTE;
1384
1385    // Find each q[k].
1386    for (int k = xlen - ylen; k >= 0; --k) {
1387        // qk is a guess for q[k] such that q[k] = qk or qk - 1.
1388        sc_digit qk;
1389
1390        // Find qk by just using 2 digits of y and 3 digits of x. The
1391        // following code assumes that sizeof(sc_digit) >= 3 BYTEs.
1392        int k2 = k + ylen;
1393
1394        qk = ((x[k2] << DOUBLE_BITS_PER_BYTE) +
1395            (x[k2 - 1] << BITS_PER_BYTE) + x[k2 - 2]) / y2;
1396
1397        if (qk >= BYTE_RADIX) // qk cannot be larger than the largest
1398            qk = BYTE_RADIX - 1; // digit in BYTE_RADIX.
1399
1400        // q[k] = qk or qk - 1. The following if-statement determines which.
1401        if (qk) {
1402            uchar *xk = (x + k);  // A shortcut for x[k].
1403
1404            // x = x - y * qk;
1405            sc_digit carry = 0;
1406
1407            for (int i = 0; i < ylen; ++i) {
1408                carry += y[i] * qk;
1409                sc_digit diff = (xk[i] + BYTE_RADIX) - (carry & BYTE_MASK);
1410                xk[i] = (uchar)(diff & BYTE_MASK);
1411                carry = (carry >> BITS_PER_BYTE) +
1412                    (1 - (diff >> BITS_PER_BYTE));
1413            }
1414
1415            if (carry) {
1416                // 2's complement the last digit.
1417                carry = (xk[ylen] + BYTE_RADIX) - carry;
1418                xk[ylen] = (uchar)(carry & BYTE_MASK);
1419                carry = 1 - (carry >> BITS_PER_BYTE);
1420
1421                if (carry) {
1422                  // qk was one too large, so decrement it.
1423                  // --qk;
1424
1425                  // x = x - y * (qk - 1) = x - y * qk + y = x_above + y.
1426                  carry = 0;
1427
1428                  for (int i = 0; i < ylen; ++i) {
1429                      carry += xk[i] + y[i];
1430                      xk[i] = (uchar)(carry & BYTE_MASK);
1431                      carry >>= BITS_PER_BYTE;
1432                  }
1433
1434                  if (carry)
1435                      xk[ylen] = (uchar)((xk[ylen] + 1) & BYTE_MASK);
1436                }  // second if carry
1437            } // first if carry
1438        }  // if qk
1439    }  // for k
1440
1441    // Set (sc_digit) w = (uchar) x for the remainder.
1442    vec_from_char(ylen, x, ulen, w);
1443
1444#ifndef SC_MAX_NBITS
1445    delete [] x;
1446    delete [] y;
1447#endif
1448
1449}
1450
1451// Compute r = u % v, where u is a vector, and r and v are scalars.
1452// - 0 < v < HALF_DIGIT_RADIX.
1453// - The remainder r is returned.
1454sc_digit
1455vec_rem_small(int ulen, const sc_digit *u, sc_digit v)
1456{
1457
1458#ifdef DEBUG_SYSTEMC
1459    sc_assert((ulen > 0) && (u != NULL));
1460    sc_assert((0 < v) && (v < HALF_DIGIT_RADIX));
1461#endif
1462
1463    // This function is adapted from vec_div_small().
1464
1465    sc_digit r = 0;
1466    const sc_digit *ubegin = u;
1467
1468    u += ulen;
1469
1470    while (ubegin < u) {
1471        sc_digit u_AB = (*--u); // A|B
1472#ifdef DEBUG_SYSTEMC
1473        // The overflow bits must be zero.
1474        sc_assert(high_half(u_AB) == high_half_masked(u_AB));
1475#endif
1476        // r = (((r|A) % v)|B) % v
1477        r = (concat(((concat(r, high_half(u_AB))) % v), low_half(u_AB))) % v;
1478    }
1479
1480    return r;
1481}
1482
1483// u = u / v, r = u % v.
1484sc_digit
1485vec_rem_on_small(int ulen, sc_digit *u, sc_digit v)
1486{
1487#ifdef DEBUG_SYSTEMC
1488    sc_assert((ulen > 0) && (u != NULL));
1489    sc_assert(v > 0);
1490#endif
1491
1492#define q_h r
1493    sc_digit r = 0;
1494    const sc_digit *ubegin = u;
1495
1496    u += ulen;
1497    while (ubegin < u) {
1498        sc_digit u_AB = (*--u); // A|B
1499#ifdef DEBUG_SYSTEMC
1500        // The overflow bits must be zero.
1501        sc_assert(high_half(u_AB) == high_half_masked(u_AB));
1502#endif
1503        sc_digit num = concat(r, high_half(u_AB)); // num = r|A
1504        q_h = num / v; // C
1505        num = concat((num % v), low_half(u_AB)); // num = (((r|A) % v)|B)
1506        (*u) = concat(q_h, num / v); // q = C|D
1507        r = num % v;
1508    }
1509#undef q_h
1510    return r;
1511}
1512
1513// Set (uchar) v = (sc_digit) u. Return the new vlen.
1514int
1515vec_to_char(int ulen, const sc_digit *u, int vlen, uchar *v)
1516{
1517#ifdef DEBUG_SYSTEMC
1518    sc_assert((ulen > 0) && (u != NULL));
1519    sc_assert((vlen > 0) && (v != NULL));
1520#endif
1521
1522    int nbits = ulen * BITS_PER_DIGIT;
1523    int right = 0;
1524    int left = right + BITS_PER_BYTE - 1;
1525
1526    vlen = 0;
1527    while (nbits > 0) {
1528        int left_digit = left / BITS_PER_DIGIT;
1529        int right_digit = right / BITS_PER_DIGIT;
1530        int nsr = ((vlen << LOG2_BITS_PER_BYTE) % BITS_PER_DIGIT);
1531        int d = u[right_digit] >> nsr;
1532
1533        if (left_digit != right_digit) {
1534            if (left_digit < ulen)
1535                d |= u[left_digit] << (BITS_PER_DIGIT - nsr);
1536        }
1537
1538        v[vlen++] = (uchar)(d & BYTE_MASK);
1539
1540        left += BITS_PER_BYTE;
1541        right += BITS_PER_BYTE;
1542        nbits -= BITS_PER_BYTE;
1543    }
1544    return vlen;
1545}
1546
1547// Set (sc_digit) v = (uchar) u.
1548// - sizeof(uchar) <= sizeof(sc_digit),
1549void
1550vec_from_char(int ulen, const uchar *u, int vlen, sc_digit *v)
1551{
1552#ifdef DEBUG_SYSTEMC
1553    sc_assert((ulen > 0) && (u != NULL));
1554    sc_assert((vlen > 0) && (v != NULL));
1555    sc_assert(sizeof(uchar) <= sizeof(sc_digit));
1556#endif
1557
1558    sc_digit *vend = (v + vlen);
1559
1560    const int nsr = BITS_PER_DIGIT - BITS_PER_BYTE;
1561    const sc_digit mask = one_and_ones(nsr);
1562
1563    (*v) = (sc_digit) u[ulen - 1];
1564
1565    for (int i = ulen - 2; i >= 0; --i) {
1566        // Manual inlining of vec_shift_left().
1567        sc_digit *viter = v;
1568        sc_digit carry = 0;
1569        while (viter < vend) {
1570            sc_digit vval = (*viter);
1571            (*viter++) = (((vval & mask) << BITS_PER_BYTE) | carry);
1572            carry = vval >> nsr;
1573        }
1574
1575        if (viter < vend)
1576            (*viter) = carry;
1577
1578        (*v) |= (sc_digit)u[i];
1579    }
1580}
1581
1582// Set u <<= nsl.
1583// If nsl is negative, it is ignored.
1584void
1585vec_shift_left(int ulen, sc_digit *u, int nsl)
1586{
1587#ifdef DEBUG_SYSTEMC
1588    sc_assert((ulen > 0) && (u != NULL));
1589#endif
1590
1591    if (nsl <= 0)
1592        return;
1593
1594    // Shift left whole digits if nsl is large enough.
1595    if (nsl >= (int) BITS_PER_DIGIT) {
1596        int nd;
1597        if (nsl % BITS_PER_DIGIT == 0) {
1598            nd = nsl / BITS_PER_DIGIT; // No need to use DIV_CEIL(nsl).
1599            nsl = 0;
1600        } else {
1601            nd = DIV_CEIL(nsl) - 1;
1602            nsl -= nd * BITS_PER_DIGIT;
1603        }
1604
1605        if (nd) {
1606            // Shift left for nd digits.
1607            for (int j = ulen - 1; j >= nd; --j)
1608                u[j] = u[j - nd];
1609
1610            vec_zero(sc_min(nd, ulen), u);
1611        }
1612        if (nsl == 0)
1613            return;
1614    }
1615
1616    // Shift left if nsl < BITS_PER_DIGIT.
1617    sc_digit *uiter = u;
1618    sc_digit *uend = uiter + ulen;
1619
1620    int nsr = BITS_PER_DIGIT - nsl;
1621    sc_digit mask = one_and_ones(nsr);
1622
1623    sc_digit carry = 0;
1624
1625    while (uiter < uend) {
1626        sc_digit uval = (*uiter);
1627        (*uiter++) = (((uval & mask) << nsl) | carry);
1628        carry = uval >> nsr;
1629    }
1630
1631    if (uiter < uend)
1632        (*uiter) = carry;
1633}
1634
1635// Set u >>= nsr.
1636// If nsr is negative, it is ignored.
1637void
1638vec_shift_right(int ulen, sc_digit *u, int nsr, sc_digit fill)
1639{
1640#ifdef DEBUG_SYSTEMC
1641    sc_assert((ulen > 0) && (u != NULL));
1642#endif
1643
1644    // fill is usually either 0 or DIGIT_MASK; it can be any value.
1645    if (nsr <= 0)
1646        return;
1647
1648    // Shift right whole digits if nsr is large enough.
1649    if (nsr >= (int) BITS_PER_DIGIT) {
1650        int nd;
1651        if (nsr % BITS_PER_DIGIT == 0) {
1652            nd = nsr / BITS_PER_DIGIT;
1653            nsr = 0;
1654        } else {
1655            nd = DIV_CEIL(nsr) - 1;
1656            nsr -= nd * BITS_PER_DIGIT;
1657        }
1658
1659        if (nd) {
1660            // Shift right for nd digits.
1661            for (int j = 0; j < (ulen - nd); ++j)
1662                u[j] = u[j + nd];
1663
1664            if (fill) {
1665                for (int j = ulen - sc_min( nd, ulen ); j < ulen; ++j)
1666                    u[j] = fill;
1667            } else {
1668                vec_zero(ulen - sc_min( nd, ulen ), ulen, u);
1669            }
1670        }
1671        if (nsr == 0)
1672          return;
1673    }
1674
1675    // Shift right if nsr < BITS_PER_DIGIT.
1676    sc_digit *ubegin = u;
1677    sc_digit *uiter = (ubegin + ulen);
1678
1679    int nsl = BITS_PER_DIGIT - nsr;
1680    sc_digit mask = one_and_ones(nsr);
1681
1682    sc_digit carry = (fill & mask) << nsl;
1683
1684    while (ubegin < uiter) {
1685        sc_digit uval = (*--uiter);
1686        (*uiter) = (uval >> nsr) | carry;
1687        carry = (uval & mask) << nsl;
1688    }
1689}
1690
1691
1692// Let u[l..r], where l and r are left and right bit positions
1693// respectively, be equal to its mirror image.
1694void
1695vec_reverse(int unb, int und, sc_digit *ud, int l, int r)
1696{
1697#ifdef DEBUG_SYSTEMC
1698    sc_assert((unb > 0) && (und > 0) && (ud != NULL));
1699    sc_assert((0 <= r) && (r <= l) && (l < unb));
1700#endif
1701
1702    if (l < r) {
1703        std::stringstream msg;
1704        msg << "vec_reverse( int, int, sc_digit*, int l, int r ) : " <<
1705               "l = " << l << " < r = " << r << " is not valid",
1706        SC_REPORT_ERROR("conversion failed", msg.str().c_str());
1707        return;
1708    }
1709
1710    // Make sure that l and r are within bounds.
1711    r = sc_max(r, 0);
1712    l = sc_min(l, unb - 1);
1713
1714    // Allocate memory for processing.
1715#ifdef SC_MAX_NBITS
1716    sc_digit d[MAX_NDIGITS];
1717#else
1718    sc_digit *d = new sc_digit[und];
1719#endif
1720
1721    // d is a copy of ud.
1722    vec_copy(und, d, ud);
1723
1724    // Based on the value of the ith in d, find the value of the jth bit
1725    // in ud.
1726    for (int i = l, j = r; i >= r; --i, ++j) {
1727        if ((d[digit_ord(i)] & one_and_zeros(bit_ord(i))) != 0) // Test.
1728            ud[digit_ord(j)] |= one_and_zeros(bit_ord(j)); // Set.
1729        else
1730            ud[digit_ord(j)] &= ~(one_and_zeros(bit_ord(j))); // Clear.
1731    }
1732
1733#ifndef SC_MAX_NBITS
1734    delete [] d;
1735#endif
1736}
1737
1738#ifdef SC_MAX_NBITS
1739void test_bound_failed(int nb)
1740{
1741    std::stringstream msg;
1742    msg << "test_bound( int nb ) : "
1743           "nb = " << nb << " > SC_MAX_NBITS = " << SC_MAX_NBITS <<
1744           "  is not valid";
1745    SC_REPORT_ERROR(sc_core::SC_ID_OUT_OF_BOUNDS_, msg.str().c_str());
1746}
1747#endif // SC_MAX_NBITS
1748
1749} // namespace sc_dt
1750