sc_nbutils.hh revision 12853
112853Sgabeblack@google.com/*****************************************************************************
212853Sgabeblack@google.com
312853Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412853Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
512853Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
612853Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
712853Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
812853Sgabeblack@google.com  License.  You may obtain a copy of the License at
912853Sgabeblack@google.com
1012853Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1112853Sgabeblack@google.com
1212853Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1312853Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1412853Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512853Sgabeblack@google.com  implied.  See the License for the specific language governing
1612853Sgabeblack@google.com  permissions and limitations under the License.
1712853Sgabeblack@google.com
1812853Sgabeblack@google.com *****************************************************************************/
1912853Sgabeblack@google.com
2012853Sgabeblack@google.com/*****************************************************************************
2112853Sgabeblack@google.com
2212853Sgabeblack@google.com  sc_nbutils.h -- External and friend functions for both sc_signed and
2312853Sgabeblack@google.com                  sc_unsigned classes.
2412853Sgabeblack@google.com
2512853Sgabeblack@google.com  Original Author: Ali Dasdan, Synopsys, Inc.
2612853Sgabeblack@google.com
2712853Sgabeblack@google.com *****************************************************************************/
2812853Sgabeblack@google.com
2912853Sgabeblack@google.com/*****************************************************************************
3012853Sgabeblack@google.com
3112853Sgabeblack@google.com  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
3212853Sgabeblack@google.com  changes you are making here.
3312853Sgabeblack@google.com
3412853Sgabeblack@google.com      Name, Affiliation, Date:
3512853Sgabeblack@google.com  Description of Modification:
3612853Sgabeblack@google.com
3712853Sgabeblack@google.com *****************************************************************************/
3812853Sgabeblack@google.com
3912853Sgabeblack@google.com// $Log: sc_nbutils.h,v $
4012853Sgabeblack@google.com// Revision 1.6  2011/09/08 16:12:15  acg
4112853Sgabeblack@google.com//  Philipp A. Hartmann: fix issue with Sun machines wrt real math libraries.
4212853Sgabeblack@google.com//
4312853Sgabeblack@google.com// Revision 1.5  2011/08/26 23:00:01  acg
4412853Sgabeblack@google.com//  Torsten Maehne: remove use of ieeefp.h.
4512853Sgabeblack@google.com//
4612853Sgabeblack@google.com// Revision 1.4  2011/08/15 16:43:24  acg
4712853Sgabeblack@google.com//  Torsten Maehne: changes to remove unused argument warnings.
4812853Sgabeblack@google.com//
4912853Sgabeblack@google.com// Revision 1.3  2011/02/18 20:19:15  acg
5012853Sgabeblack@google.com//  Andy Goodrich: updating Copyright notice.
5112853Sgabeblack@google.com//
5212853Sgabeblack@google.com// Revision 1.2  2010/09/06 16:35:48  acg
5312853Sgabeblack@google.com//  Andy Goodrich: changed i386 to __i386__ in ifdef's.
5412853Sgabeblack@google.com//
5512853Sgabeblack@google.com// Revision 1.1.1.1  2006/12/15 20:20:05  acg
5612853Sgabeblack@google.com// SystemC 2.3
5712853Sgabeblack@google.com//
5812853Sgabeblack@google.com// Revision 1.3  2006/01/13 18:49:32  acg
5912853Sgabeblack@google.com// Added $Log command so that CVS check in comments are reproduced in the
6012853Sgabeblack@google.com// source.
6112853Sgabeblack@google.com//
6212853Sgabeblack@google.com
6312853Sgabeblack@google.com#ifndef __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__
6412853Sgabeblack@google.com#define __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__
6512853Sgabeblack@google.com
6612853Sgabeblack@google.com#include <cmath>
6712853Sgabeblack@google.com#include <ios>
6812853Sgabeblack@google.com#include <limits>
6912853Sgabeblack@google.com#include <ostream>
7012853Sgabeblack@google.com
7112853Sgabeblack@google.com#include "../../utils/sc_report_handler.hh"
7212853Sgabeblack@google.com#include "sc_nbdefs.hh"
7312853Sgabeblack@google.com
7412853Sgabeblack@google.comnamespace sc_dt
7512853Sgabeblack@google.com{
7612853Sgabeblack@google.com
7712853Sgabeblack@google.com//-----------------------------------------------------------------------------
7812853Sgabeblack@google.com//"sc_io_base"
7912853Sgabeblack@google.com//
8012853Sgabeblack@google.com// This inline function returns the type of an i/o stream's base as a SystemC
8112853Sgabeblack@google.com// base designator.
8212853Sgabeblack@google.com//   stream_object = reference to the i/o stream whose base is to be returned.
8312853Sgabeblack@google.com//
8412853Sgabeblack@google.com//"sc_io_show_base"
8512853Sgabeblack@google.com//
8612853Sgabeblack@google.com// This inline function returns true if the base should be shown when a SystemC
8712853Sgabeblack@google.com// value is displayed via the supplied stream operator.
8812853Sgabeblack@google.com//   stream_object = reference to the i/o stream to return showbase value for.
8912853Sgabeblack@google.com//-----------------------------------------------------------------------------
9012853Sgabeblack@google.cominline sc_numrep
9112853Sgabeblack@google.comsc_io_base(::std::ostream &os, sc_numrep def_base)
9212853Sgabeblack@google.com{
9312853Sgabeblack@google.com    std::ios::fmtflags flags = os.flags() & std::ios::basefield;
9412853Sgabeblack@google.com    if (flags & ::std::ios::dec) return SC_DEC;
9512853Sgabeblack@google.com    if (flags & ::std::ios::hex) return SC_HEX;
9612853Sgabeblack@google.com    if (flags & ::std::ios::oct) return SC_OCT;
9712853Sgabeblack@google.com    return def_base;
9812853Sgabeblack@google.com}
9912853Sgabeblack@google.com
10012853Sgabeblack@google.cominline bool
10112853Sgabeblack@google.comsc_io_show_base(::std::ostream &os)
10212853Sgabeblack@google.com{
10312853Sgabeblack@google.com    return (os.flags() & ::std::ios::showbase) != 0;
10412853Sgabeblack@google.com}
10512853Sgabeblack@google.com
10612853Sgabeblack@google.comconst std::string to_string(sc_numrep);
10712853Sgabeblack@google.com
10812853Sgabeblack@google.cominline ::std::ostream &
10912853Sgabeblack@google.comoperator << (::std::ostream &os, sc_numrep numrep)
11012853Sgabeblack@google.com{
11112853Sgabeblack@google.com    os << to_string(numrep);
11212853Sgabeblack@google.com    return os;
11312853Sgabeblack@google.com}
11412853Sgabeblack@google.com
11512853Sgabeblack@google.com// ----------------------------------------------------------------------------
11612853Sgabeblack@google.com
11712853Sgabeblack@google.com// One transition of the FSM to find base and sign of a number.
11812853Sgabeblack@google.comextern small_type fsm_move(
11912853Sgabeblack@google.com        char c, small_type &b, small_type &s, small_type &state);
12012853Sgabeblack@google.com
12112853Sgabeblack@google.com// Parse a character string into its equivalent binary bits.
12212853Sgabeblack@google.comextern void parse_binary_bits(
12312853Sgabeblack@google.com        const char *src_p, int dst_n, sc_digit *data_p, sc_digit *ctrl_p=0);
12412853Sgabeblack@google.com
12512853Sgabeblack@google.com// Parse a character string into its equivalent hexadecimal bits.
12612853Sgabeblack@google.comextern void parse_hex_bits(
12712853Sgabeblack@google.com        const char *src_p, int dst_n, sc_digit *data_p, sc_digit *ctrl_p=0);
12812853Sgabeblack@google.com
12912853Sgabeblack@google.com// Find the base and sign of a number in v.
13012853Sgabeblack@google.comextern const char *get_base_and_sign(
13112853Sgabeblack@google.com        const char *v, small_type &base, small_type &sign);
13212853Sgabeblack@google.com
13312853Sgabeblack@google.com// Create a number out of v in base.
13412853Sgabeblack@google.comextern small_type
13512853Sgabeblack@google.comvec_from_str(int unb, int und, sc_digit *u,
13612853Sgabeblack@google.com             const char *v, sc_numrep base=SC_NOBASE);
13712853Sgabeblack@google.com
13812853Sgabeblack@google.com
13912853Sgabeblack@google.com// ----------------------------------------------------------------------------
14012853Sgabeblack@google.com//  Naming convention for the vec_ functions below:
14112853Sgabeblack@google.com//    vec_OP(u, v, w)  : computes w = u OP v.
14212853Sgabeblack@google.com//    vec_OP_on(u, v)  : computes u = u OP v if u has more digits than v.
14312853Sgabeblack@google.com//    vec_OP_on2(u, v) : computes u = u OP v if u has fewer digits than v.
14412853Sgabeblack@google.com//    _large           : parameters are vectors.
14512853Sgabeblack@google.com//    _small           : one of the parameters is a single digit.
14612853Sgabeblack@google.com//    Xlen             : the number of digits in X.
14712853Sgabeblack@google.com// ----------------------------------------------------------------------------
14812853Sgabeblack@google.com
14912853Sgabeblack@google.com// ----------------------------------------------------------------------------
15012853Sgabeblack@google.com//  Functions for vector addition: w = u + v or u += v.
15112853Sgabeblack@google.com// ----------------------------------------------------------------------------
15212853Sgabeblack@google.com
15312853Sgabeblack@google.comextern void vec_add(int ulen, const sc_digit *u,
15412853Sgabeblack@google.com                    int vlen, const sc_digit *v, sc_digit *w);
15512853Sgabeblack@google.comextern void vec_add_on(int ulen, sc_digit *u, int vlen, const sc_digit *v);
15612853Sgabeblack@google.comextern void vec_add_on2(int ulen, sc_digit *u, int vlen, const sc_digit *v);
15712853Sgabeblack@google.comextern void vec_add_small(int ulen, const sc_digit *u,
15812853Sgabeblack@google.com                          sc_digit v, sc_digit *w);
15912853Sgabeblack@google.comextern void vec_add_small_on(int ulen, sc_digit *u, sc_digit v);
16012853Sgabeblack@google.com
16112853Sgabeblack@google.com// ----------------------------------------------------------------------------
16212853Sgabeblack@google.com//  Functions for vector subtraction: w = u - v, u -= v, or u = v - u.
16312853Sgabeblack@google.com// ----------------------------------------------------------------------------
16412853Sgabeblack@google.com
16512853Sgabeblack@google.comextern void vec_sub(int ulen, const sc_digit *u,
16612853Sgabeblack@google.com                    int vlen, const sc_digit *v, sc_digit *w);
16712853Sgabeblack@google.comextern void vec_sub_on(int ulen, sc_digit *u, int vlen, const sc_digit *v);
16812853Sgabeblack@google.comextern void vec_sub_on2(int ulen, sc_digit *u, int vlen, const sc_digit *v);
16912853Sgabeblack@google.comextern void vec_sub_small(int ulen, const sc_digit *u,
17012853Sgabeblack@google.com                          sc_digit v, sc_digit *w);
17112853Sgabeblack@google.comextern void vec_sub_small_on(int ulen, sc_digit *u, sc_digit v);
17212853Sgabeblack@google.com
17312853Sgabeblack@google.com
17412853Sgabeblack@google.com// ----------------------------------------------------------------------------
17512853Sgabeblack@google.com//  Functions for vector multiplication: w = u * v or u *= v.
17612853Sgabeblack@google.com// ----------------------------------------------------------------------------
17712853Sgabeblack@google.com
17812853Sgabeblack@google.comextern void vec_mul(int ulen, const sc_digit *u,
17912853Sgabeblack@google.com                    int vlen, const sc_digit *v, sc_digit *w);
18012853Sgabeblack@google.comextern void vec_mul_small(int ulen, const sc_digit *u,
18112853Sgabeblack@google.com                          sc_digit v, sc_digit *w);
18212853Sgabeblack@google.comextern void vec_mul_small_on(int ulen, sc_digit *u, sc_digit v);
18312853Sgabeblack@google.com
18412853Sgabeblack@google.com
18512853Sgabeblack@google.com// ----------------------------------------------------------------------------
18612853Sgabeblack@google.com//  Functions for vector division: w = u / v.
18712853Sgabeblack@google.com// ----------------------------------------------------------------------------
18812853Sgabeblack@google.com
18912853Sgabeblack@google.comextern void vec_div_large(int ulen, const sc_digit *u,
19012853Sgabeblack@google.com                          int vlen, const sc_digit *v, sc_digit *w);
19112853Sgabeblack@google.comextern void vec_div_small(int ulen, const sc_digit *u,
19212853Sgabeblack@google.com                          sc_digit v, sc_digit *w);
19312853Sgabeblack@google.com
19412853Sgabeblack@google.com
19512853Sgabeblack@google.com// ----------------------------------------------------------------------------
19612853Sgabeblack@google.com//  Functions for vector remainder: w = u % v or u %= v.
19712853Sgabeblack@google.com// ----------------------------------------------------------------------------
19812853Sgabeblack@google.com
19912853Sgabeblack@google.comextern void vec_rem_large(int ulen, const sc_digit *u,
20012853Sgabeblack@google.com                          int vlen, const sc_digit *v, sc_digit *w);
20112853Sgabeblack@google.comextern sc_digit vec_rem_small(int ulen, const sc_digit *u, sc_digit v);
20212853Sgabeblack@google.comextern sc_digit vec_rem_on_small(int ulen, sc_digit *u, sc_digit v);
20312853Sgabeblack@google.com
20412853Sgabeblack@google.com
20512853Sgabeblack@google.com// ----------------------------------------------------------------------------
20612853Sgabeblack@google.com//  Functions to convert between vectors of char and sc_digit.
20712853Sgabeblack@google.com// ----------------------------------------------------------------------------
20812853Sgabeblack@google.com
20912853Sgabeblack@google.comextern int vec_to_char(int ulen, const sc_digit *u, int vlen, uchar *v);
21012853Sgabeblack@google.comextern void vec_from_char(int ulen, const uchar *u, int vlen, sc_digit *v);
21112853Sgabeblack@google.com
21212853Sgabeblack@google.com
21312853Sgabeblack@google.com// ----------------------------------------------------------------------------
21412853Sgabeblack@google.com//  Functions to shift left or right, or to create a mirror image of vectors.
21512853Sgabeblack@google.com// ----------------------------------------------------------------------------
21612853Sgabeblack@google.com
21712853Sgabeblack@google.comextern void vec_shift_left(int ulen, sc_digit *u, int nsl);
21812853Sgabeblack@google.comextern void vec_shift_right(int vlen, sc_digit *u, int nsr, sc_digit fill=0);
21912853Sgabeblack@google.comextern void vec_reverse(int unb, int und, sc_digit *ud, int l, int r=0);
22012853Sgabeblack@google.com
22112853Sgabeblack@google.com
22212853Sgabeblack@google.com// ----------------------------------------------------------------------------
22312853Sgabeblack@google.com//  Various utility functions.
22412853Sgabeblack@google.com// ----------------------------------------------------------------------------
22512853Sgabeblack@google.com
22612853Sgabeblack@google.com// Return the low half part of d.
22712853Sgabeblack@google.cominline sc_digit low_half(sc_digit d) { return (d & HALF_DIGIT_MASK); }
22812853Sgabeblack@google.com
22912853Sgabeblack@google.com// Return the high half part of d. The high part of the digit may have
23012853Sgabeblack@google.com// more bits than BITS_PER_HALF_DIGIT due to, e.g., overflow in the
23112853Sgabeblack@google.com// multiplication. Hence, in other functions that use high_half(),
23212853Sgabeblack@google.com// make sure that the result contains BITS_PER_HALF_DIGIT if
23312853Sgabeblack@google.com// necessary. This is done by high_half_masked().
23412853Sgabeblack@google.cominline sc_digit high_half(sc_digit d) { return (d >> BITS_PER_HALF_DIGIT); }
23512853Sgabeblack@google.cominline sc_digit
23612853Sgabeblack@google.comhigh_half_masked(sc_digit d)
23712853Sgabeblack@google.com{
23812853Sgabeblack@google.com    return (high_half(d) & HALF_DIGIT_MASK);
23912853Sgabeblack@google.com}
24012853Sgabeblack@google.com
24112853Sgabeblack@google.com// Concatenate the high part h and low part l. Assumes that h and l
24212853Sgabeblack@google.com// are less than or equal to HALF_DIGIT_MASK;
24312853Sgabeblack@google.cominline sc_digit
24412853Sgabeblack@google.comconcat(sc_digit h, sc_digit l)
24512853Sgabeblack@google.com{
24612853Sgabeblack@google.com    return ((h << BITS_PER_HALF_DIGIT) | l);
24712853Sgabeblack@google.com}
24812853Sgabeblack@google.com
24912853Sgabeblack@google.com// Create a number with n 1's.
25012853Sgabeblack@google.cominline sc_digit
25112853Sgabeblack@google.comone_and_ones(int n)
25212853Sgabeblack@google.com{
25312853Sgabeblack@google.com    return (((sc_digit) 1 << n) - 1);
25412853Sgabeblack@google.com}
25512853Sgabeblack@google.com
25612853Sgabeblack@google.com// Create a number with one 1 and n 0's.
25712853Sgabeblack@google.cominline sc_digit one_and_zeros(int n) { return ((sc_digit) 1 << n); }
25812853Sgabeblack@google.com
25912853Sgabeblack@google.com
26012853Sgabeblack@google.com// ----------------------------------------------------------------------------
26112853Sgabeblack@google.com
26212853Sgabeblack@google.com// Find the digit that bit i is in.
26312853Sgabeblack@google.cominline int digit_ord(int i) { return (i / BITS_PER_DIGIT); }
26412853Sgabeblack@google.com
26512853Sgabeblack@google.com// Find the bit in digit_ord(i) that bit i corressponds to.
26612853Sgabeblack@google.cominline int bit_ord(int i) { return (i % BITS_PER_DIGIT); }
26712853Sgabeblack@google.com
26812853Sgabeblack@google.com
26912853Sgabeblack@google.com// ----------------------------------------------------------------------------
27012853Sgabeblack@google.com//  Functions to compare, zero, complement vector(s).
27112853Sgabeblack@google.com// ----------------------------------------------------------------------------
27212853Sgabeblack@google.com
27312853Sgabeblack@google.com// Compare u and v and return r
27412853Sgabeblack@google.com//  r = 0 if u == v
27512853Sgabeblack@google.com//  r < 0 if u < v
27612853Sgabeblack@google.com//  r > 0 if u > v
27712853Sgabeblack@google.com// - Assume that all the leading zero digits are already skipped.
27812853Sgabeblack@google.com// - ulen and/or vlen can be zero.
27912853Sgabeblack@google.com// - Every digit is less than or equal to DIGIT_MASK;
28012853Sgabeblack@google.cominline int
28112853Sgabeblack@google.comvec_cmp(int ulen, const sc_digit *u,
28212853Sgabeblack@google.com        int vlen, const sc_digit *v)
28312853Sgabeblack@google.com{
28412853Sgabeblack@google.com
28512853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
28612853Sgabeblack@google.com    // sc_assert((ulen <= 0) || (u != NULL));
28712853Sgabeblack@google.com    // sc_assert((vlen <= 0) || (v != NULL));
28812853Sgabeblack@google.com
28912853Sgabeblack@google.com    // ulen and vlen can be equal to 0 because vec_cmp can be called
29012853Sgabeblack@google.com    // after vec_skip_leading_zeros.
29112853Sgabeblack@google.com    sc_assert((ulen >= 0) && (u != NULL));
29212853Sgabeblack@google.com    sc_assert((vlen >= 0) && (v != NULL));
29312853Sgabeblack@google.com    // If ulen > 0, then the leading digit of u must be non-zero.
29412853Sgabeblack@google.com    sc_assert((ulen <= 0) || (u[ulen - 1] != 0));
29512853Sgabeblack@google.com    sc_assert((vlen <= 0) || (v[vlen - 1] != 0));
29612853Sgabeblack@google.com#endif
29712853Sgabeblack@google.com
29812853Sgabeblack@google.com    if (ulen != vlen)
29912853Sgabeblack@google.com        return (ulen - vlen);
30012853Sgabeblack@google.com
30112853Sgabeblack@google.com    // ulen == vlen >= 1
30212853Sgabeblack@google.com    while ((--ulen >= 0) && (u[ulen] == v[ulen]))
30312853Sgabeblack@google.com    {}
30412853Sgabeblack@google.com
30512853Sgabeblack@google.com    if (ulen < 0)
30612853Sgabeblack@google.com        return 0;
30712853Sgabeblack@google.com
30812853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
30912853Sgabeblack@google.com    // Test to see if the result is wrong due to the presence of
31012853Sgabeblack@google.com    // overflow bits.
31112853Sgabeblack@google.com    sc_assert((u[ulen] & DIGIT_MASK) != (v[ulen] & DIGIT_MASK));
31212853Sgabeblack@google.com#endif
31312853Sgabeblack@google.com
31412853Sgabeblack@google.com    return (int)(u[ulen] - v[ulen]);
31512853Sgabeblack@google.com}
31612853Sgabeblack@google.com
31712853Sgabeblack@google.com// Find the index of the first non-zero digit.
31812853Sgabeblack@google.com// - ulen (before) = the number of digits in u.
31912853Sgabeblack@google.com// - the returned value = the index of the first non-zero digit.
32012853Sgabeblack@google.com// A negative value of -1 indicates that every digit in u is zero.
32112853Sgabeblack@google.cominline int
32212853Sgabeblack@google.comvec_find_first_nonzero(int ulen, const sc_digit *u)
32312853Sgabeblack@google.com{
32412853Sgabeblack@google.com
32512853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
32612853Sgabeblack@google.com    // sc_assert((ulen <= 0) || (u != NULL));
32712853Sgabeblack@google.com    sc_assert((ulen > 0) && (u != NULL));
32812853Sgabeblack@google.com#endif
32912853Sgabeblack@google.com
33012853Sgabeblack@google.com    while ((--ulen >= 0) && (! u[ulen]))
33112853Sgabeblack@google.com    {}
33212853Sgabeblack@google.com
33312853Sgabeblack@google.com    return ulen;
33412853Sgabeblack@google.com}
33512853Sgabeblack@google.com
33612853Sgabeblack@google.com// Skip all the leading zero digits.
33712853Sgabeblack@google.com// - ulen (before) = the number of digits in u.
33812853Sgabeblack@google.com// - the returned value = the number of non-zero digits in u.
33912853Sgabeblack@google.com// - the returned value is non-negative.
34012853Sgabeblack@google.cominline int
34112853Sgabeblack@google.comvec_skip_leading_zeros(int ulen, const sc_digit *u)
34212853Sgabeblack@google.com{
34312853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
34412853Sgabeblack@google.com    // sc_assert((ulen <= 0) || (u != NULL));
34512853Sgabeblack@google.com    sc_assert((ulen > 0) && (u != NULL));
34612853Sgabeblack@google.com#endif
34712853Sgabeblack@google.com
34812853Sgabeblack@google.com    return (1 + vec_find_first_nonzero(ulen, u));
34912853Sgabeblack@google.com}
35012853Sgabeblack@google.com
35112853Sgabeblack@google.com// Compare u and v and return r
35212853Sgabeblack@google.com//  r = 0 if u == v
35312853Sgabeblack@google.com//  r < 0 if u < v
35412853Sgabeblack@google.com//  r > 0 if u > v
35512853Sgabeblack@google.cominline int
35612853Sgabeblack@google.comvec_skip_and_cmp(int ulen, const sc_digit *u, int vlen, const sc_digit *v)
35712853Sgabeblack@google.com{
35812853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
35912853Sgabeblack@google.com    sc_assert((ulen > 0) && (u != NULL));
36012853Sgabeblack@google.com    sc_assert((vlen > 0) && (v != NULL));
36112853Sgabeblack@google.com#endif
36212853Sgabeblack@google.com
36312853Sgabeblack@google.com    ulen = vec_skip_leading_zeros(ulen, u);
36412853Sgabeblack@google.com    vlen = vec_skip_leading_zeros(vlen, v);
36512853Sgabeblack@google.com    // ulen and/or vlen can be equal to zero here.
36612853Sgabeblack@google.com    return vec_cmp(ulen, u, vlen, v);
36712853Sgabeblack@google.com}
36812853Sgabeblack@google.com
36912853Sgabeblack@google.com// Set u[i] = 0 where i = from ... (ulen - 1).
37012853Sgabeblack@google.cominline void
37112853Sgabeblack@google.comvec_zero(int from, int ulen, sc_digit *u)
37212853Sgabeblack@google.com{
37312853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
37412853Sgabeblack@google.com    sc_assert((ulen > 0) && (u != NULL));
37512853Sgabeblack@google.com#endif
37612853Sgabeblack@google.com    for (int i = from; i < ulen; i++)
37712853Sgabeblack@google.com        u[i] = 0;
37812853Sgabeblack@google.com}
37912853Sgabeblack@google.com
38012853Sgabeblack@google.com// Set u[i] = 0 where i = 0 .. (ulen - 1).
38112853Sgabeblack@google.cominline void vec_zero(int ulen, sc_digit *u) { vec_zero(0, ulen, u); }
38212853Sgabeblack@google.com
38312853Sgabeblack@google.com// Copy n digits from v to u.
38412853Sgabeblack@google.cominline void
38512853Sgabeblack@google.comvec_copy(int n, sc_digit *u, const sc_digit *v)
38612853Sgabeblack@google.com{
38712853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
38812853Sgabeblack@google.com    sc_assert((n > 0) && (u != NULL) && (v != NULL));
38912853Sgabeblack@google.com#endif
39012853Sgabeblack@google.com    for (int i = 0; i < n; ++i)
39112853Sgabeblack@google.com        u[i] = v[i];
39212853Sgabeblack@google.com}
39312853Sgabeblack@google.com
39412853Sgabeblack@google.com// Copy v to u, where ulen >= vlen, and zero the rest of the digits in u.
39512853Sgabeblack@google.cominline void
39612853Sgabeblack@google.comvec_copy_and_zero(int ulen, sc_digit *u, int vlen, const sc_digit *v)
39712853Sgabeblack@google.com{
39812853Sgabeblack@google.com
39912853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
40012853Sgabeblack@google.com    sc_assert((ulen > 0) && (u != NULL));
40112853Sgabeblack@google.com    sc_assert((vlen > 0) && (v != NULL));
40212853Sgabeblack@google.com    sc_assert(ulen >= vlen);
40312853Sgabeblack@google.com#endif
40412853Sgabeblack@google.com    vec_copy(vlen, u, v);
40512853Sgabeblack@google.com    vec_zero(vlen, ulen, u);
40612853Sgabeblack@google.com
40712853Sgabeblack@google.com}
40812853Sgabeblack@google.com
40912853Sgabeblack@google.com// 2's-complement the digits in u.
41012853Sgabeblack@google.cominline void
41112853Sgabeblack@google.comvec_complement(int ulen, sc_digit *u)
41212853Sgabeblack@google.com{
41312853Sgabeblack@google.com
41412853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
41512853Sgabeblack@google.com    sc_assert((ulen > 0) && (u != NULL));
41612853Sgabeblack@google.com#endif
41712853Sgabeblack@google.com
41812853Sgabeblack@google.com    sc_digit carry = 1;
41912853Sgabeblack@google.com
42012853Sgabeblack@google.com    for (int i = 0; i < ulen; ++i) {
42112853Sgabeblack@google.com        carry += (~u[i] & DIGIT_MASK);
42212853Sgabeblack@google.com        u[i] = carry & DIGIT_MASK;
42312853Sgabeblack@google.com        carry >>= BITS_PER_DIGIT;
42412853Sgabeblack@google.com    }
42512853Sgabeblack@google.com}
42612853Sgabeblack@google.com
42712853Sgabeblack@google.com
42812853Sgabeblack@google.com// ----------------------------------------------------------------------------
42912853Sgabeblack@google.com//  Functions to handle built-in types or signs.
43012853Sgabeblack@google.com// ----------------------------------------------------------------------------
43112853Sgabeblack@google.com
43212853Sgabeblack@google.com// u = v
43312853Sgabeblack@google.com// - v is an unsigned long or uint64, and positive integer.
43412853Sgabeblack@google.comtemplate<class Type>
43512853Sgabeblack@google.cominline void
43612853Sgabeblack@google.comfrom_uint(int ulen, sc_digit *u, Type v)
43712853Sgabeblack@google.com{
43812853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
43912853Sgabeblack@google.com    // sc_assert((ulen <= 0) || (u != NULL));
44012853Sgabeblack@google.com    sc_assert((ulen > 0) && (u != NULL));
44112853Sgabeblack@google.com    sc_assert(v >= 0);
44212853Sgabeblack@google.com#endif
44312853Sgabeblack@google.com
44412853Sgabeblack@google.com    int i = 0;
44512853Sgabeblack@google.com
44612853Sgabeblack@google.com    while (v && (i < ulen)) {
44712853Sgabeblack@google.com        u[i++] = static_cast<sc_digit>(v & DIGIT_MASK);
44812853Sgabeblack@google.com        v >>= BITS_PER_DIGIT;
44912853Sgabeblack@google.com    }
45012853Sgabeblack@google.com    vec_zero(i, ulen, u);
45112853Sgabeblack@google.com}
45212853Sgabeblack@google.com
45312853Sgabeblack@google.com#ifndef __GNUC__
45412853Sgabeblack@google.com#  define SC_LIKELY_(x) !!(x)
45512853Sgabeblack@google.com#else
45612853Sgabeblack@google.com#  define SC_LIKELY_(x) __builtin_expect(!!(x), 1)
45712853Sgabeblack@google.com#endif
45812853Sgabeblack@google.com
45912853Sgabeblack@google.com// Get u's sign and return its absolute value.
46012853Sgabeblack@google.com// u can be long, unsigned long, int64, or uint64.
46112853Sgabeblack@google.comtemplate<class Type>
46212853Sgabeblack@google.cominline small_type
46312853Sgabeblack@google.comget_sign(Type &u)
46412853Sgabeblack@google.com{
46512853Sgabeblack@google.com    if (u > 0)
46612853Sgabeblack@google.com        return SC_POS;
46712853Sgabeblack@google.com
46812853Sgabeblack@google.com    if (u == 0)
46912853Sgabeblack@google.com        return SC_ZERO;
47012853Sgabeblack@google.com
47112853Sgabeblack@google.com    // no positive number representable for minimum value,
47212853Sgabeblack@google.com    // leave as is to avoid Undefined Behaviour
47312853Sgabeblack@google.com    if (SC_LIKELY_(u > (std::numeric_limits<Type>::min)()))
47412853Sgabeblack@google.com        u = -u;
47512853Sgabeblack@google.com
47612853Sgabeblack@google.com    return SC_NEG;
47712853Sgabeblack@google.com}
47812853Sgabeblack@google.com
47912853Sgabeblack@google.com#undef SC_LIKELY_
48012853Sgabeblack@google.com
48112853Sgabeblack@google.com
48212853Sgabeblack@google.com// Return us * vs:
48312853Sgabeblack@google.com// - Return SC_ZERO if either sign is SC_ZERO.
48412853Sgabeblack@google.com// - Return SC_POS if us == vs
48512853Sgabeblack@google.com// - Return SC_NEG if us != vs.
48612853Sgabeblack@google.cominline small_type
48712853Sgabeblack@google.commul_signs(small_type us, small_type vs)
48812853Sgabeblack@google.com{
48912853Sgabeblack@google.com    if ((us == SC_ZERO) || (vs == SC_ZERO))
49012853Sgabeblack@google.com        return SC_ZERO;
49112853Sgabeblack@google.com
49212853Sgabeblack@google.com    if (us == vs)
49312853Sgabeblack@google.com        return SC_POS;
49412853Sgabeblack@google.com
49512853Sgabeblack@google.com    return SC_NEG;
49612853Sgabeblack@google.com}
49712853Sgabeblack@google.com
49812853Sgabeblack@google.com
49912853Sgabeblack@google.com// ----------------------------------------------------------------------------
50012853Sgabeblack@google.com//  Functions to test for errors and print out error messages.
50112853Sgabeblack@google.com// ----------------------------------------------------------------------------
50212853Sgabeblack@google.com
50312853Sgabeblack@google.com#ifdef SC_MAX_NBITS
50412853Sgabeblack@google.com
50512853Sgabeblack@google.comvoid test_bound_failed(int nb);
50612853Sgabeblack@google.com
50712853Sgabeblack@google.cominline void
50812853Sgabeblack@google.comtest_bound(int nb)
50912853Sgabeblack@google.com{
51012853Sgabeblack@google.com    if (nb > SC_MAX_NBITS) {
51112853Sgabeblack@google.com        test_bound_failed(nb);
51212853Sgabeblack@google.com        sc_core::sc_abort(); // can't recover from here
51312853Sgabeblack@google.com    }
51412853Sgabeblack@google.com}
51512853Sgabeblack@google.com
51612853Sgabeblack@google.com#endif
51712853Sgabeblack@google.com
51812853Sgabeblack@google.comtemplate<class Type>
51912853Sgabeblack@google.cominline void
52012853Sgabeblack@google.comdiv_by_zero(Type s)
52112853Sgabeblack@google.com{
52212853Sgabeblack@google.com    if (s == 0) {
52312853Sgabeblack@google.com        SC_REPORT_ERROR("operation failed",
52412853Sgabeblack@google.com                        "div_by_zero<Type>(Type) : division by zero");
52512853Sgabeblack@google.com        sc_core::sc_abort(); // can't recover from here
52612853Sgabeblack@google.com    }
52712853Sgabeblack@google.com}
52812853Sgabeblack@google.com
52912853Sgabeblack@google.com
53012853Sgabeblack@google.com// ----------------------------------------------------------------------------
53112853Sgabeblack@google.com//  Functions to check if a given vector is zero or make one.
53212853Sgabeblack@google.com// ----------------------------------------------------------------------------
53312853Sgabeblack@google.com
53412853Sgabeblack@google.com// If u[i] is zero for every i = 0,..., ulen - 1, return SC_ZERO,
53512853Sgabeblack@google.com// else return s.
53612853Sgabeblack@google.cominline small_type
53712853Sgabeblack@google.comcheck_for_zero(small_type s, int ulen, const sc_digit *u)
53812853Sgabeblack@google.com{
53912853Sgabeblack@google.com
54012853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
54112853Sgabeblack@google.com    // sc_assert(ulen >= 0);
54212853Sgabeblack@google.com    sc_assert((ulen > 0) && (u != NULL));
54312853Sgabeblack@google.com#endif
54412853Sgabeblack@google.com
54512853Sgabeblack@google.com    if (vec_find_first_nonzero(ulen, u) < 0)
54612853Sgabeblack@google.com        return SC_ZERO;
54712853Sgabeblack@google.com
54812853Sgabeblack@google.com    return s;
54912853Sgabeblack@google.com}
55012853Sgabeblack@google.com
55112853Sgabeblack@google.com// If u[i] is zero for every i = 0,..., ulen - 1, return true,
55212853Sgabeblack@google.com// else return false.
55312853Sgabeblack@google.cominline bool
55412853Sgabeblack@google.comcheck_for_zero(int ulen, const sc_digit *u)
55512853Sgabeblack@google.com{
55612853Sgabeblack@google.com
55712853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
55812853Sgabeblack@google.com    // sc_assert(ulen >= 0);
55912853Sgabeblack@google.com    sc_assert((ulen > 0) && (u != NULL));
56012853Sgabeblack@google.com#endif
56112853Sgabeblack@google.com
56212853Sgabeblack@google.com    if (vec_find_first_nonzero(ulen, u) < 0)
56312853Sgabeblack@google.com        return true;
56412853Sgabeblack@google.com
56512853Sgabeblack@google.com    return false;
56612853Sgabeblack@google.com}
56712853Sgabeblack@google.com
56812853Sgabeblack@google.cominline small_type
56912853Sgabeblack@google.commake_zero(int nd, sc_digit *d)
57012853Sgabeblack@google.com{
57112853Sgabeblack@google.com    vec_zero(nd, d);
57212853Sgabeblack@google.com    return SC_ZERO;
57312853Sgabeblack@google.com}
57412853Sgabeblack@google.com
57512853Sgabeblack@google.com
57612853Sgabeblack@google.com// ----------------------------------------------------------------------------
57712853Sgabeblack@google.com//  Functions for both signed and unsigned numbers to convert sign-magnitude
57812853Sgabeblack@google.com//  (SM) and 2's complement (2C) representations.
57912853Sgabeblack@google.com//  added = 1 => for signed.
58012853Sgabeblack@google.com//  added = 0 => for unsigned.
58112853Sgabeblack@google.com//  IF_SC_SIGNED can be used as 'added'.
58212853Sgabeblack@google.com// ----------------------------------------------------------------------------
58312853Sgabeblack@google.com
58412853Sgabeblack@google.com// Trim the extra leading bits of a signed or unsigned number.
58512853Sgabeblack@google.cominline void
58612853Sgabeblack@google.comtrim(small_type added, int nb, int nd, sc_digit *d)
58712853Sgabeblack@google.com{
58812853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
58912853Sgabeblack@google.com    sc_assert((nb > 0) && (nd > 0) && (d != NULL));
59012853Sgabeblack@google.com#endif
59112853Sgabeblack@google.com    d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + added);
59212853Sgabeblack@google.com}
59312853Sgabeblack@google.com
59412853Sgabeblack@google.com// Convert an (un)signed number from sign-magnitude representation to
59512853Sgabeblack@google.com// 2's complement representation and trim the extra bits.
59612853Sgabeblack@google.cominline void
59712853Sgabeblack@google.comconvert_SM_to_2C_trimmed(small_type added,
59812853Sgabeblack@google.com                         small_type s, int nb, int nd, sc_digit *d)
59912853Sgabeblack@google.com{
60012853Sgabeblack@google.com    if (s == SC_NEG) {
60112853Sgabeblack@google.com        vec_complement(nd, d);
60212853Sgabeblack@google.com        trim(added, nb, nd, d);
60312853Sgabeblack@google.com    }
60412853Sgabeblack@google.com}
60512853Sgabeblack@google.com
60612853Sgabeblack@google.com// Convert an (un)signed number from sign-magnitude representation to
60712853Sgabeblack@google.com// 2's complement representation but do not trim the extra bits.
60812853Sgabeblack@google.cominline void
60912853Sgabeblack@google.comconvert_SM_to_2C(small_type s, int nd, sc_digit *d)
61012853Sgabeblack@google.com{
61112853Sgabeblack@google.com    if (s == SC_NEG)
61212853Sgabeblack@google.com        vec_complement(nd, d);
61312853Sgabeblack@google.com}
61412853Sgabeblack@google.com
61512853Sgabeblack@google.com
61612853Sgabeblack@google.com// ----------------------------------------------------------------------------
61712853Sgabeblack@google.com//  Functions to convert between sign-magnitude (SM) and 2's complement
61812853Sgabeblack@google.com//  (2C) representations of signed numbers.
61912853Sgabeblack@google.com// ----------------------------------------------------------------------------
62012853Sgabeblack@google.com
62112853Sgabeblack@google.com// Trim the extra leading bits off a signed number.
62212853Sgabeblack@google.cominline void
62312853Sgabeblack@google.comtrim_signed(int nb, int nd, sc_digit *d)
62412853Sgabeblack@google.com{
62512853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
62612853Sgabeblack@google.com    sc_assert((nb > 0) && (nd > 0) && (d != NULL));
62712853Sgabeblack@google.com#endif
62812853Sgabeblack@google.com    d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + 1);
62912853Sgabeblack@google.com}
63012853Sgabeblack@google.com
63112853Sgabeblack@google.com// Convert a signed number from 2's complement representation to
63212853Sgabeblack@google.com// sign-magnitude representation, and return its sign. nd is d's
63312853Sgabeblack@google.com// actual size, without zeros eliminated.
63412853Sgabeblack@google.cominline small_type
63512853Sgabeblack@google.comconvert_signed_2C_to_SM(int nb, int nd, sc_digit *d)
63612853Sgabeblack@google.com{
63712853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
63812853Sgabeblack@google.com    sc_assert((nb > 0) && (nd > 0) && (d != NULL));
63912853Sgabeblack@google.com#endif
64012853Sgabeblack@google.com
64112853Sgabeblack@google.com    small_type s;
64212853Sgabeblack@google.com
64312853Sgabeblack@google.com    int xnb = bit_ord(nb - 1) + 1;
64412853Sgabeblack@google.com
64512853Sgabeblack@google.com    // Test the sign bit.
64612853Sgabeblack@google.com    if (d[nd - 1] & one_and_zeros(xnb - 1)) {
64712853Sgabeblack@google.com        s = SC_NEG;
64812853Sgabeblack@google.com        vec_complement(nd, d);
64912853Sgabeblack@google.com    } else {
65012853Sgabeblack@google.com        s = SC_POS;
65112853Sgabeblack@google.com    }
65212853Sgabeblack@google.com
65312853Sgabeblack@google.com    // Trim the last digit.
65412853Sgabeblack@google.com    d[nd - 1] &= one_and_ones(xnb);
65512853Sgabeblack@google.com
65612853Sgabeblack@google.com    // Check if the new number is zero.
65712853Sgabeblack@google.com    if (s == SC_POS)
65812853Sgabeblack@google.com        return check_for_zero(s, nd, d);
65912853Sgabeblack@google.com
66012853Sgabeblack@google.com    return s;
66112853Sgabeblack@google.com}
66212853Sgabeblack@google.com
66312853Sgabeblack@google.com// Convert a signed number from sign-magnitude representation to 2's
66412853Sgabeblack@google.com// complement representation, get its sign, convert back to
66512853Sgabeblack@google.com// sign-magnitude representation, and return its sign. nd is d's
66612853Sgabeblack@google.com// actual size, without zeros eliminated.
66712853Sgabeblack@google.cominline small_type
66812853Sgabeblack@google.comconvert_signed_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d)
66912853Sgabeblack@google.com{
67012853Sgabeblack@google.com    convert_SM_to_2C(s, nd, d);
67112853Sgabeblack@google.com    return convert_signed_2C_to_SM(nb, nd, d);
67212853Sgabeblack@google.com}
67312853Sgabeblack@google.com
67412853Sgabeblack@google.com// Convert a signed number from sign-magnitude representation to 2's
67512853Sgabeblack@google.com// complement representation and trim the extra bits.
67612853Sgabeblack@google.cominline void
67712853Sgabeblack@google.comconvert_signed_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d)
67812853Sgabeblack@google.com{
67912853Sgabeblack@google.com    convert_SM_to_2C_trimmed(1, s, nb, nd, d);
68012853Sgabeblack@google.com}
68112853Sgabeblack@google.com
68212853Sgabeblack@google.com// Convert a signed number from sign-magnitude representation to 2's
68312853Sgabeblack@google.com// complement representation but do not trim the extra bits.
68412853Sgabeblack@google.cominline void
68512853Sgabeblack@google.comconvert_signed_SM_to_2C(small_type s, int nd, sc_digit *d)
68612853Sgabeblack@google.com{
68712853Sgabeblack@google.com    convert_SM_to_2C(s, nd, d);
68812853Sgabeblack@google.com}
68912853Sgabeblack@google.com
69012853Sgabeblack@google.com
69112853Sgabeblack@google.com// ----------------------------------------------------------------------------
69212853Sgabeblack@google.com//  Functions to convert between sign-magnitude (SM) and 2's complement
69312853Sgabeblack@google.com//  (2C) representations of unsigned numbers.
69412853Sgabeblack@google.com// ----------------------------------------------------------------------------
69512853Sgabeblack@google.com
69612853Sgabeblack@google.com// Trim the extra leading bits off an unsigned number.
69712853Sgabeblack@google.cominline void
69812853Sgabeblack@google.comtrim_unsigned(int nb, int nd, sc_digit *d)
69912853Sgabeblack@google.com{
70012853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
70112853Sgabeblack@google.com    sc_assert((nb > 0) && (nd > 0) && (d != NULL));
70212853Sgabeblack@google.com#endif
70312853Sgabeblack@google.com
70412853Sgabeblack@google.com    d[nd - 1] &= one_and_ones(bit_ord(nb - 1));
70512853Sgabeblack@google.com}
70612853Sgabeblack@google.com
70712853Sgabeblack@google.com// Convert an unsigned number from 2's complement representation to
70812853Sgabeblack@google.com// sign-magnitude representation, and return its sign. nd is d's
70912853Sgabeblack@google.com// actual size, without zeros eliminated.
71012853Sgabeblack@google.cominline small_type
71112853Sgabeblack@google.comconvert_unsigned_2C_to_SM(int nb, int nd, sc_digit *d)
71212853Sgabeblack@google.com{
71312853Sgabeblack@google.com    trim_unsigned(nb, nd, d);
71412853Sgabeblack@google.com    return check_for_zero(SC_POS, nd, d);
71512853Sgabeblack@google.com}
71612853Sgabeblack@google.com
71712853Sgabeblack@google.com// Convert an unsigned number from sign-magnitude representation to
71812853Sgabeblack@google.com// 2's complement representation, get its sign, convert back to
71912853Sgabeblack@google.com// sign-magnitude representation, and return its sign. nd is d's
72012853Sgabeblack@google.com// actual size, without zeros eliminated.
72112853Sgabeblack@google.cominline small_type
72212853Sgabeblack@google.comconvert_unsigned_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d)
72312853Sgabeblack@google.com{
72412853Sgabeblack@google.com    convert_SM_to_2C(s, nd, d);
72512853Sgabeblack@google.com    return convert_unsigned_2C_to_SM(nb, nd, d);
72612853Sgabeblack@google.com}
72712853Sgabeblack@google.com
72812853Sgabeblack@google.com// Convert an unsigned number from sign-magnitude representation to
72912853Sgabeblack@google.com// 2's complement representation and trim the extra bits.
73012853Sgabeblack@google.cominline void
73112853Sgabeblack@google.comconvert_unsigned_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d)
73212853Sgabeblack@google.com{
73312853Sgabeblack@google.com    convert_SM_to_2C_trimmed(0, s, nb, nd, d);
73412853Sgabeblack@google.com}
73512853Sgabeblack@google.com
73612853Sgabeblack@google.com// Convert an unsigned number from sign-magnitude representation to
73712853Sgabeblack@google.com// 2's complement representation but do not trim the extra bits.
73812853Sgabeblack@google.cominline void
73912853Sgabeblack@google.comconvert_unsigned_SM_to_2C(small_type s, int nd, sc_digit *d)
74012853Sgabeblack@google.com{
74112853Sgabeblack@google.com    convert_SM_to_2C(s, nd, d);
74212853Sgabeblack@google.com}
74312853Sgabeblack@google.com
74412853Sgabeblack@google.com
74512853Sgabeblack@google.com// ----------------------------------------------------------------------------
74612853Sgabeblack@google.com//  Functions to copy one (un)signed number to another.
74712853Sgabeblack@google.com// ----------------------------------------------------------------------------
74812853Sgabeblack@google.com
74912853Sgabeblack@google.com// Copy v to u.
75012853Sgabeblack@google.cominline void
75112853Sgabeblack@google.comcopy_digits_signed(small_type &us,
75212853Sgabeblack@google.com                   int unb, int und, sc_digit *ud,
75312853Sgabeblack@google.com                   int vnb, int vnd, const sc_digit *vd)
75412853Sgabeblack@google.com{
75512853Sgabeblack@google.com    if (und <= vnd) {
75612853Sgabeblack@google.com        vec_copy(und, ud, vd);
75712853Sgabeblack@google.com
75812853Sgabeblack@google.com        if (unb <= vnb)
75912853Sgabeblack@google.com            us = convert_signed_SM_to_2C_to_SM(us, unb, und, ud);
76012853Sgabeblack@google.com    } else { // und > vnd
76112853Sgabeblack@google.com        vec_copy_and_zero(und, ud, vnd, vd);
76212853Sgabeblack@google.com    }
76312853Sgabeblack@google.com}
76412853Sgabeblack@google.com
76512853Sgabeblack@google.com// Copy v to u.
76612853Sgabeblack@google.cominline void
76712853Sgabeblack@google.comcopy_digits_unsigned(small_type &us,
76812853Sgabeblack@google.com                     int unb, int und, sc_digit *ud,
76912853Sgabeblack@google.com                     int /* vnb */, int vnd, const sc_digit *vd)
77012853Sgabeblack@google.com{
77112853Sgabeblack@google.com    if (und <= vnd)
77212853Sgabeblack@google.com        vec_copy(und, ud, vd);
77312853Sgabeblack@google.com    else // und > vnd
77412853Sgabeblack@google.com        vec_copy_and_zero(und, ud, vnd, vd);
77512853Sgabeblack@google.com
77612853Sgabeblack@google.com    us = convert_unsigned_SM_to_2C_to_SM(us, unb, und, ud);
77712853Sgabeblack@google.com}
77812853Sgabeblack@google.com
77912853Sgabeblack@google.com
78012853Sgabeblack@google.com// ----------------------------------------------------------------------------
78112853Sgabeblack@google.com//  Faster set(i, v), without bound checking.
78212853Sgabeblack@google.com// ----------------------------------------------------------------------------
78312853Sgabeblack@google.com
78412853Sgabeblack@google.com// A version of set(i, v) without bound checking.
78512853Sgabeblack@google.cominline void
78612853Sgabeblack@google.comsafe_set(int i, bool v, sc_digit *d)
78712853Sgabeblack@google.com{
78812853Sgabeblack@google.com
78912853Sgabeblack@google.com#ifdef DEBUG_SYSTEMC
79012853Sgabeblack@google.com    sc_assert((i >= 0) && (d != NULL));
79112853Sgabeblack@google.com#endif
79212853Sgabeblack@google.com
79312853Sgabeblack@google.com    int bit_num = bit_ord(i);
79412853Sgabeblack@google.com    int digit_num = digit_ord(i);
79512853Sgabeblack@google.com
79612853Sgabeblack@google.com    if (v)
79712853Sgabeblack@google.com        d[digit_num] |= one_and_zeros(bit_num);
79812853Sgabeblack@google.com    else
79912853Sgabeblack@google.com        d[digit_num] &= ~(one_and_zeros(bit_num));
80012853Sgabeblack@google.com}
80112853Sgabeblack@google.com
80212853Sgabeblack@google.com
80312853Sgabeblack@google.com// ----------------------------------------------------------------------------
80412853Sgabeblack@google.com//  Function to check if a double number is bad (NaN or infinite).
80512853Sgabeblack@google.com// ----------------------------------------------------------------------------
80612853Sgabeblack@google.com
80712853Sgabeblack@google.cominline bool
80812853Sgabeblack@google.comis_nan(double v)
80912853Sgabeblack@google.com{
81012853Sgabeblack@google.com    return std::numeric_limits<double>::has_quiet_NaN && (v != v);
81112853Sgabeblack@google.com}
81212853Sgabeblack@google.com
81312853Sgabeblack@google.cominline bool
81412853Sgabeblack@google.comis_inf(double v)
81512853Sgabeblack@google.com{
81612853Sgabeblack@google.com    return v ==  std::numeric_limits<double>::infinity() ||
81712853Sgabeblack@google.com           v == -std::numeric_limits<double>::infinity();
81812853Sgabeblack@google.com}
81912853Sgabeblack@google.com
82012853Sgabeblack@google.cominline void
82112853Sgabeblack@google.comis_bad_double(double v)
82212853Sgabeblack@google.com{
82312853Sgabeblack@google.com    // Windows throws exception.
82412853Sgabeblack@google.com    if (is_nan(v) || is_inf(v))
82512853Sgabeblack@google.com        SC_REPORT_ERROR("value is not valid",
82612853Sgabeblack@google.com                        "is_bad_double(double v) : "
82712853Sgabeblack@google.com                        "v is not finite - NaN or Inf");
82812853Sgabeblack@google.com}
82912853Sgabeblack@google.com
83012853Sgabeblack@google.com} // namespace sc_dt
83112853Sgabeblack@google.com
83212853Sgabeblack@google.com#endif // __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__
833