summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Mesnier <mesnier_p@ociweb.com>2015-06-24 09:18:27 -0500
committerPhil Mesnier <mesnier_p@ociweb.com>2015-06-24 09:18:27 -0500
commitfba94d061ecdf31bf853f1c7a52bba7f54429e25 (patch)
treef98a7dce7d23b9a2cb7f45e53bab61b9fb1652d3
parentb589dc30458fa73e2ab757cb1413702bbdaa98eb (diff)
parentceb825a446f74288f4bdb66170aaba8e096996f5 (diff)
downloadATCD-fba94d061ecdf31bf853f1c7a52bba7f54429e25.tar.gz
Merge pull request #96 from jrw972/master
Rewrote normalize to fix off-by-one error. Fixed bug in division and added test. This only impacts the new Fixed type.
-rw-r--r--ACE/ace/CDR_Base.cpp47
-rw-r--r--ACE/tests/CDR_Fixed_Test.cpp3
2 files changed, 19 insertions, 31 deletions
diff --git a/ACE/ace/CDR_Base.cpp b/ACE/ace/CDR_Base.cpp
index 92702361a7a..daca058f704 100644
--- a/ACE/ace/CDR_Base.cpp
+++ b/ACE/ace/CDR_Base.cpp
@@ -917,36 +917,19 @@ void ACE_CDR::Fixed::normalize (UShort min_scale)
if (this->value_[15] & 0xf0 || !this->scale_)
return;
- 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);
- }
+ // 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;
}
ACE_CDR::Fixed ACE_CDR::Fixed::from_string (const char *str)
@@ -1394,7 +1377,8 @@ ACE_CDR::Fixed &ACE_CDR::Fixed::operator/= (const Fixed &rhs)
if (neg)
this->value_[15] = (this->value_[15] & 0xf0) | POSITIVE;
- Fixed r, q = this->div_helper2 (rhs_no_scale, r);
+ Fixed r;
+ Fixed q = this->div_helper2 (rhs_no_scale, r);
if (!r)
return *this = neg ? -q : q;;
@@ -1461,6 +1445,7 @@ 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 83c175a2f46..f9611bbf529 100644
--- a/ACE/tests/CDR_Fixed_Test.cpp
+++ b/ACE/tests/CDR_Fixed_Test.cpp
@@ -224,6 +224,9 @@ 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;
}