From a241bf4f74170bec8ac23ccad90c356a17ecfe8d Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 18 Jul 2011 19:35:55 -0700 Subject: [PATCH] Fix mixed size verinum negative comparisons. For mixed sized negative operands the verinum comparisons were sometimes returning the wrong value. --- verinum.cc | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/verinum.cc b/verinum.cc index 143c0cac9..d59d47c81 100644 --- a/verinum.cc +++ b/verinum.cc @@ -804,7 +804,8 @@ verinum::V operator <= (const verinum&left, const verinum&right) { verinum::V left_pad = verinum::V0; verinum::V right_pad = verinum::V0; - if (left.has_sign() && right.has_sign()) { + bool signed_calc = left.has_sign() && right.has_sign(); + if (signed_calc) { left_pad = left.get(left.len()-1); right_pad = right.get(right.len()-1); @@ -816,11 +817,23 @@ verinum::V operator <= (const verinum&left, const verinum&right) unsigned idx; for (idx = left.len() ; idx > right.len() ; idx -= 1) { - if (left[idx-1] != right_pad) return verinum::V0; + if (left[idx-1] != right_pad) { + // A change of padding for a negative left argument + // denotes the left value is less than the right. + return (signed_calc && + (left_pad == verinum::V1)) ? verinum::V1 : + verinum::V0; + } } for (idx = right.len() ; idx > left.len() ; idx -= 1) { - if (right[idx-1] != left_pad) return verinum::V1; + if (right[idx-1] != left_pad) { + // A change of padding for a negative right argument + // denotes the left value is not less than the right. + return (signed_calc && + (right_pad == verinum::V1)) ? verinum::V0 : + verinum::V1; + } } idx = right.len(); @@ -843,7 +856,8 @@ verinum::V operator < (const verinum&left, const verinum&right) { verinum::V left_pad = verinum::V0; verinum::V right_pad = verinum::V0; - if (left.has_sign() && right.has_sign()) { + bool signed_calc = left.has_sign() && right.has_sign(); + if (signed_calc) { left_pad = left.get(left.len()-1); right_pad = right.get(right.len()-1); @@ -855,11 +869,23 @@ verinum::V operator < (const verinum&left, const verinum&right) unsigned idx; for (idx = left.len() ; idx > right.len() ; idx -= 1) { - if (left[idx-1] != right_pad) return verinum::V0; + if (left[idx-1] != right_pad) { + // A change of padding for a negative left argument + // denotes the left value is less than the right. + return (signed_calc && + (left_pad == verinum::V1)) ? verinum::V1 : + verinum::V0; + } } for (idx = right.len() ; idx > left.len() ; idx -= 1) { - if (right[idx-1] != left_pad) return verinum::V1; + if (right[idx-1] != left_pad) { + // A change of padding for a negative right argument + // denotes the left value is not less than the right. + return (signed_calc && + (right_pad == verinum::V1)) ? verinum::V0 : + verinum::V1; + } } while (idx > 0) {