📄 corbafixed.cc
字号:
OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_RangeError, CORBA::COMPLETED_NO); return 1;}voidCORBA::Fixed::PR_changeScale(CORBA::UShort new_scale){ if (new_scale > pd_digits) pd_digits = new_scale; pd_scale = new_scale;}//// Arithmetic//static intabsCmp(const CORBA::Fixed& a, const CORBA::Fixed& b){ int c; c = (a.fixed_digits()-a.fixed_scale()) - (b.fixed_digits()-b.fixed_scale()); if (c) return c; int ai, bi; ai = a.fixed_digits() - 1; bi = b.fixed_digits() - 1; while (ai >= 0 && bi >= 0) { c = a.PR_val()[ai] - b.PR_val()[bi]; if (c) return c; --ai; --bi; } if (ai >= 0) return 1; if (bi >= 0) return -1; return 0;}static CORBA::FixedrealAdd(const CORBA::Fixed& a, const CORBA::Fixed& b, CORBA::Boolean negative){ int scale, v, carry = 0, ai = 0, bi = 0, wi = 0; CORBA::Octet work[OMNI_FIXED_DIGITS * 2]; if (a.fixed_scale() > b.fixed_scale()) { scale = a.fixed_scale(); while (ai < a.fixed_scale() - b.fixed_scale()) work[wi++] = a.PR_val()[ai++]; } else if (b.fixed_scale() > a.fixed_scale()) { scale = b.fixed_scale(); while (bi < b.fixed_scale() - a.fixed_scale()) work[wi++] = b.PR_val()[bi++]; } else scale = a.fixed_scale(); while (ai < a.fixed_digits() && bi < b.fixed_digits()) { v = a.PR_val()[ai++] + b.PR_val()[bi++] + carry; if (v > 9) { carry = 1; v -= 10; } else carry = 0; work[wi++] = v; } while (ai < a.fixed_digits()) { v = a.PR_val()[ai++] + carry; if (v > 9) { carry = 1; v -= 10; } else carry = 0; work[wi++] = v; } while (bi < b.fixed_digits()) { v = b.PR_val()[bi++] + carry; if (v > 9) { carry = 1; v -= 10; } else carry = 0; work[wi++] = v; } if (carry) { work[wi++] = carry; } CORBA::Octet* wp = work; int digits = wi; // Truncate or complain if too many digits if (digits > OMNI_FIXED_DIGITS) { if (digits - scale <= OMNI_FIXED_DIGITS) { int chop = digits - OMNI_FIXED_DIGITS; wp += chop; scale -= chop; digits = OMNI_FIXED_DIGITS; } else { OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_RangeError, CORBA::COMPLETED_NO); } } // Strip trailing zeros while (scale > 0 && *wp == 0) { ++wp; --scale; --digits; } return CORBA::Fixed(wp, digits, scale, negative);}static CORBA::FixedrealSub(const CORBA::Fixed& a, const CORBA::Fixed& b, CORBA::Boolean negative){ int scale, v, carry = 0, ai = 0, bi = 0, wi = 0; CORBA::Octet work[OMNI_FIXED_DIGITS * 2]; if (a.fixed_scale() > b.fixed_scale()) { scale = a.fixed_scale(); while (ai < a.fixed_scale() - b.fixed_scale()) work[wi++] = a.PR_val()[ai++]; } else if (b.fixed_scale() > a.fixed_scale()) { scale = b.fixed_scale(); while (bi < b.fixed_scale() - a.fixed_scale()) { work[wi++] = 10 - b.PR_val()[bi++] + carry; carry = -1; } } else scale = a.fixed_scale(); while (ai < a.fixed_digits() && bi < b.fixed_digits()) { v = a.PR_val()[ai++] - b.PR_val()[bi++] + carry; if (v < 0) { carry = -1; v += 10; } else carry = 0; work[wi++] = v; } while (ai < a.fixed_digits()) { v = a.PR_val()[ai++] + carry; if (v < 0) { carry = -1; v += 10; } else carry = 0; work[wi++] = v; } OMNIORB_ASSERT(bi == b.fixed_digits()); OMNIORB_ASSERT(carry == 0); int digits = wi; CORBA::Octet* wp = work; // Strip leading zeros while (work[digits-1] == 0 && digits > scale) --digits; // Truncate or complain if too many digits if (digits > OMNI_FIXED_DIGITS) { OMNIORB_ASSERT(digits - scale <= OMNI_FIXED_DIGITS); int chop = digits - OMNI_FIXED_DIGITS; wp += chop; scale -= chop; digits = OMNI_FIXED_DIGITS; } // Strip trailing zeros while (scale > 0 && *wp == 0) { ++wp; --scale; --digits; } return CORBA::Fixed(wp, digits, scale, negative);}static CORBA::FixedrealMul(const CORBA::Fixed& a, const CORBA::Fixed& b, CORBA::Boolean negative){ int ai, bi, wi, digits, scale, v, ad, bd, carry = 0; CORBA::Octet work[OMNI_FIXED_DIGITS * 2]; memset(work, 0, OMNI_FIXED_DIGITS * 2); scale = a.fixed_scale() + b.fixed_scale(); for (ai=0, wi=0; ai < a.fixed_digits(); ++ai) { ad = a.PR_val()[ai]; if (ad == 0) continue; for (bi=0; bi < b.fixed_digits(); ++bi) { bd = b.PR_val()[bi]; if (bd == 0 && carry == 0) continue; wi = ai + bi; v = work[wi] + ad * bd + carry; carry = v / 10; work[wi] = v % 10; } while (carry) { ++wi; v = work[wi] + carry; carry = v / 10; work[wi] = v % 10; } } digits = wi+1; if (scale > digits) digits = scale; // Truncate or complain if too many digits CORBA::Octet* wp = work; if (digits > OMNI_FIXED_DIGITS) { if (digits - scale <= OMNI_FIXED_DIGITS) { int chop = digits - OMNI_FIXED_DIGITS; wp += chop; scale -= chop; digits = OMNI_FIXED_DIGITS; } else { OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_RangeError, CORBA::COMPLETED_NO); } } // Strip trailing zeros while (scale > 0 && *wp == 0) { ++wp; --scale; --digits; } return CORBA::Fixed(wp, digits, scale, negative);}static intdivCmp(const CORBA::Octet* av, int ad, const CORBA::Octet* bv, int bd, int pos){ int c, ai, bi; for (ai = ad-1; ai > pos; --ai) { if (av[ai]) return 1; } ai = pos; bi = bd - 1; OMNIORB_ASSERT(ai >= bi); while (bi >= 0) { c = av[ai] - bv[bi]; if (c) return c; --ai; --bi; } return 0;}static intdivDigit(CORBA::Octet* av, int ad, const CORBA::Octet* bv, int bd, int pos){ int ai, bi, carry, v, count = 0; while (divCmp(av, ad, bv, bd, pos) >= 0) { ++count; carry = 0; ai = pos - bd + 1; bi = 0; while (bi < bd) { v = av[ai] - bv[bi] + carry; if (v < 0) { carry = -1; v += 10; } else carry = 0; av[ai] = v; ++ai; ++bi; } while (ai < ad) { v = av[ai] + carry; if (v < 0) { carry = -1; v += 10; } else carry = 0; av[ai] = v; ++ai; } } OMNIORB_ASSERT(count < 10); return count;}static CORBA::FixedrealDiv(const CORBA::Fixed& a, const CORBA::Fixed& b, CORBA::Boolean negative){ int i, ai, bi, wi, ri, digits, scale, unscale, v, ad, bd, carry = 0; // This division algorithm basically does classic long division. The // numerator, a, is loaded into the top digits of "running". The // divisor, b, is then repeatedly subtracted from the top digits of // "running" until it can no longer be subtracted without becoming // negative. The count of subtractions forms the top digit of the // result. Then the next digit is found by shifting the divisor down // one digit, and repeating, and so on. // // The ugliness all comes because we need to figure out where to put // the decimal point. It would be easy if it wasn't for the fact // that values with scale > digits are not permitted. This means // that if the result is going to be of that form, some initial zero // digits have to be included. CORBA::Octet work [OMNI_FIXED_DIGITS * 2]; CORBA::Octet running[OMNI_FIXED_DIGITS * 2]; memset(work, 0, OMNI_FIXED_DIGITS * 2); memset(running, 0, OMNI_FIXED_DIGITS * 2); // Skip all leading zeros in a ad = a.fixed_digits(); while (a.PR_val()[ad - 1] == 0) --ad; // Set most siginificant digits of running to a's digits ri = OMNI_FIXED_DIGITS * 2 - 1; ai = ad - 1; while (ai >= 0) { running[ri] = a.PR_val()[ai]; --ri; --ai; } // Skip all leading zeros in b bd = b.fixed_digits(); while (b.PR_val()[bd - 1] == 0) --bd; // unscale = number of digits to left of decimal point in answer unscale = (ad - a.fixed_scale()) - (bd - b.fixed_scale()) + 1; digits = 0; // Set some initial zero digits to prevent scale > digits if (unscale < 0) digits = -unscale; ri = OMNI_FIXED_DIGITS * 2 - 1; wi = ri - digits; // Iterate to work out the result digits while (digits < OMNI_FIXED_DIGITS) { // Finish if running is zero for (i=0; i < OMNI_FIXED_DIGITS*2 && running[i] == 0; ++i); if (i == OMNI_FIXED_DIGITS * 2) break; work[wi] = divDigit(running, OMNI_FIXED_DIGITS * 2, b.PR_val(), bd, ri); if (digits || work[wi]) ++digits; --wi; --ri; } wi = OMNI_FIXED_DIGITS * 2 - 1; // Skip an initial zero if we weren't expecting one if (unscale >= 0) { while (work[wi] == 0 && unscale > 0) { --wi; --unscale; } } else unscale = 0; // Complain if too many digits before decimal point if (unscale > OMNI_FIXED_DIGITS) { OMNIORB_THROW(DATA_CONVERSION, DATA_CONVERSION_RangeError, CORBA::COMPLETED_NO); } // Deal with numbers with trailing zeros before the decimal point if (digits < unscale) digits = unscale; CORBA::Octet* wp = &work[wi - digits + 1]; // Figure out scale scale = digits - unscale; if (digits < scale) digits = scale; // Strip trailing zeros while (scale > 0 && *wp == 0) { ++wp; --scale; --digits; } return CORBA::Fixed(wp, digits, scale, negative);}//// Arithmetic operators//CORBA::Fixedoperator+(const CORBA::Fixed& a, const CORBA::Fixed& b){ if (a.PR_negative() == b.PR_negative()) return realAdd(a, b, a.PR_negative()); int cmp = absCmp(a, b); if (cmp == 0) // a == b return CORBA::Fixed(); else if (cmp > 0) // a > b return realSub(a, b, a.PR_negative()); else return realSub(b, a, b.PR_negative());}CORBA::Fixedoperator-(const CORBA::Fixed& a, const CORBA::Fixed& b){ if (a.PR_negative() != b.PR_negative()) return realAdd(a, b, a.PR_negative()); int cmp = absCmp(a, b); if (cmp == 0) // a == b return CORBA::Fixed(); else if (cmp > 0) // a > b return realSub(a, b, a.PR_negative()); else return realSub(b, a, !a.PR_negative());}CORBA::Fixedoperator*(const CORBA::Fixed& a, const CORBA::Fixed& b){ if (a.fixed_digits() == 0 || b.fixed_digits() == 0) return CORBA::Fixed(); if (a.PR_negative() == b.PR_negative()) return realMul(a, b, 0); else return realMul(a, b, 1);}CORBA::Fixedoperator/(const CORBA::Fixed& a, const CORBA::Fixed& b){ if (b.fixed_digits() == 0) { int fixed_point_divide_by_zero = 0; OMNIORB_USER_CHECK(fixed_point_divide_by_zero); } if (a.fixed_digits() == 0) return CORBA::Fixed(); if (a.PR_negative() == b.PR_negative()) return realDiv(a, b, 0); else return realDiv(a, b, 1);}//// Comparison operators//intCORBA::Fixed::NP_cmp(const Fixed& a, const Fixed& b){ int c; if (a.PR_negative()) { if (b.PR_negative()) c = absCmp(b, a); else return -1; } else { if (b.PR_negative()) return 1; else c = absCmp(a, b); } if (c < 0) return -1; if (c > 0) return 1; return 0;}CORBA::Booleanoperator>(const CORBA::Fixed& a, const CORBA::Fixed& b){ return CORBA::Fixed::NP_cmp(a, b) > 0;}CORBA::Booleanoperator<(const CORBA::Fixed& a, const CORBA::Fixed& b){ return CORBA::Fixed::NP_cmp(a, b) < 0;}CORBA::Booleanoperator>=(const CORBA::Fixed& a, const CORBA::Fixed& b){ return CORBA::Fixed::NP_cmp(a, b) >= 0;}CORBA::Booleanoperator<=(const CORBA::Fixed& a, const CORBA::Fixed& b){ return CORBA::Fixed::NP_cmp(a, b) <= 0;}CORBA::Booleanoperator==(const CORBA::Fixed& a, const CORBA::Fixed& b){ return CORBA::Fixed::NP_cmp(a, b) == 0;}CORBA::Booleanoperator!=(const CORBA::Fixed& a, const CORBA::Fixed& b){ return CORBA::Fixed::NP_cmp(a, b) != 0;}//// Marshalling operators//voidCORBA::Fixed::operator>>=(cdrStream& s) const{ OMNIORB_ASSERT(pd_idl_digits); OMNIORB_ASSERT(pd_digits <= pd_idl_digits); OMNIORB_ASSERT(pd_scale <= pd_idl_scale); CORBA::Octet buffer[16]; int digits_to_write = pd_idl_digits; // Pad with extra zero digit if even no. of digits if ((digits_to_write % 2) == 0) ++digits_to_write; int unscale_to_write = digits_to_write - pd_idl_scale; int unscale = pd_digits - pd_scale; int bi, vi; // Write any leading zeros for (bi=0; bi < unscale_to_write - unscale; bi+=2) { buffer[bi/2] = 0; } bi = unscale_to_write - unscale; vi = pd_digits - 1; // Write digits for (; vi >= 0; --vi, ++bi) { if (bi % 2) buffer[bi/2] |= pd_val[vi]; else buffer[bi/2] = pd_val[vi] << 4; } // Write trailing zeros if (bi % 2) ++bi; for (; bi < digits_to_write; bi+=2) { buffer[bi/2] = 0; } // Sign indicator buffer[digits_to_write / 2] |= pd_negative ? 0xD : 0xC; // Marshal the buffer s.put_octet_array(buffer, digits_to_write / 2 + 1);}voidCORBA::Fixed::operator<<=(cdrStream& s){ OMNIORB_ASSERT(pd_idl_digits); CORBA::Octet buffer[16]; int digits_to_read = pd_idl_digits; if ((digits_to_read % 2) == 0) ++digits_to_read; pd_digits = digits_to_read; pd_scale = pd_idl_scale; // Read the data s.get_octet_array(buffer, digits_to_read / 2 + 1); CORBA::Octet d; // Sign indicator int vi; // Index into pd_val int di; // Digit index int bi = digits_to_read; // Buffer index d = buffer[bi/2] & 0xF; if (d == 0xC) pd_negative = 0; else if (d == 0xD) pd_negative = 1; else OMNIORB_THROW(MARSHAL, MARSHAL_InvalidFixedValue, (CORBA::CompletionStatus)s.completion()); --bi; di = vi = 0; // Skip trailing zeros while (di < pd_idl_scale) { if (bi % 2) d = buffer[bi/2] & 0xF; else d = buffer[bi/2] >> 4; if (d != 0) break; --bi; ++di; --pd_digits; --pd_scale; } // Read and check the digits for (vi = 0; di < digits_to_read; ++di, ++vi, --bi) { if (bi % 2) d = buffer[bi/2] & 0xF; else d = buffer[bi/2] >> 4; if (d > 0x9) OMNIORB_THROW(MARSHAL, MARSHAL_InvalidFixedValue, (CORBA::CompletionStatus)s.completion()); pd_val[vi] = d; } OMNIORB_ASSERT(vi == pd_digits); // Strip off leading zeros. Stop when we hit the decimal point. --vi; while (vi >= pd_scale && pd_val[vi] == 0) --vi; pd_digits = vi + 1; // Fill rest of val with zeros memset(pd_val + pd_digits, 0, OMNI_FIXED_DIGITS - pd_digits); // Sanity check if (pd_digits - pd_scale == pd_idl_digits - pd_idl_scale + 1) { // This happens if idl_digits is even, and the sending ORB put a // non-zero half-octet as the most-siginificant digit. OMNIORB_THROW(MARSHAL, MARSHAL_InvalidFixedValue, (CORBA::CompletionStatus)s.completion()); } OMNIORB_ASSERT(pd_digits <= pd_idl_digits); OMNIORB_ASSERT(pd_scale <= pd_idl_scale); OMNIORB_ASSERT(pd_scale <= pd_digits);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -