diff options
-rw-r--r-- | ACE/ace/CDR_Base.cpp | 47 | ||||
-rw-r--r-- | ACE/tests/CDR_Fixed_Test.cpp | 3 |
2 files changed, 31 insertions, 19 deletions
diff --git a/ACE/ace/CDR_Base.cpp b/ACE/ace/CDR_Base.cpp index daca058f704..92702361a7a 100644 --- a/ACE/ace/CDR_Base.cpp +++ b/ACE/ace/CDR_Base.cpp @@ -917,19 +917,36 @@ void ACE_CDR::Fixed::normalize (UShort min_scale) if (this->value_[15] & 0xf0 || !this->scale_) return; - // Calculate the number of nibbles that can be moved. - size_t nibbles = 0; - while (digit(nibbles) == 0 && this->scale_ - nibbles > min_scale) - ++nibbles; - - // Move and clear the nibbles. - for (size_t idx = nibbles; idx != this->digits_; ++idx) { - digit (idx - nibbles, digit (idx)); - digit (idx, 0); - } - - this->scale_ -= nibbles; - this->digits_ -= nibbles; + size_t bytes = 0; // number of bytes to shift down + while (2 * (bytes + 1) < this->scale_ + && this->scale_ - 2 * (bytes + 1) >= min_scale + && !this->value_[14 - bytes]) + ++bytes; + + const bool extra_nibble = 2 * (bytes + 1) <= this->scale_ + && this->scale_ - 2 * (bytes + 1) >= min_scale + && !(this->value_[14 - bytes] & 0xf); + const size_t nibbles = 1 /*[15].high*/ + bytes * 2 + extra_nibble; + this->digits_ -= static_cast<Octet> (nibbles); + this->scale_ -= static_cast<Octet> (nibbles); + + if (extra_nibble) + { + const bool sign = this->sign (); + std::memmove (this->value_ + bytes + 1, this->value_, 15 - bytes); + std::memset (this->value_, 0, bytes + 1); + this->value_[15] |= sign ? NEGATIVE : POSITIVE; + } + else + { + this->value_[15] = (this->value_[14 - bytes] & 0xf) << 4 + | (this->value_[15] & 0xf); + for (size_t i = 14; i > bytes; --i) + this->value_[i] = (this->value_[i - bytes - 1] & 0xf) << 4 + | (this->value_[i - bytes] >> 4); + this->value_[bytes] = this->value_[0] >> 4; + std::memset (this->value_, 0, bytes); + } } ACE_CDR::Fixed ACE_CDR::Fixed::from_string (const char *str) @@ -1377,8 +1394,7 @@ ACE_CDR::Fixed &ACE_CDR::Fixed::operator/= (const Fixed &rhs) if (neg) this->value_[15] = (this->value_[15] & 0xf0) | POSITIVE; - Fixed r; - Fixed q = this->div_helper2 (rhs_no_scale, r); + Fixed r, q = this->div_helper2 (rhs_no_scale, r); if (!r) return *this = neg ? -q : q;; @@ -1445,7 +1461,6 @@ ACE_CDR::Fixed ACE_CDR::Fixed::div_helper1 (const Fixed &rhs, Fixed &r) const if (q > 9) q = 9; Fixed t = from_integer (LongLong (q)) * rhs; - t.scale_ = this->scale_; for (int i = 0; i < 2 && t > *this; ++i) { --q; diff --git a/ACE/tests/CDR_Fixed_Test.cpp b/ACE/tests/CDR_Fixed_Test.cpp index f9611bbf529..83c175a2f46 100644 --- a/ACE/tests/CDR_Fixed_Test.cpp +++ b/ACE/tests/CDR_Fixed_Test.cpp @@ -224,9 +224,6 @@ int run_main (int, ACE_TCHAR *[]) Fixed f29 = Fixed::from_integer (LongLong (1)) / Fixed::from_integer (LongLong (-3)); EXPECT ("-0.333333333333333333333333333333", f29); //TODO: one more 3 - Fixed f30 = Fixed::from_string("-9999752.0000") / Fixed::from_string("-4999876.00"); - EXPECT ("2", f30); - ACE_END_TEST; return failed; } |