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