Commit 342513dd authored by Martin Heistermann's avatar Martin Heistermann
Browse files

Fix ExactConstraintSatisfaction::safeDot:

In an edge case, it could happen that k is negative (even INT_MIN),
leading to an endless (modulo safebreak) loop.

Simplify the code, eliminating some dangerous manual edge case handling.
parent 49a044af
Pipeline #19043 passed with stages
in 9 minutes and 49 seconds
...@@ -294,42 +294,38 @@ double ExactConstraintSatisfaction::safeDot(const std::vector<std::pair<int, dou ...@@ -294,42 +294,38 @@ double ExactConstraintSatisfaction::safeDot(const std::vector<std::pair<int, dou
} }
} }
std::pair<int, double> element;
double dbl_k;
int safebreak = 9999999; int safebreak = 9999999;
while((!P.empty() || !N.empty())) while((!P.empty() || !N.empty()))
{ {
if(!P.empty() && (result < 0 || N.empty())) if(!P.empty() && (result < 0 || N.empty()))
{ {
const std::pair<int, double> element = P.back(); element = P.back();
P.pop_back(); P.pop_back();
double test_value = element.second;
if(test_value < 0.00000001) k = element.first;
{ //to prevent overflow through the dividing dbl_k = (delta_ - result)/element.second;
k = element.first; assert(dbl_k >= 0);
} if (dbl_k < k) {
else k = static_cast<int>(std::floor(dbl_k));
{ P.push_back({element.first - k, element.second});
k = std::min(element.first, static_cast<int>(std::floor((delta_ - result)/element.second)));
} }
result = result + k * element.second; result = result + k * element.second;
if(k < element.first)
P.push_back({element.first - k, element.second});
} }
else else
{ {
const std::pair<int, double> element = N.back(); element = N.back();
N.pop_back(); N.pop_back();
double test_value = element.second;
if(std::abs(test_value) < 0.00000001) //to prevent overflow through the dividing k = element.first;
{ dbl_k = (-delta_ - result)/element.second;
k = element.first; assert(dbl_k >= 0);
} if (dbl_k < k) {
else k = static_cast<int>(std::floor(dbl_k));
{ N.push_back({element.first - k, element.second});
k = std::min(element.first, static_cast<int>(std::floor((-delta_ - result)/element.second)));
} }
result = result + k * element.second; result = result + k * element.second;
if(k < element.first)
N.push_back({element.first - k, element.second});
} }
if(k == 0) if(k == 0)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment