Support: Return scale from ScaledNumbers::matchScales()

This will be convenient when extracting `ScaledNumbers::getSum()`.

llvm-svn: 211552
This commit is contained in:
Duncan P. N. Exon Smith 2014-06-23 23:14:51 +00:00
parent 9ea8efaf92
commit 68a5ef1a63
2 changed files with 17 additions and 14 deletions

View File

@ -271,28 +271,30 @@ int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale) {
/// losing precision only when necessary. /// losing precision only when necessary.
/// ///
/// If the output value of \c LDigits (\c RDigits) is \c 0, the output value of /// If the output value of \c LDigits (\c RDigits) is \c 0, the output value of
/// \c LScale (\c RScale) is unspecified. If both \c LDigits and \c RDigits /// \c LScale (\c RScale) is unspecified.
/// are \c 0, the output value is one of \c LScale and \c RScale; which is ///
/// unspecified. /// As a convenience, returns the matching scale. If the output value of one
/// number is zero, returns the scale of the other. If both are zero, which
/// scale is returned is unspecifed.
template <class DigitsT> template <class DigitsT>
void matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits, int16_t matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits,
int16_t &RScale) { int16_t &RScale) {
static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
if (LScale < RScale) { if (LScale < RScale)
// Swap arguments. // Swap arguments.
matchScales(RDigits, RScale, LDigits, LScale); return matchScales(RDigits, RScale, LDigits, LScale);
return; if (!LDigits)
} return RScale;
if (!LDigits || !RDigits || LScale == RScale) if (!RDigits || LScale == RScale)
return; return LScale;
// Now LScale > RScale. Get the difference. // Now LScale > RScale. Get the difference.
int32_t ScaleDiff = int32_t(LScale) - RScale; int32_t ScaleDiff = int32_t(LScale) - RScale;
if (ScaleDiff >= 2 * getWidth<DigitsT>()) { if (ScaleDiff >= 2 * getWidth<DigitsT>()) {
// Don't bother shifting. RDigits will get zero-ed out anyway. // Don't bother shifting. RDigits will get zero-ed out anyway.
RDigits = 0; RDigits = 0;
return; return LScale;
} }
// Shift LDigits left as much as possible, then shift RDigits right. // Shift LDigits left as much as possible, then shift RDigits right.
@ -303,7 +305,7 @@ void matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits,
if (ShiftR >= getWidth<DigitsT>()) { if (ShiftR >= getWidth<DigitsT>()) {
// Don't bother shifting. RDigits will get zero-ed out anyway. // Don't bother shifting. RDigits will get zero-ed out anyway.
RDigits = 0; RDigits = 0;
return; return LScale;
} }
LDigits <<= ShiftL; LDigits <<= ShiftL;
@ -312,6 +314,7 @@ void matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits,
LScale -= ShiftL; LScale -= ShiftL;
RScale += ShiftR; RScale += ShiftR;
assert(LScale == RScale && "scales should match"); assert(LScale == RScale && "scales should match");
return LScale;
} }
} // end namespace ScaledNumbers } // end namespace ScaledNumbers

View File

@ -336,7 +336,7 @@ TEST(ScaledNumberHelpersTest, matchScales) {
int16_t RSx = RSIn; \ int16_t RSx = RSIn; \
int16_t Sy = SOut; \ int16_t Sy = SOut; \
\ \
matchScales(LDx, LSx, RDx, RSx); \ EXPECT_EQ(SOut, matchScales(LDx, LSx, RDx, RSx)); \
EXPECT_EQ(LDy, LDx); \ EXPECT_EQ(LDy, LDx); \
EXPECT_EQ(RDy, RDx); \ EXPECT_EQ(RDy, RDx); \
if (LDy) \ if (LDy) \