📄 sc_nbutils.cpp
字号:
#ifdef SC_MAX_NBITS uchar x[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; uchar y[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)];#else uchar *x = new uchar[xlen]; uchar *y = new uchar[ylen];#endif // r corresponds to w. // Set (uchar) x = (sc_digit) u. xlen = vec_to_char(ulen, u, xlen, x); // Skip all the leading zeros in x. while ((--xlen >= 0) && (! x[xlen])); xlen++; // Set (uchar) y = (sc_digit) v. ylen = vec_to_char(vlen, v, ylen, y); // Skip all the leading zeros in y. while ((--ylen >= 0) && (! y[ylen])); ylen++;#ifdef DEBUG_SYSTEMC assert(xlen > 1); assert(ylen > 1);#endif // At this point, all the leading zeros are eliminated from x and y. // Zero the last digit of x. x[xlen] = 0; // The first two digits of y. register sc_digit y2 = (y[ylen - 1] << BITS_PER_BYTE) + y[ylen - 2]; const sc_digit DOUBLE_BITS_PER_BYTE = 2 * BITS_PER_BYTE; // Find each q[k]. for (register int k = xlen - ylen; k >= 0; --k) { // qk is a guess for q[k] such that q[k] = qk or qk - 1. register sc_digit qk; // Find qk by just using 2 digits of y and 3 digits of x. The // following code assumes that sizeof(sc_digit) >= 3 BYTEs. int k2 = k + ylen; qk = ((x[k2] << DOUBLE_BITS_PER_BYTE) + (x[k2 - 1] << BITS_PER_BYTE) + x[k2 - 2]) / y2; if (qk >= BYTE_RADIX) // qk cannot be larger than the largest qk = BYTE_RADIX - 1; // digit in BYTE_RADIX. // q[k] = qk or qk - 1. The following if-statement determines which. if (qk) { register uchar *xk = (x + k); // A shortcut for x[k]. // x = x - y * qk; register sc_digit carry = 0; for (register int i = 0; i < ylen; ++i) { carry += y[i] * qk; sc_digit diff = (xk[i] + BYTE_RADIX) - (carry & BYTE_MASK); xk[i] = (uchar)(diff & BYTE_MASK); carry = (carry >> BITS_PER_BYTE) + (1 - (diff >> BITS_PER_BYTE)); } if (carry) { // 2's complement the last digit. carry = (xk[ylen] + BYTE_RADIX) - carry; xk[ylen] = (uchar)(carry & BYTE_MASK); carry = 1 - (carry >> BITS_PER_BYTE); if (carry) { // qk was one too large, so decrement it. // --qk; // x = x - y * (qk - 1) = x - y * qk + y = x_above + y. carry = 0; for (register int i = 0; i < ylen; ++i) { carry += xk[i] + y[i]; xk[i] = (uchar)(carry & BYTE_MASK); carry >>= BITS_PER_BYTE; } if (carry) xk[ylen] = (uchar)((xk[ylen] + 1) & BYTE_MASK); } // second if carry } // first if carry } // if qk } // for k // Set (sc_digit) w = (uchar) x for the remainder. vec_from_char(ylen, x, ulen, w);#ifndef SC_MAX_NBITS delete [] x; delete [] y;#endif}// Compute r = u % v, where u is a vector, and r and v are scalars.// - 0 < v < HALF_DIGIT_RADIX. // - The remainder r is returned.sc_digitvec_rem_small(int ulen, const sc_digit *u, sc_digit v){#ifdef DEBUG_SYSTEMC assert((ulen > 0) && (u != NULL)); assert((0 < v) && (v < HALF_DIGIT_RADIX));#endif // This function is adapted from vec_div_small(). register sc_digit r = 0; const sc_digit *ubegin = u; u += ulen; while (ubegin < u) { register sc_digit u_AB = (*--u); // A|B#ifdef DEBUG_SYSTEMC // The overflow bits must be zero. assert(high_half(u_AB) == high_half_masked(u_AB));#endif // r = (((r|A) % v)|B) % v r = (concat(((concat(r, high_half(u_AB))) % v), low_half(u_AB))) % v; } return r;}// u = u / v, r = u % v.sc_digitvec_rem_on_small(int ulen, sc_digit *u, sc_digit v){#ifdef DEBUG_SYSTEMC assert((ulen > 0) && (u != NULL)); assert(v > 0);#endif#define q_h r register sc_digit r = 0; const sc_digit *ubegin = u; u += ulen; while (ubegin < u) { sc_digit u_AB = (*--u); // A|B#ifdef DEBUG_SYSTEMC // The overflow bits must be zero. assert(high_half(u_AB) == high_half_masked(u_AB));#endif register sc_digit num = concat(r, high_half(u_AB)); // num = r|A q_h = num / v; // C num = concat((num % v), low_half(u_AB)); // num = (((r|A) % v)|B) (*u) = concat(q_h, num / v); // q = C|D r = num % v; }#undef q_h return r;}// Set (uchar) v = (sc_digit) u. Return the new vlen.intvec_to_char(int ulen, const sc_digit *u, int vlen, uchar *v){#ifdef DEBUG_SYSTEMC assert((ulen > 0) && (u != NULL)); assert((vlen > 0) && (v != NULL));#endif register int nbits = ulen * BITS_PER_DIGIT; register int right = 0; register int left = right + BITS_PER_BYTE - 1; vlen = 0; while (nbits > 0) { int left_digit = left / BITS_PER_DIGIT; int right_digit = right / BITS_PER_DIGIT; register int nsr = ((vlen << LOG2_BITS_PER_BYTE) % BITS_PER_DIGIT); int d = u[right_digit] >> nsr; if (left_digit != right_digit) { if (left_digit < ulen) d |= u[left_digit] << (BITS_PER_DIGIT - nsr); } v[vlen++] = (uchar)(d & BYTE_MASK); left += BITS_PER_BYTE; right += BITS_PER_BYTE; nbits -= BITS_PER_BYTE; } return vlen;}// Set (sc_digit) v = (uchar) u. // - sizeof(uchar) <= sizeof(sc_digit), void vec_from_char(int ulen, const uchar *u, int vlen, sc_digit *v){#ifdef DEBUG_SYSTEMC assert((ulen > 0) && (u != NULL)); assert((vlen > 0) && (v != NULL)); assert(sizeof(uchar) <= sizeof(sc_digit));#endif sc_digit *vend = (v + vlen); const int nsr = BITS_PER_DIGIT - BITS_PER_BYTE; const sc_digit mask = one_and_ones(nsr); (*v) = (sc_digit) u[ulen - 1]; for (register int i = ulen - 2; i >= 0; --i) { // Manual inlining of vec_shift_left(). register sc_digit *viter = v; register sc_digit carry = 0; while (viter < vend) { register sc_digit vval = (*viter); (*viter++) = (((vval & mask) << BITS_PER_BYTE) | carry); carry = vval >> nsr; } if (viter < vend) (*viter) = carry; (*v) |= (sc_digit) u[i]; }}// Set u <<= nsl.// If nsl is negative, it is ignored.void vec_shift_left(int ulen, sc_digit *u, int nsl){#ifdef DEBUG_SYSTEMC assert((ulen > 0) && (u != NULL));#endif if (nsl <= 0) return; // Shift left whole digits if nsl is large enough. if (nsl >= (int) BITS_PER_DIGIT) { int nd; if (nsl % BITS_PER_DIGIT == 0) { nd = nsl / BITS_PER_DIGIT; // No need to use DIV_CEIL(nsl). nsl = 0; } else { nd = DIV_CEIL(nsl) - 1; nsl -= nd * BITS_PER_DIGIT; } if (nd) { // Shift left for nd digits. for (register int j = ulen - 1; j >= nd; --j) u[j] = u[j - nd]; vec_zero( sc_min( nd, ulen ), u ); } if (nsl == 0) return; } // Shift left if nsl < BITS_PER_DIGIT. register sc_digit *uiter = u; sc_digit *uend = uiter + ulen; int nsr = BITS_PER_DIGIT - nsl; sc_digit mask = one_and_ones(nsr); register sc_digit carry = 0; while (uiter < uend) { register sc_digit uval = (*uiter); (*uiter++) = (((uval & mask) << nsl) | carry); carry = uval >> nsr; } if (uiter < uend) (*uiter) = carry;}// Set u >>= nsr.// If nsr is negative, it is ignored.void vec_shift_right(int ulen, sc_digit *u, int nsr, sc_digit fill){#ifdef DEBUG_SYSTEMC assert((ulen > 0) && (u != NULL));#endif // fill is usually either 0 or DIGIT_MASK; it can be any value. if (nsr <= 0) return; // Shift right whole digits if nsr is large enough. if (nsr >= (int) BITS_PER_DIGIT) { int nd; if (nsr % BITS_PER_DIGIT == 0) { nd = nsr / BITS_PER_DIGIT; nsr = 0; } else { nd = DIV_CEIL(nsr) - 1; nsr -= nd * BITS_PER_DIGIT; } if (nd) { // Shift right for nd digits. for (register int j = 0; j < (ulen - nd); ++j) u[j] = u[j + nd]; if (fill) { for (register int j = ulen - sc_min( nd, ulen ); j < ulen; ++j) u[j] = fill; } else vec_zero(ulen - sc_min( nd, ulen ), ulen, u); } if (nsr == 0) return; } // Shift right if nsr < BITS_PER_DIGIT. sc_digit *ubegin = u; register sc_digit *uiter = (ubegin + ulen); int nsl = BITS_PER_DIGIT - nsr; sc_digit mask = one_and_ones(nsr); register sc_digit carry = (fill & mask) << nsl; while (ubegin < uiter) { register sc_digit uval = (*--uiter); (*uiter) = (uval >> nsr) | carry; carry = (uval & mask) << nsl; }}// Let u[l..r], where l and r are left and right bit positions// respectively, be equal to its mirror image.voidvec_reverse(int unb, int und, sc_digit *ud, int l, int r){#ifdef DEBUG_SYSTEMC assert((unb > 0) && (und > 0) && (ud != NULL)); assert((0 <= r) && (r <= l) && (l < unb));#endif if (l < r) { char msg[BUFSIZ]; std::sprintf( msg, "vec_reverse( int, int, sc_digit*, int l, int r ) : " "l = %d < r = %d is not valid", l, r ); SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); } // Make sure that l and r are within bounds. r = sc_max(r, 0); l = sc_min(l, unb - 1); // Allocate memory for processing.#ifdef SC_MAX_NBITS sc_digit d[MAX_NDIGITS];#else sc_digit *d = new sc_digit[und];#endif // d is a copy of ud. vec_copy(und, d, ud); // Based on the value of the ith in d, find the value of the jth bit // in ud. for (register int i = l, j = r; i >= r; --i, ++j) { if ((d[digit_ord(i)] & one_and_zeros(bit_ord(i))) != 0) // Test. ud[digit_ord(j)] |= one_and_zeros(bit_ord(j)); // Set. else ud[digit_ord(j)] &= ~(one_and_zeros(bit_ord(j))); // Clear. }#ifndef SC_MAX_NBITS delete [] d;#endif }} // namespace sc_dt// End of file.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -