sc_nbutils.hh revision 12853
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.h -- 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// $Log: sc_nbutils.h,v $
40// Revision 1.6  2011/09/08 16:12:15  acg
41//  Philipp A. Hartmann: fix issue with Sun machines wrt real math libraries.
42//
43// Revision 1.5  2011/08/26 23:00:01  acg
44//  Torsten Maehne: remove use of ieeefp.h.
45//
46// Revision 1.4  2011/08/15 16:43:24  acg
47//  Torsten Maehne: changes to remove unused argument warnings.
48//
49// Revision 1.3  2011/02/18 20:19:15  acg
50//  Andy Goodrich: updating Copyright notice.
51//
52// Revision 1.2  2010/09/06 16:35:48  acg
53//  Andy Goodrich: changed i386 to __i386__ in ifdef's.
54//
55// Revision 1.1.1.1  2006/12/15 20:20:05  acg
56// SystemC 2.3
57//
58// Revision 1.3  2006/01/13 18:49:32  acg
59// Added $Log command so that CVS check in comments are reproduced in the
60// source.
61//
62
63#ifndef __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__
64#define __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__
65
66#include <cmath>
67#include <ios>
68#include <limits>
69#include <ostream>
70
71#include "../../utils/sc_report_handler.hh"
72#include "sc_nbdefs.hh"
73
74namespace sc_dt
75{
76
77//-----------------------------------------------------------------------------
78//"sc_io_base"
79//
80// This inline function returns the type of an i/o stream's base as a SystemC
81// base designator.
82//   stream_object = reference to the i/o stream whose base is to be returned.
83//
84//"sc_io_show_base"
85//
86// This inline function returns true if the base should be shown when a SystemC
87// value is displayed via the supplied stream operator.
88//   stream_object = reference to the i/o stream to return showbase value for.
89//-----------------------------------------------------------------------------
90inline sc_numrep
91sc_io_base(::std::ostream &os, sc_numrep def_base)
92{
93    std::ios::fmtflags flags = os.flags() & std::ios::basefield;
94    if (flags & ::std::ios::dec) return SC_DEC;
95    if (flags & ::std::ios::hex) return SC_HEX;
96    if (flags & ::std::ios::oct) return SC_OCT;
97    return def_base;
98}
99
100inline bool
101sc_io_show_base(::std::ostream &os)
102{
103    return (os.flags() & ::std::ios::showbase) != 0;
104}
105
106const std::string to_string(sc_numrep);
107
108inline ::std::ostream &
109operator << (::std::ostream &os, sc_numrep numrep)
110{
111    os << to_string(numrep);
112    return os;
113}
114
115// ----------------------------------------------------------------------------
116
117// One transition of the FSM to find base and sign of a number.
118extern small_type fsm_move(
119        char c, small_type &b, small_type &s, small_type &state);
120
121// Parse a character string into its equivalent binary bits.
122extern void parse_binary_bits(
123        const char *src_p, int dst_n, sc_digit *data_p, sc_digit *ctrl_p=0);
124
125// Parse a character string into its equivalent hexadecimal bits.
126extern void parse_hex_bits(
127        const char *src_p, int dst_n, sc_digit *data_p, sc_digit *ctrl_p=0);
128
129// Find the base and sign of a number in v.
130extern const char *get_base_and_sign(
131        const char *v, small_type &base, small_type &sign);
132
133// Create a number out of v in base.
134extern small_type
135vec_from_str(int unb, int und, sc_digit *u,
136             const char *v, sc_numrep base=SC_NOBASE);
137
138
139// ----------------------------------------------------------------------------
140//  Naming convention for the vec_ functions below:
141//    vec_OP(u, v, w)  : computes w = u OP v.
142//    vec_OP_on(u, v)  : computes u = u OP v if u has more digits than v.
143//    vec_OP_on2(u, v) : computes u = u OP v if u has fewer digits than v.
144//    _large           : parameters are vectors.
145//    _small           : one of the parameters is a single digit.
146//    Xlen             : the number of digits in X.
147// ----------------------------------------------------------------------------
148
149// ----------------------------------------------------------------------------
150//  Functions for vector addition: w = u + v or u += v.
151// ----------------------------------------------------------------------------
152
153extern void vec_add(int ulen, const sc_digit *u,
154                    int vlen, const sc_digit *v, sc_digit *w);
155extern void vec_add_on(int ulen, sc_digit *u, int vlen, const sc_digit *v);
156extern void vec_add_on2(int ulen, sc_digit *u, int vlen, const sc_digit *v);
157extern void vec_add_small(int ulen, const sc_digit *u,
158                          sc_digit v, sc_digit *w);
159extern void vec_add_small_on(int ulen, sc_digit *u, sc_digit v);
160
161// ----------------------------------------------------------------------------
162//  Functions for vector subtraction: w = u - v, u -= v, or u = v - u.
163// ----------------------------------------------------------------------------
164
165extern void vec_sub(int ulen, const sc_digit *u,
166                    int vlen, const sc_digit *v, sc_digit *w);
167extern void vec_sub_on(int ulen, sc_digit *u, int vlen, const sc_digit *v);
168extern void vec_sub_on2(int ulen, sc_digit *u, int vlen, const sc_digit *v);
169extern void vec_sub_small(int ulen, const sc_digit *u,
170                          sc_digit v, sc_digit *w);
171extern void vec_sub_small_on(int ulen, sc_digit *u, sc_digit v);
172
173
174// ----------------------------------------------------------------------------
175//  Functions for vector multiplication: w = u * v or u *= v.
176// ----------------------------------------------------------------------------
177
178extern void vec_mul(int ulen, const sc_digit *u,
179                    int vlen, const sc_digit *v, sc_digit *w);
180extern void vec_mul_small(int ulen, const sc_digit *u,
181                          sc_digit v, sc_digit *w);
182extern void vec_mul_small_on(int ulen, sc_digit *u, sc_digit v);
183
184
185// ----------------------------------------------------------------------------
186//  Functions for vector division: w = u / v.
187// ----------------------------------------------------------------------------
188
189extern void vec_div_large(int ulen, const sc_digit *u,
190                          int vlen, const sc_digit *v, sc_digit *w);
191extern void vec_div_small(int ulen, const sc_digit *u,
192                          sc_digit v, sc_digit *w);
193
194
195// ----------------------------------------------------------------------------
196//  Functions for vector remainder: w = u % v or u %= v.
197// ----------------------------------------------------------------------------
198
199extern void vec_rem_large(int ulen, const sc_digit *u,
200                          int vlen, const sc_digit *v, sc_digit *w);
201extern sc_digit vec_rem_small(int ulen, const sc_digit *u, sc_digit v);
202extern sc_digit vec_rem_on_small(int ulen, sc_digit *u, sc_digit v);
203
204
205// ----------------------------------------------------------------------------
206//  Functions to convert between vectors of char and sc_digit.
207// ----------------------------------------------------------------------------
208
209extern int vec_to_char(int ulen, const sc_digit *u, int vlen, uchar *v);
210extern void vec_from_char(int ulen, const uchar *u, int vlen, sc_digit *v);
211
212
213// ----------------------------------------------------------------------------
214//  Functions to shift left or right, or to create a mirror image of vectors.
215// ----------------------------------------------------------------------------
216
217extern void vec_shift_left(int ulen, sc_digit *u, int nsl);
218extern void vec_shift_right(int vlen, sc_digit *u, int nsr, sc_digit fill=0);
219extern void vec_reverse(int unb, int und, sc_digit *ud, int l, int r=0);
220
221
222// ----------------------------------------------------------------------------
223//  Various utility functions.
224// ----------------------------------------------------------------------------
225
226// Return the low half part of d.
227inline sc_digit low_half(sc_digit d) { return (d & HALF_DIGIT_MASK); }
228
229// Return the high half part of d. The high part of the digit may have
230// more bits than BITS_PER_HALF_DIGIT due to, e.g., overflow in the
231// multiplication. Hence, in other functions that use high_half(),
232// make sure that the result contains BITS_PER_HALF_DIGIT if
233// necessary. This is done by high_half_masked().
234inline sc_digit high_half(sc_digit d) { return (d >> BITS_PER_HALF_DIGIT); }
235inline sc_digit
236high_half_masked(sc_digit d)
237{
238    return (high_half(d) & HALF_DIGIT_MASK);
239}
240
241// Concatenate the high part h and low part l. Assumes that h and l
242// are less than or equal to HALF_DIGIT_MASK;
243inline sc_digit
244concat(sc_digit h, sc_digit l)
245{
246    return ((h << BITS_PER_HALF_DIGIT) | l);
247}
248
249// Create a number with n 1's.
250inline sc_digit
251one_and_ones(int n)
252{
253    return (((sc_digit) 1 << n) - 1);
254}
255
256// Create a number with one 1 and n 0's.
257inline sc_digit one_and_zeros(int n) { return ((sc_digit) 1 << n); }
258
259
260// ----------------------------------------------------------------------------
261
262// Find the digit that bit i is in.
263inline int digit_ord(int i) { return (i / BITS_PER_DIGIT); }
264
265// Find the bit in digit_ord(i) that bit i corressponds to.
266inline int bit_ord(int i) { return (i % BITS_PER_DIGIT); }
267
268
269// ----------------------------------------------------------------------------
270//  Functions to compare, zero, complement vector(s).
271// ----------------------------------------------------------------------------
272
273// Compare u and v and return r
274//  r = 0 if u == v
275//  r < 0 if u < v
276//  r > 0 if u > v
277// - Assume that all the leading zero digits are already skipped.
278// - ulen and/or vlen can be zero.
279// - Every digit is less than or equal to DIGIT_MASK;
280inline int
281vec_cmp(int ulen, const sc_digit *u,
282        int vlen, const sc_digit *v)
283{
284
285#ifdef DEBUG_SYSTEMC
286    // sc_assert((ulen <= 0) || (u != NULL));
287    // sc_assert((vlen <= 0) || (v != NULL));
288
289    // ulen and vlen can be equal to 0 because vec_cmp can be called
290    // after vec_skip_leading_zeros.
291    sc_assert((ulen >= 0) && (u != NULL));
292    sc_assert((vlen >= 0) && (v != NULL));
293    // If ulen > 0, then the leading digit of u must be non-zero.
294    sc_assert((ulen <= 0) || (u[ulen - 1] != 0));
295    sc_assert((vlen <= 0) || (v[vlen - 1] != 0));
296#endif
297
298    if (ulen != vlen)
299        return (ulen - vlen);
300
301    // ulen == vlen >= 1
302    while ((--ulen >= 0) && (u[ulen] == v[ulen]))
303    {}
304
305    if (ulen < 0)
306        return 0;
307
308#ifdef DEBUG_SYSTEMC
309    // Test to see if the result is wrong due to the presence of
310    // overflow bits.
311    sc_assert((u[ulen] & DIGIT_MASK) != (v[ulen] & DIGIT_MASK));
312#endif
313
314    return (int)(u[ulen] - v[ulen]);
315}
316
317// Find the index of the first non-zero digit.
318// - ulen (before) = the number of digits in u.
319// - the returned value = the index of the first non-zero digit.
320// A negative value of -1 indicates that every digit in u is zero.
321inline int
322vec_find_first_nonzero(int ulen, const sc_digit *u)
323{
324
325#ifdef DEBUG_SYSTEMC
326    // sc_assert((ulen <= 0) || (u != NULL));
327    sc_assert((ulen > 0) && (u != NULL));
328#endif
329
330    while ((--ulen >= 0) && (! u[ulen]))
331    {}
332
333    return ulen;
334}
335
336// Skip all the leading zero digits.
337// - ulen (before) = the number of digits in u.
338// - the returned value = the number of non-zero digits in u.
339// - the returned value is non-negative.
340inline int
341vec_skip_leading_zeros(int ulen, const sc_digit *u)
342{
343#ifdef DEBUG_SYSTEMC
344    // sc_assert((ulen <= 0) || (u != NULL));
345    sc_assert((ulen > 0) && (u != NULL));
346#endif
347
348    return (1 + vec_find_first_nonzero(ulen, u));
349}
350
351// Compare u and v and return r
352//  r = 0 if u == v
353//  r < 0 if u < v
354//  r > 0 if u > v
355inline int
356vec_skip_and_cmp(int ulen, const sc_digit *u, int vlen, const sc_digit *v)
357{
358#ifdef DEBUG_SYSTEMC
359    sc_assert((ulen > 0) && (u != NULL));
360    sc_assert((vlen > 0) && (v != NULL));
361#endif
362
363    ulen = vec_skip_leading_zeros(ulen, u);
364    vlen = vec_skip_leading_zeros(vlen, v);
365    // ulen and/or vlen can be equal to zero here.
366    return vec_cmp(ulen, u, vlen, v);
367}
368
369// Set u[i] = 0 where i = from ... (ulen - 1).
370inline void
371vec_zero(int from, int ulen, sc_digit *u)
372{
373#ifdef DEBUG_SYSTEMC
374    sc_assert((ulen > 0) && (u != NULL));
375#endif
376    for (int i = from; i < ulen; i++)
377        u[i] = 0;
378}
379
380// Set u[i] = 0 where i = 0 .. (ulen - 1).
381inline void vec_zero(int ulen, sc_digit *u) { vec_zero(0, ulen, u); }
382
383// Copy n digits from v to u.
384inline void
385vec_copy(int n, sc_digit *u, const sc_digit *v)
386{
387#ifdef DEBUG_SYSTEMC
388    sc_assert((n > 0) && (u != NULL) && (v != NULL));
389#endif
390    for (int i = 0; i < n; ++i)
391        u[i] = v[i];
392}
393
394// Copy v to u, where ulen >= vlen, and zero the rest of the digits in u.
395inline void
396vec_copy_and_zero(int ulen, sc_digit *u, int vlen, const sc_digit *v)
397{
398
399#ifdef DEBUG_SYSTEMC
400    sc_assert((ulen > 0) && (u != NULL));
401    sc_assert((vlen > 0) && (v != NULL));
402    sc_assert(ulen >= vlen);
403#endif
404    vec_copy(vlen, u, v);
405    vec_zero(vlen, ulen, u);
406
407}
408
409// 2's-complement the digits in u.
410inline void
411vec_complement(int ulen, sc_digit *u)
412{
413
414#ifdef DEBUG_SYSTEMC
415    sc_assert((ulen > 0) && (u != NULL));
416#endif
417
418    sc_digit carry = 1;
419
420    for (int i = 0; i < ulen; ++i) {
421        carry += (~u[i] & DIGIT_MASK);
422        u[i] = carry & DIGIT_MASK;
423        carry >>= BITS_PER_DIGIT;
424    }
425}
426
427
428// ----------------------------------------------------------------------------
429//  Functions to handle built-in types or signs.
430// ----------------------------------------------------------------------------
431
432// u = v
433// - v is an unsigned long or uint64, and positive integer.
434template<class Type>
435inline void
436from_uint(int ulen, sc_digit *u, Type v)
437{
438#ifdef DEBUG_SYSTEMC
439    // sc_assert((ulen <= 0) || (u != NULL));
440    sc_assert((ulen > 0) && (u != NULL));
441    sc_assert(v >= 0);
442#endif
443
444    int i = 0;
445
446    while (v && (i < ulen)) {
447        u[i++] = static_cast<sc_digit>(v & DIGIT_MASK);
448        v >>= BITS_PER_DIGIT;
449    }
450    vec_zero(i, ulen, u);
451}
452
453#ifndef __GNUC__
454#  define SC_LIKELY_(x) !!(x)
455#else
456#  define SC_LIKELY_(x) __builtin_expect(!!(x), 1)
457#endif
458
459// Get u's sign and return its absolute value.
460// u can be long, unsigned long, int64, or uint64.
461template<class Type>
462inline small_type
463get_sign(Type &u)
464{
465    if (u > 0)
466        return SC_POS;
467
468    if (u == 0)
469        return SC_ZERO;
470
471    // no positive number representable for minimum value,
472    // leave as is to avoid Undefined Behaviour
473    if (SC_LIKELY_(u > (std::numeric_limits<Type>::min)()))
474        u = -u;
475
476    return SC_NEG;
477}
478
479#undef SC_LIKELY_
480
481
482// Return us * vs:
483// - Return SC_ZERO if either sign is SC_ZERO.
484// - Return SC_POS if us == vs
485// - Return SC_NEG if us != vs.
486inline small_type
487mul_signs(small_type us, small_type vs)
488{
489    if ((us == SC_ZERO) || (vs == SC_ZERO))
490        return SC_ZERO;
491
492    if (us == vs)
493        return SC_POS;
494
495    return SC_NEG;
496}
497
498
499// ----------------------------------------------------------------------------
500//  Functions to test for errors and print out error messages.
501// ----------------------------------------------------------------------------
502
503#ifdef SC_MAX_NBITS
504
505void test_bound_failed(int nb);
506
507inline void
508test_bound(int nb)
509{
510    if (nb > SC_MAX_NBITS) {
511        test_bound_failed(nb);
512        sc_core::sc_abort(); // can't recover from here
513    }
514}
515
516#endif
517
518template<class Type>
519inline void
520div_by_zero(Type s)
521{
522    if (s == 0) {
523        SC_REPORT_ERROR("operation failed",
524                        "div_by_zero<Type>(Type) : division by zero");
525        sc_core::sc_abort(); // can't recover from here
526    }
527}
528
529
530// ----------------------------------------------------------------------------
531//  Functions to check if a given vector is zero or make one.
532// ----------------------------------------------------------------------------
533
534// If u[i] is zero for every i = 0,..., ulen - 1, return SC_ZERO,
535// else return s.
536inline small_type
537check_for_zero(small_type s, int ulen, const sc_digit *u)
538{
539
540#ifdef DEBUG_SYSTEMC
541    // sc_assert(ulen >= 0);
542    sc_assert((ulen > 0) && (u != NULL));
543#endif
544
545    if (vec_find_first_nonzero(ulen, u) < 0)
546        return SC_ZERO;
547
548    return s;
549}
550
551// If u[i] is zero for every i = 0,..., ulen - 1, return true,
552// else return false.
553inline bool
554check_for_zero(int ulen, const sc_digit *u)
555{
556
557#ifdef DEBUG_SYSTEMC
558    // sc_assert(ulen >= 0);
559    sc_assert((ulen > 0) && (u != NULL));
560#endif
561
562    if (vec_find_first_nonzero(ulen, u) < 0)
563        return true;
564
565    return false;
566}
567
568inline small_type
569make_zero(int nd, sc_digit *d)
570{
571    vec_zero(nd, d);
572    return SC_ZERO;
573}
574
575
576// ----------------------------------------------------------------------------
577//  Functions for both signed and unsigned numbers to convert sign-magnitude
578//  (SM) and 2's complement (2C) representations.
579//  added = 1 => for signed.
580//  added = 0 => for unsigned.
581//  IF_SC_SIGNED can be used as 'added'.
582// ----------------------------------------------------------------------------
583
584// Trim the extra leading bits of a signed or unsigned number.
585inline void
586trim(small_type added, int nb, int nd, sc_digit *d)
587{
588#ifdef DEBUG_SYSTEMC
589    sc_assert((nb > 0) && (nd > 0) && (d != NULL));
590#endif
591    d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + added);
592}
593
594// Convert an (un)signed number from sign-magnitude representation to
595// 2's complement representation and trim the extra bits.
596inline void
597convert_SM_to_2C_trimmed(small_type added,
598                         small_type s, int nb, int nd, sc_digit *d)
599{
600    if (s == SC_NEG) {
601        vec_complement(nd, d);
602        trim(added, nb, nd, d);
603    }
604}
605
606// Convert an (un)signed number from sign-magnitude representation to
607// 2's complement representation but do not trim the extra bits.
608inline void
609convert_SM_to_2C(small_type s, int nd, sc_digit *d)
610{
611    if (s == SC_NEG)
612        vec_complement(nd, d);
613}
614
615
616// ----------------------------------------------------------------------------
617//  Functions to convert between sign-magnitude (SM) and 2's complement
618//  (2C) representations of signed numbers.
619// ----------------------------------------------------------------------------
620
621// Trim the extra leading bits off a signed number.
622inline void
623trim_signed(int nb, int nd, sc_digit *d)
624{
625#ifdef DEBUG_SYSTEMC
626    sc_assert((nb > 0) && (nd > 0) && (d != NULL));
627#endif
628    d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + 1);
629}
630
631// Convert a signed number from 2's complement representation to
632// sign-magnitude representation, and return its sign. nd is d's
633// actual size, without zeros eliminated.
634inline small_type
635convert_signed_2C_to_SM(int nb, int nd, sc_digit *d)
636{
637#ifdef DEBUG_SYSTEMC
638    sc_assert((nb > 0) && (nd > 0) && (d != NULL));
639#endif
640
641    small_type s;
642
643    int xnb = bit_ord(nb - 1) + 1;
644
645    // Test the sign bit.
646    if (d[nd - 1] & one_and_zeros(xnb - 1)) {
647        s = SC_NEG;
648        vec_complement(nd, d);
649    } else {
650        s = SC_POS;
651    }
652
653    // Trim the last digit.
654    d[nd - 1] &= one_and_ones(xnb);
655
656    // Check if the new number is zero.
657    if (s == SC_POS)
658        return check_for_zero(s, nd, d);
659
660    return s;
661}
662
663// Convert a signed number from sign-magnitude representation to 2's
664// complement representation, get its sign, convert back to
665// sign-magnitude representation, and return its sign. nd is d's
666// actual size, without zeros eliminated.
667inline small_type
668convert_signed_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d)
669{
670    convert_SM_to_2C(s, nd, d);
671    return convert_signed_2C_to_SM(nb, nd, d);
672}
673
674// Convert a signed number from sign-magnitude representation to 2's
675// complement representation and trim the extra bits.
676inline void
677convert_signed_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d)
678{
679    convert_SM_to_2C_trimmed(1, s, nb, nd, d);
680}
681
682// Convert a signed number from sign-magnitude representation to 2's
683// complement representation but do not trim the extra bits.
684inline void
685convert_signed_SM_to_2C(small_type s, int nd, sc_digit *d)
686{
687    convert_SM_to_2C(s, nd, d);
688}
689
690
691// ----------------------------------------------------------------------------
692//  Functions to convert between sign-magnitude (SM) and 2's complement
693//  (2C) representations of unsigned numbers.
694// ----------------------------------------------------------------------------
695
696// Trim the extra leading bits off an unsigned number.
697inline void
698trim_unsigned(int nb, int nd, sc_digit *d)
699{
700#ifdef DEBUG_SYSTEMC
701    sc_assert((nb > 0) && (nd > 0) && (d != NULL));
702#endif
703
704    d[nd - 1] &= one_and_ones(bit_ord(nb - 1));
705}
706
707// Convert an unsigned number from 2's complement representation to
708// sign-magnitude representation, and return its sign. nd is d's
709// actual size, without zeros eliminated.
710inline small_type
711convert_unsigned_2C_to_SM(int nb, int nd, sc_digit *d)
712{
713    trim_unsigned(nb, nd, d);
714    return check_for_zero(SC_POS, nd, d);
715}
716
717// Convert an unsigned number from sign-magnitude representation to
718// 2's complement representation, get its sign, convert back to
719// sign-magnitude representation, and return its sign. nd is d's
720// actual size, without zeros eliminated.
721inline small_type
722convert_unsigned_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d)
723{
724    convert_SM_to_2C(s, nd, d);
725    return convert_unsigned_2C_to_SM(nb, nd, d);
726}
727
728// Convert an unsigned number from sign-magnitude representation to
729// 2's complement representation and trim the extra bits.
730inline void
731convert_unsigned_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d)
732{
733    convert_SM_to_2C_trimmed(0, s, nb, nd, d);
734}
735
736// Convert an unsigned number from sign-magnitude representation to
737// 2's complement representation but do not trim the extra bits.
738inline void
739convert_unsigned_SM_to_2C(small_type s, int nd, sc_digit *d)
740{
741    convert_SM_to_2C(s, nd, d);
742}
743
744
745// ----------------------------------------------------------------------------
746//  Functions to copy one (un)signed number to another.
747// ----------------------------------------------------------------------------
748
749// Copy v to u.
750inline void
751copy_digits_signed(small_type &us,
752                   int unb, int und, sc_digit *ud,
753                   int vnb, int vnd, const sc_digit *vd)
754{
755    if (und <= vnd) {
756        vec_copy(und, ud, vd);
757
758        if (unb <= vnb)
759            us = convert_signed_SM_to_2C_to_SM(us, unb, und, ud);
760    } else { // und > vnd
761        vec_copy_and_zero(und, ud, vnd, vd);
762    }
763}
764
765// Copy v to u.
766inline void
767copy_digits_unsigned(small_type &us,
768                     int unb, int und, sc_digit *ud,
769                     int /* vnb */, int vnd, const sc_digit *vd)
770{
771    if (und <= vnd)
772        vec_copy(und, ud, vd);
773    else // und > vnd
774        vec_copy_and_zero(und, ud, vnd, vd);
775
776    us = convert_unsigned_SM_to_2C_to_SM(us, unb, und, ud);
777}
778
779
780// ----------------------------------------------------------------------------
781//  Faster set(i, v), without bound checking.
782// ----------------------------------------------------------------------------
783
784// A version of set(i, v) without bound checking.
785inline void
786safe_set(int i, bool v, sc_digit *d)
787{
788
789#ifdef DEBUG_SYSTEMC
790    sc_assert((i >= 0) && (d != NULL));
791#endif
792
793    int bit_num = bit_ord(i);
794    int digit_num = digit_ord(i);
795
796    if (v)
797        d[digit_num] |= one_and_zeros(bit_num);
798    else
799        d[digit_num] &= ~(one_and_zeros(bit_num));
800}
801
802
803// ----------------------------------------------------------------------------
804//  Function to check if a double number is bad (NaN or infinite).
805// ----------------------------------------------------------------------------
806
807inline bool
808is_nan(double v)
809{
810    return std::numeric_limits<double>::has_quiet_NaN && (v != v);
811}
812
813inline bool
814is_inf(double v)
815{
816    return v ==  std::numeric_limits<double>::infinity() ||
817           v == -std::numeric_limits<double>::infinity();
818}
819
820inline void
821is_bad_double(double v)
822{
823    // Windows throws exception.
824    if (is_nan(v) || is_inf(v))
825        SC_REPORT_ERROR("value is not valid",
826                        "is_bad_double(double v) : "
827                        "v is not finite - NaN or Inf");
828}
829
830} // namespace sc_dt
831
832#endif // __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__
833