summaryrefslogtreecommitdiff
path: root/src/systemc/ext/dt/int/sc_nbutils.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/ext/dt/int/sc_nbutils.hh')
-rw-r--r--src/systemc/ext/dt/int/sc_nbutils.hh832
1 files changed, 832 insertions, 0 deletions
diff --git a/src/systemc/ext/dt/int/sc_nbutils.hh b/src/systemc/ext/dt/int/sc_nbutils.hh
new file mode 100644
index 000000000..9f7269e8c
--- /dev/null
+++ b/src/systemc/ext/dt/int/sc_nbutils.hh
@@ -0,0 +1,832 @@
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_nbutils.h -- External and friend functions for both sc_signed and
+ sc_unsigned classes.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+// $Log: sc_nbutils.h,v $
+// Revision 1.6 2011/09/08 16:12:15 acg
+// Philipp A. Hartmann: fix issue with Sun machines wrt real math libraries.
+//
+// Revision 1.5 2011/08/26 23:00:01 acg
+// Torsten Maehne: remove use of ieeefp.h.
+//
+// Revision 1.4 2011/08/15 16:43:24 acg
+// Torsten Maehne: changes to remove unused argument warnings.
+//
+// Revision 1.3 2011/02/18 20:19:15 acg
+// Andy Goodrich: updating Copyright notice.
+//
+// Revision 1.2 2010/09/06 16:35:48 acg
+// Andy Goodrich: changed i386 to __i386__ in ifdef's.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:49:32 acg
+// Added $Log command so that CVS check in comments are reproduced in the
+// source.
+//
+
+#ifndef __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__
+#define __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__
+
+#include <cmath>
+#include <ios>
+#include <limits>
+#include <ostream>
+
+#include "../../utils/sc_report_handler.hh"
+#include "sc_nbdefs.hh"
+
+namespace sc_dt
+{
+
+//-----------------------------------------------------------------------------
+//"sc_io_base"
+//
+// This inline function returns the type of an i/o stream's base as a SystemC
+// base designator.
+// stream_object = reference to the i/o stream whose base is to be returned.
+//
+//"sc_io_show_base"
+//
+// This inline function returns true if the base should be shown when a SystemC
+// value is displayed via the supplied stream operator.
+// stream_object = reference to the i/o stream to return showbase value for.
+//-----------------------------------------------------------------------------
+inline sc_numrep
+sc_io_base(::std::ostream &os, sc_numrep def_base)
+{
+ std::ios::fmtflags flags = os.flags() & std::ios::basefield;
+ if (flags & ::std::ios::dec) return SC_DEC;
+ if (flags & ::std::ios::hex) return SC_HEX;
+ if (flags & ::std::ios::oct) return SC_OCT;
+ return def_base;
+}
+
+inline bool
+sc_io_show_base(::std::ostream &os)
+{
+ return (os.flags() & ::std::ios::showbase) != 0;
+}
+
+const std::string to_string(sc_numrep);
+
+inline ::std::ostream &
+operator << (::std::ostream &os, sc_numrep numrep)
+{
+ os << to_string(numrep);
+ return os;
+}
+
+// ----------------------------------------------------------------------------
+
+// One transition of the FSM to find base and sign of a number.
+extern small_type fsm_move(
+ char c, small_type &b, small_type &s, small_type &state);
+
+// Parse a character string into its equivalent binary bits.
+extern void parse_binary_bits(
+ const char *src_p, int dst_n, sc_digit *data_p, sc_digit *ctrl_p=0);
+
+// Parse a character string into its equivalent hexadecimal bits.
+extern void parse_hex_bits(
+ const char *src_p, int dst_n, sc_digit *data_p, sc_digit *ctrl_p=0);
+
+// Find the base and sign of a number in v.
+extern const char *get_base_and_sign(
+ const char *v, small_type &base, small_type &sign);
+
+// Create a number out of v in base.
+extern small_type
+vec_from_str(int unb, int und, sc_digit *u,
+ const char *v, sc_numrep base=SC_NOBASE);
+
+
+// ----------------------------------------------------------------------------
+// Naming convention for the vec_ functions below:
+// vec_OP(u, v, w) : computes w = u OP v.
+// vec_OP_on(u, v) : computes u = u OP v if u has more digits than v.
+// vec_OP_on2(u, v) : computes u = u OP v if u has fewer digits than v.
+// _large : parameters are vectors.
+// _small : one of the parameters is a single digit.
+// Xlen : the number of digits in X.
+// ----------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------
+// Functions for vector addition: w = u + v or u += v.
+// ----------------------------------------------------------------------------
+
+extern void vec_add(int ulen, const sc_digit *u,
+ int vlen, const sc_digit *v, sc_digit *w);
+extern void vec_add_on(int ulen, sc_digit *u, int vlen, const sc_digit *v);
+extern void vec_add_on2(int ulen, sc_digit *u, int vlen, const sc_digit *v);
+extern void vec_add_small(int ulen, const sc_digit *u,
+ sc_digit v, sc_digit *w);
+extern void vec_add_small_on(int ulen, sc_digit *u, sc_digit v);
+
+// ----------------------------------------------------------------------------
+// Functions for vector subtraction: w = u - v, u -= v, or u = v - u.
+// ----------------------------------------------------------------------------
+
+extern void vec_sub(int ulen, const sc_digit *u,
+ int vlen, const sc_digit *v, sc_digit *w);
+extern void vec_sub_on(int ulen, sc_digit *u, int vlen, const sc_digit *v);
+extern void vec_sub_on2(int ulen, sc_digit *u, int vlen, const sc_digit *v);
+extern void vec_sub_small(int ulen, const sc_digit *u,
+ sc_digit v, sc_digit *w);
+extern void vec_sub_small_on(int ulen, sc_digit *u, sc_digit v);
+
+
+// ----------------------------------------------------------------------------
+// Functions for vector multiplication: w = u * v or u *= v.
+// ----------------------------------------------------------------------------
+
+extern void vec_mul(int ulen, const sc_digit *u,
+ int vlen, const sc_digit *v, sc_digit *w);
+extern void vec_mul_small(int ulen, const sc_digit *u,
+ sc_digit v, sc_digit *w);
+extern void vec_mul_small_on(int ulen, sc_digit *u, sc_digit v);
+
+
+// ----------------------------------------------------------------------------
+// Functions for vector division: w = u / v.
+// ----------------------------------------------------------------------------
+
+extern void vec_div_large(int ulen, const sc_digit *u,
+ int vlen, const sc_digit *v, sc_digit *w);
+extern void vec_div_small(int ulen, const sc_digit *u,
+ sc_digit v, sc_digit *w);
+
+
+// ----------------------------------------------------------------------------
+// Functions for vector remainder: w = u % v or u %= v.
+// ----------------------------------------------------------------------------
+
+extern void vec_rem_large(int ulen, const sc_digit *u,
+ int vlen, const sc_digit *v, sc_digit *w);
+extern sc_digit vec_rem_small(int ulen, const sc_digit *u, sc_digit v);
+extern sc_digit vec_rem_on_small(int ulen, sc_digit *u, sc_digit v);
+
+
+// ----------------------------------------------------------------------------
+// Functions to convert between vectors of char and sc_digit.
+// ----------------------------------------------------------------------------
+
+extern int vec_to_char(int ulen, const sc_digit *u, int vlen, uchar *v);
+extern void vec_from_char(int ulen, const uchar *u, int vlen, sc_digit *v);
+
+
+// ----------------------------------------------------------------------------
+// Functions to shift left or right, or to create a mirror image of vectors.
+// ----------------------------------------------------------------------------
+
+extern void vec_shift_left(int ulen, sc_digit *u, int nsl);
+extern void vec_shift_right(int vlen, sc_digit *u, int nsr, sc_digit fill=0);
+extern void vec_reverse(int unb, int und, sc_digit *ud, int l, int r=0);
+
+
+// ----------------------------------------------------------------------------
+// Various utility functions.
+// ----------------------------------------------------------------------------
+
+// Return the low half part of d.
+inline sc_digit low_half(sc_digit d) { return (d & HALF_DIGIT_MASK); }
+
+// Return the high half part of d. The high part of the digit may have
+// more bits than BITS_PER_HALF_DIGIT due to, e.g., overflow in the
+// multiplication. Hence, in other functions that use high_half(),
+// make sure that the result contains BITS_PER_HALF_DIGIT if
+// necessary. This is done by high_half_masked().
+inline sc_digit high_half(sc_digit d) { return (d >> BITS_PER_HALF_DIGIT); }
+inline sc_digit
+high_half_masked(sc_digit d)
+{
+ return (high_half(d) & HALF_DIGIT_MASK);
+}
+
+// Concatenate the high part h and low part l. Assumes that h and l
+// are less than or equal to HALF_DIGIT_MASK;
+inline sc_digit
+concat(sc_digit h, sc_digit l)
+{
+ return ((h << BITS_PER_HALF_DIGIT) | l);
+}
+
+// Create a number with n 1's.
+inline sc_digit
+one_and_ones(int n)
+{
+ return (((sc_digit) 1 << n) - 1);
+}
+
+// Create a number with one 1 and n 0's.
+inline sc_digit one_and_zeros(int n) { return ((sc_digit) 1 << n); }
+
+
+// ----------------------------------------------------------------------------
+
+// Find the digit that bit i is in.
+inline int digit_ord(int i) { return (i / BITS_PER_DIGIT); }
+
+// Find the bit in digit_ord(i) that bit i corressponds to.
+inline int bit_ord(int i) { return (i % BITS_PER_DIGIT); }
+
+
+// ----------------------------------------------------------------------------
+// Functions to compare, zero, complement vector(s).
+// ----------------------------------------------------------------------------
+
+// Compare u and v and return r
+// r = 0 if u == v
+// r < 0 if u < v
+// r > 0 if u > v
+// - Assume that all the leading zero digits are already skipped.
+// - ulen and/or vlen can be zero.
+// - Every digit is less than or equal to DIGIT_MASK;
+inline int
+vec_cmp(int ulen, const sc_digit *u,
+ int vlen, const sc_digit *v)
+{
+
+#ifdef DEBUG_SYSTEMC
+ // sc_assert((ulen <= 0) || (u != NULL));
+ // sc_assert((vlen <= 0) || (v != NULL));
+
+ // ulen and vlen can be equal to 0 because vec_cmp can be called
+ // after vec_skip_leading_zeros.
+ sc_assert((ulen >= 0) && (u != NULL));
+ sc_assert((vlen >= 0) && (v != NULL));
+ // If ulen > 0, then the leading digit of u must be non-zero.
+ sc_assert((ulen <= 0) || (u[ulen - 1] != 0));
+ sc_assert((vlen <= 0) || (v[vlen - 1] != 0));
+#endif
+
+ if (ulen != vlen)
+ return (ulen - vlen);
+
+ // ulen == vlen >= 1
+ while ((--ulen >= 0) && (u[ulen] == v[ulen]))
+ {}
+
+ if (ulen < 0)
+ return 0;
+
+#ifdef DEBUG_SYSTEMC
+ // Test to see if the result is wrong due to the presence of
+ // overflow bits.
+ sc_assert((u[ulen] & DIGIT_MASK) != (v[ulen] & DIGIT_MASK));
+#endif
+
+ return (int)(u[ulen] - v[ulen]);
+}
+
+// Find the index of the first non-zero digit.
+// - ulen (before) = the number of digits in u.
+// - the returned value = the index of the first non-zero digit.
+// A negative value of -1 indicates that every digit in u is zero.
+inline int
+vec_find_first_nonzero(int ulen, const sc_digit *u)
+{
+
+#ifdef DEBUG_SYSTEMC
+ // sc_assert((ulen <= 0) || (u != NULL));
+ sc_assert((ulen > 0) && (u != NULL));
+#endif
+
+ while ((--ulen >= 0) && (! u[ulen]))
+ {}
+
+ return ulen;
+}
+
+// Skip all the leading zero digits.
+// - ulen (before) = the number of digits in u.
+// - the returned value = the number of non-zero digits in u.
+// - the returned value is non-negative.
+inline int
+vec_skip_leading_zeros(int ulen, const sc_digit *u)
+{
+#ifdef DEBUG_SYSTEMC
+ // sc_assert((ulen <= 0) || (u != NULL));
+ sc_assert((ulen > 0) && (u != NULL));
+#endif
+
+ return (1 + vec_find_first_nonzero(ulen, u));
+}
+
+// Compare u and v and return r
+// r = 0 if u == v
+// r < 0 if u < v
+// r > 0 if u > v
+inline int
+vec_skip_and_cmp(int ulen, const sc_digit *u, int vlen, const sc_digit *v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+#endif
+
+ ulen = vec_skip_leading_zeros(ulen, u);
+ vlen = vec_skip_leading_zeros(vlen, v);
+ // ulen and/or vlen can be equal to zero here.
+ return vec_cmp(ulen, u, vlen, v);
+}
+
+// Set u[i] = 0 where i = from ... (ulen - 1).
+inline void
+vec_zero(int from, int ulen, sc_digit *u)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+#endif
+ for (int i = from; i < ulen; i++)
+ u[i] = 0;
+}
+
+// Set u[i] = 0 where i = 0 .. (ulen - 1).
+inline void vec_zero(int ulen, sc_digit *u) { vec_zero(0, ulen, u); }
+
+// Copy n digits from v to u.
+inline void
+vec_copy(int n, sc_digit *u, const sc_digit *v)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((n > 0) && (u != NULL) && (v != NULL));
+#endif
+ for (int i = 0; i < n; ++i)
+ u[i] = v[i];
+}
+
+// Copy v to u, where ulen >= vlen, and zero the rest of the digits in u.
+inline void
+vec_copy_and_zero(int ulen, sc_digit *u, int vlen, const sc_digit *v)
+{
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert((vlen > 0) && (v != NULL));
+ sc_assert(ulen >= vlen);
+#endif
+ vec_copy(vlen, u, v);
+ vec_zero(vlen, ulen, u);
+
+}
+
+// 2's-complement the digits in u.
+inline void
+vec_complement(int ulen, sc_digit *u)
+{
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert((ulen > 0) && (u != NULL));
+#endif
+
+ sc_digit carry = 1;
+
+ for (int i = 0; i < ulen; ++i) {
+ carry += (~u[i] & DIGIT_MASK);
+ u[i] = carry & DIGIT_MASK;
+ carry >>= BITS_PER_DIGIT;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// Functions to handle built-in types or signs.
+// ----------------------------------------------------------------------------
+
+// u = v
+// - v is an unsigned long or uint64, and positive integer.
+template<class Type>
+inline void
+from_uint(int ulen, sc_digit *u, Type v)
+{
+#ifdef DEBUG_SYSTEMC
+ // sc_assert((ulen <= 0) || (u != NULL));
+ sc_assert((ulen > 0) && (u != NULL));
+ sc_assert(v >= 0);
+#endif
+
+ int i = 0;
+
+ while (v && (i < ulen)) {
+ u[i++] = static_cast<sc_digit>(v & DIGIT_MASK);
+ v >>= BITS_PER_DIGIT;
+ }
+ vec_zero(i, ulen, u);
+}
+
+#ifndef __GNUC__
+# define SC_LIKELY_(x) !!(x)
+#else
+# define SC_LIKELY_(x) __builtin_expect(!!(x), 1)
+#endif
+
+// Get u's sign and return its absolute value.
+// u can be long, unsigned long, int64, or uint64.
+template<class Type>
+inline small_type
+get_sign(Type &u)
+{
+ if (u > 0)
+ return SC_POS;
+
+ if (u == 0)
+ return SC_ZERO;
+
+ // no positive number representable for minimum value,
+ // leave as is to avoid Undefined Behaviour
+ if (SC_LIKELY_(u > (std::numeric_limits<Type>::min)()))
+ u = -u;
+
+ return SC_NEG;
+}
+
+#undef SC_LIKELY_
+
+
+// Return us * vs:
+// - Return SC_ZERO if either sign is SC_ZERO.
+// - Return SC_POS if us == vs
+// - Return SC_NEG if us != vs.
+inline small_type
+mul_signs(small_type us, small_type vs)
+{
+ if ((us == SC_ZERO) || (vs == SC_ZERO))
+ return SC_ZERO;
+
+ if (us == vs)
+ return SC_POS;
+
+ return SC_NEG;
+}
+
+
+// ----------------------------------------------------------------------------
+// Functions to test for errors and print out error messages.
+// ----------------------------------------------------------------------------
+
+#ifdef SC_MAX_NBITS
+
+void test_bound_failed(int nb);
+
+inline void
+test_bound(int nb)
+{
+ if (nb > SC_MAX_NBITS) {
+ test_bound_failed(nb);
+ sc_core::sc_abort(); // can't recover from here
+ }
+}
+
+#endif
+
+template<class Type>
+inline void
+div_by_zero(Type s)
+{
+ if (s == 0) {
+ SC_REPORT_ERROR("operation failed",
+ "div_by_zero<Type>(Type) : division by zero");
+ sc_core::sc_abort(); // can't recover from here
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// Functions to check if a given vector is zero or make one.
+// ----------------------------------------------------------------------------
+
+// If u[i] is zero for every i = 0,..., ulen - 1, return SC_ZERO,
+// else return s.
+inline small_type
+check_for_zero(small_type s, int ulen, const sc_digit *u)
+{
+
+#ifdef DEBUG_SYSTEMC
+ // sc_assert(ulen >= 0);
+ sc_assert((ulen > 0) && (u != NULL));
+#endif
+
+ if (vec_find_first_nonzero(ulen, u) < 0)
+ return SC_ZERO;
+
+ return s;
+}
+
+// If u[i] is zero for every i = 0,..., ulen - 1, return true,
+// else return false.
+inline bool
+check_for_zero(int ulen, const sc_digit *u)
+{
+
+#ifdef DEBUG_SYSTEMC
+ // sc_assert(ulen >= 0);
+ sc_assert((ulen > 0) && (u != NULL));
+#endif
+
+ if (vec_find_first_nonzero(ulen, u) < 0)
+ return true;
+
+ return false;
+}
+
+inline small_type
+make_zero(int nd, sc_digit *d)
+{
+ vec_zero(nd, d);
+ return SC_ZERO;
+}
+
+
+// ----------------------------------------------------------------------------
+// Functions for both signed and unsigned numbers to convert sign-magnitude
+// (SM) and 2's complement (2C) representations.
+// added = 1 => for signed.
+// added = 0 => for unsigned.
+// IF_SC_SIGNED can be used as 'added'.
+// ----------------------------------------------------------------------------
+
+// Trim the extra leading bits of a signed or unsigned number.
+inline void
+trim(small_type added, int nb, int nd, sc_digit *d)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((nb > 0) && (nd > 0) && (d != NULL));
+#endif
+ d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + added);
+}
+
+// Convert an (un)signed number from sign-magnitude representation to
+// 2's complement representation and trim the extra bits.
+inline void
+convert_SM_to_2C_trimmed(small_type added,
+ small_type s, int nb, int nd, sc_digit *d)
+{
+ if (s == SC_NEG) {
+ vec_complement(nd, d);
+ trim(added, nb, nd, d);
+ }
+}
+
+// Convert an (un)signed number from sign-magnitude representation to
+// 2's complement representation but do not trim the extra bits.
+inline void
+convert_SM_to_2C(small_type s, int nd, sc_digit *d)
+{
+ if (s == SC_NEG)
+ vec_complement(nd, d);
+}
+
+
+// ----------------------------------------------------------------------------
+// Functions to convert between sign-magnitude (SM) and 2's complement
+// (2C) representations of signed numbers.
+// ----------------------------------------------------------------------------
+
+// Trim the extra leading bits off a signed number.
+inline void
+trim_signed(int nb, int nd, sc_digit *d)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((nb > 0) && (nd > 0) && (d != NULL));
+#endif
+ d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + 1);
+}
+
+// Convert a signed number from 2's complement representation to
+// sign-magnitude representation, and return its sign. nd is d's
+// actual size, without zeros eliminated.
+inline small_type
+convert_signed_2C_to_SM(int nb, int nd, sc_digit *d)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((nb > 0) && (nd > 0) && (d != NULL));
+#endif
+
+ small_type s;
+
+ int xnb = bit_ord(nb - 1) + 1;
+
+ // Test the sign bit.
+ if (d[nd - 1] & one_and_zeros(xnb - 1)) {
+ s = SC_NEG;
+ vec_complement(nd, d);
+ } else {
+ s = SC_POS;
+ }
+
+ // Trim the last digit.
+ d[nd - 1] &= one_and_ones(xnb);
+
+ // Check if the new number is zero.
+ if (s == SC_POS)
+ return check_for_zero(s, nd, d);
+
+ return s;
+}
+
+// Convert a signed number from sign-magnitude representation to 2's
+// complement representation, get its sign, convert back to
+// sign-magnitude representation, and return its sign. nd is d's
+// actual size, without zeros eliminated.
+inline small_type
+convert_signed_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d)
+{
+ convert_SM_to_2C(s, nd, d);
+ return convert_signed_2C_to_SM(nb, nd, d);
+}
+
+// Convert a signed number from sign-magnitude representation to 2's
+// complement representation and trim the extra bits.
+inline void
+convert_signed_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d)
+{
+ convert_SM_to_2C_trimmed(1, s, nb, nd, d);
+}
+
+// Convert a signed number from sign-magnitude representation to 2's
+// complement representation but do not trim the extra bits.
+inline void
+convert_signed_SM_to_2C(small_type s, int nd, sc_digit *d)
+{
+ convert_SM_to_2C(s, nd, d);
+}
+
+
+// ----------------------------------------------------------------------------
+// Functions to convert between sign-magnitude (SM) and 2's complement
+// (2C) representations of unsigned numbers.
+// ----------------------------------------------------------------------------
+
+// Trim the extra leading bits off an unsigned number.
+inline void
+trim_unsigned(int nb, int nd, sc_digit *d)
+{
+#ifdef DEBUG_SYSTEMC
+ sc_assert((nb > 0) && (nd > 0) && (d != NULL));
+#endif
+
+ d[nd - 1] &= one_and_ones(bit_ord(nb - 1));
+}
+
+// Convert an unsigned number from 2's complement representation to
+// sign-magnitude representation, and return its sign. nd is d's
+// actual size, without zeros eliminated.
+inline small_type
+convert_unsigned_2C_to_SM(int nb, int nd, sc_digit *d)
+{
+ trim_unsigned(nb, nd, d);
+ return check_for_zero(SC_POS, nd, d);
+}
+
+// Convert an unsigned number from sign-magnitude representation to
+// 2's complement representation, get its sign, convert back to
+// sign-magnitude representation, and return its sign. nd is d's
+// actual size, without zeros eliminated.
+inline small_type
+convert_unsigned_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d)
+{
+ convert_SM_to_2C(s, nd, d);
+ return convert_unsigned_2C_to_SM(nb, nd, d);
+}
+
+// Convert an unsigned number from sign-magnitude representation to
+// 2's complement representation and trim the extra bits.
+inline void
+convert_unsigned_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d)
+{
+ convert_SM_to_2C_trimmed(0, s, nb, nd, d);
+}
+
+// Convert an unsigned number from sign-magnitude representation to
+// 2's complement representation but do not trim the extra bits.
+inline void
+convert_unsigned_SM_to_2C(small_type s, int nd, sc_digit *d)
+{
+ convert_SM_to_2C(s, nd, d);
+}
+
+
+// ----------------------------------------------------------------------------
+// Functions to copy one (un)signed number to another.
+// ----------------------------------------------------------------------------
+
+// Copy v to u.
+inline void
+copy_digits_signed(small_type &us,
+ int unb, int und, sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+ if (und <= vnd) {
+ vec_copy(und, ud, vd);
+
+ if (unb <= vnb)
+ us = convert_signed_SM_to_2C_to_SM(us, unb, und, ud);
+ } else { // und > vnd
+ vec_copy_and_zero(und, ud, vnd, vd);
+ }
+}
+
+// Copy v to u.
+inline void
+copy_digits_unsigned(small_type &us,
+ int unb, int und, sc_digit *ud,
+ int /* vnb */, int vnd, const sc_digit *vd)
+{
+ if (und <= vnd)
+ vec_copy(und, ud, vd);
+ else // und > vnd
+ vec_copy_and_zero(und, ud, vnd, vd);
+
+ us = convert_unsigned_SM_to_2C_to_SM(us, unb, und, ud);
+}
+
+
+// ----------------------------------------------------------------------------
+// Faster set(i, v), without bound checking.
+// ----------------------------------------------------------------------------
+
+// A version of set(i, v) without bound checking.
+inline void
+safe_set(int i, bool v, sc_digit *d)
+{
+
+#ifdef DEBUG_SYSTEMC
+ sc_assert((i >= 0) && (d != NULL));
+#endif
+
+ int bit_num = bit_ord(i);
+ int digit_num = digit_ord(i);
+
+ if (v)
+ d[digit_num] |= one_and_zeros(bit_num);
+ else
+ d[digit_num] &= ~(one_and_zeros(bit_num));
+}
+
+
+// ----------------------------------------------------------------------------
+// Function to check if a double number is bad (NaN or infinite).
+// ----------------------------------------------------------------------------
+
+inline bool
+is_nan(double v)
+{
+ return std::numeric_limits<double>::has_quiet_NaN && (v != v);
+}
+
+inline bool
+is_inf(double v)
+{
+ return v == std::numeric_limits<double>::infinity() ||
+ v == -std::numeric_limits<double>::infinity();
+}
+
+inline void
+is_bad_double(double v)
+{
+ // Windows throws exception.
+ if (is_nan(v) || is_inf(v))
+ SC_REPORT_ERROR("value is not valid",
+ "is_bad_double(double v) : "
+ "v is not finite - NaN or Inf");
+}
+
+} // namespace sc_dt
+
+#endif // __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__