Fixed #4087 (div by zero check is invalid for floats)

This commit is contained in:
Daniel Marjamäki 2012-09-11 16:50:42 +02:00
parent 1863306198
commit 64faa780fe
6 changed files with 108 additions and 98 deletions

View File

@ -295,7 +295,7 @@ static bool for_condition(const Token *tok2, unsigned int varid, std::string &mi
Token::Match(tok2, "%varid% != %num% ; %varid% ++", varid)) { Token::Match(tok2, "%varid% != %num% ; %varid% ++", varid)) {
maxMinFlipped = false; maxMinFlipped = false;
const MathLib::bigint value = MathLib::toLongNumber(tok2->strAt(2)); const MathLib::bigint value = MathLib::toLongNumber(tok2->strAt(2));
max_value = MathLib::toString<MathLib::bigint>(value - 1); max_value = MathLib::longToString(value - 1);
} else if (Token::Match(tok2, "%varid% <= %num% ;|&&|%oror%", varid)) { } else if (Token::Match(tok2, "%varid% <= %num% ;|&&|%oror%", varid)) {
maxMinFlipped = false; maxMinFlipped = false;
max_value = tok2->strAt(2); max_value = tok2->strAt(2);
@ -305,7 +305,7 @@ static bool for_condition(const Token *tok2, unsigned int varid, std::string &mi
maxMinFlipped = true; maxMinFlipped = true;
const MathLib::bigint value = MathLib::toLongNumber(tok2->str()); const MathLib::bigint value = MathLib::toLongNumber(tok2->str());
max_value = min_value; max_value = min_value;
min_value = MathLib::toString<MathLib::bigint>(value + 1); min_value = MathLib::longToString(value + 1);
} else if (Token::Match(tok2, "%num% <= %varid% ;|&&|%oror%", varid)) { } else if (Token::Match(tok2, "%num% <= %varid% ;|&&|%oror%", varid)) {
maxMinFlipped = true; maxMinFlipped = true;
max_value = min_value; max_value = min_value;
@ -351,7 +351,7 @@ static bool for_maxvalue(const Token * const stepvalue, const std::string &min_v
MathLib::bigint max = MathLib::toLongNumber(max_value); MathLib::bigint max = MathLib::toLongNumber(max_value);
const MathLib::bigint min = MathLib::toLongNumber(min_value); const MathLib::bigint min = MathLib::toLongNumber(min_value);
max = ((max - min) / num) * num + min; max = ((max - min) / num) * num + min;
max_value = MathLib::toString<MathLib::bigint>(max); max_value = MathLib::longToString(max);
return true; return true;
} }

View File

@ -67,6 +67,13 @@ MathLib::bigint MathLib::toLongNumber(const std::string &str)
return ret; return ret;
} }
std::string MathLib::longToString(const bigint value)
{
std::ostringstream result;
result << value;
return result.str();
}
double MathLib::toDoubleNumber(const std::string &str) double MathLib::toDoubleNumber(const std::string &str)
{ {
if (isHex(str)) if (isHex(str))
@ -81,6 +88,18 @@ double MathLib::toDoubleNumber(const std::string &str)
return ret; return ret;
} }
std::string MathLib::doubleToString(const double value)
{
std::ostringstream result;
result.precision(12);
result << value;
if (result.str() == "-0")
return "0.0";
if (result.str().find(".") == std::string::npos)
return result.str() + ".0";
return result.str();
}
bool MathLib::isFloat(const std::string &s) bool MathLib::isFloat(const std::string &s)
{ {
// every number that contains a . is a float // every number that contains a . is a float
@ -215,25 +234,25 @@ bool MathLib::isInt(const std::string & s)
std::string MathLib::add(const std::string & first, const std::string & second) std::string MathLib::add(const std::string & first, const std::string & second)
{ {
if (MathLib::isInt(first) && MathLib::isInt(second)) { if (MathLib::isInt(first) && MathLib::isInt(second)) {
return toString<bigint>(toLongNumber(first) + toLongNumber(second)); return longToString(toLongNumber(first) + toLongNumber(second));
} }
double d1 = toDoubleNumber(first); double d1 = toDoubleNumber(first);
double d2 = toDoubleNumber(second); double d2 = toDoubleNumber(second);
int count = 0; int count = 0;
while (d1 > 100000.0 * d2 && toString<double>(d1+d2)==first && ++count<5) while (d1 > 100000.0 * d2 && doubleToString(d1+d2)==first && ++count<5)
d2 *= 10.0; d2 *= 10.0;
while (d2 > 100000.0 * d1 && toString<double>(d1+d2)==second && ++count<5) while (d2 > 100000.0 * d1 && doubleToString(d1+d2)==second && ++count<5)
d1 *= 10.0; d1 *= 10.0;
return toString<double>(d1 + d2); return doubleToString(d1 + d2);
} }
std::string MathLib::subtract(const std::string &first, const std::string &second) std::string MathLib::subtract(const std::string &first, const std::string &second)
{ {
if (MathLib::isInt(first) && MathLib::isInt(second)) { if (MathLib::isInt(first) && MathLib::isInt(second)) {
return toString<bigint>(toLongNumber(first) - toLongNumber(second)); return longToString(toLongNumber(first) - toLongNumber(second));
} }
if (first == second) if (first == second)
@ -243,12 +262,12 @@ std::string MathLib::subtract(const std::string &first, const std::string &secon
double d2 = toDoubleNumber(second); double d2 = toDoubleNumber(second);
int count = 0; int count = 0;
while (d1 > 100000.0 * d2 && toString<double>(d1-d2)==first && ++count<5) while (d1 > 100000.0 * d2 && doubleToString(d1-d2)==first && ++count<5)
d2 *= 10.0; d2 *= 10.0;
while (d2 > 100000.0 * d1 && toString<double>(d1-d2)==second && ++count<5) while (d2 > 100000.0 * d1 && doubleToString(d1-d2)==second && ++count<5)
d1 *= 10.0; d1 *= 10.0;
return toString<double>(d1 - d2); return doubleToString(d1 - d2);
} }
std::string MathLib::divide(const std::string &first, const std::string &second) std::string MathLib::divide(const std::string &first, const std::string &second)
@ -257,17 +276,17 @@ std::string MathLib::divide(const std::string &first, const std::string &second)
bigint b = toLongNumber(second); bigint b = toLongNumber(second);
if (b == 0) if (b == 0)
throw InternalError(0, "Internal Error: Division by zero"); throw InternalError(0, "Internal Error: Division by zero");
return toString<bigint>(toLongNumber(first) / b); return longToString(toLongNumber(first) / b);
} }
return toString<double>(toDoubleNumber(first) / toDoubleNumber(second)); return doubleToString(toDoubleNumber(first) / toDoubleNumber(second));
} }
std::string MathLib::multiply(const std::string &first, const std::string &second) std::string MathLib::multiply(const std::string &first, const std::string &second)
{ {
if (MathLib::isInt(first) && MathLib::isInt(second)) { if (MathLib::isInt(first) && MathLib::isInt(second)) {
return toString<bigint>(toLongNumber(first) * toLongNumber(second)); return longToString(toLongNumber(first) * toLongNumber(second));
} }
return toString<double>(toDoubleNumber(first) * toDoubleNumber(second)); return doubleToString(toDoubleNumber(first) * toDoubleNumber(second));
} }
std::string MathLib::mod(const std::string &first, const std::string &second) std::string MathLib::mod(const std::string &first, const std::string &second)
@ -276,9 +295,9 @@ std::string MathLib::mod(const std::string &first, const std::string &second)
bigint b = toLongNumber(second); bigint b = toLongNumber(second);
if (b == 0) if (b == 0)
throw InternalError(0, "Internal Error: Division by zero"); throw InternalError(0, "Internal Error: Division by zero");
return toString<MathLib::bigint>(toLongNumber(first) % b); return longToString(toLongNumber(first) % b);
} }
return toString<double>(fmod(toDoubleNumber(first),toDoubleNumber(second))); return doubleToString(fmod(toDoubleNumber(first),toDoubleNumber(second)));
} }
std::string MathLib::calculate(const std::string &first, const std::string &second, char action) std::string MathLib::calculate(const std::string &first, const std::string &second, char action)
@ -300,13 +319,13 @@ std::string MathLib::calculate(const std::string &first, const std::string &seco
return MathLib::mod(first, second); return MathLib::mod(first, second);
case '&': case '&':
return MathLib::toString(MathLib::toLongNumber(first) & MathLib::toLongNumber(second)); return MathLib::longToString(MathLib::toLongNumber(first) & MathLib::toLongNumber(second));
case '|': case '|':
return MathLib::toString(MathLib::toLongNumber(first) | MathLib::toLongNumber(second)); return MathLib::longToString(MathLib::toLongNumber(first) | MathLib::toLongNumber(second));
case '^': case '^':
return MathLib::toString(MathLib::toLongNumber(first) ^ MathLib::toLongNumber(second)); return MathLib::longToString(MathLib::toLongNumber(first) ^ MathLib::toLongNumber(second));
default: default:
throw InternalError(0, std::string("Unexpected action '") + action + "' in MathLib::calculate(). Please report this to Cppcheck developers."); throw InternalError(0, std::string("Unexpected action '") + action + "' in MathLib::calculate(). Please report this to Cppcheck developers.");
@ -315,31 +334,31 @@ std::string MathLib::calculate(const std::string &first, const std::string &seco
std::string MathLib::sin(const std::string &tok) std::string MathLib::sin(const std::string &tok)
{ {
return toString<double>(std::sin(toDoubleNumber(tok))); return doubleToString(std::sin(toDoubleNumber(tok)));
} }
std::string MathLib::cos(const std::string &tok) std::string MathLib::cos(const std::string &tok)
{ {
return toString<double>(std::cos(toDoubleNumber(tok))); return doubleToString(std::cos(toDoubleNumber(tok)));
} }
std::string MathLib::tan(const std::string &tok) std::string MathLib::tan(const std::string &tok)
{ {
return toString<double>(std::tan(toDoubleNumber(tok))); return doubleToString(std::tan(toDoubleNumber(tok)));
} }
std::string MathLib::abs(const std::string &tok) std::string MathLib::abs(const std::string &tok)
{ {
return toString<double>(std::abs(toDoubleNumber(tok))); return doubleToString(std::abs(toDoubleNumber(tok)));
} }
bool MathLib::isEqual(const std::string &first, const std::string &second) bool MathLib::isEqual(const std::string &first, const std::string &second)
{ {
// this conversion is needed for formating // this conversion is needed for formating
// e.g. if first=0.1 and second=1.0E-1, the direct comparison of the strings whould fail // e.g. if first=0.1 and second=1.0E-1, the direct comparison of the strings whould fail
return toString<double>(toDoubleNumber(first)) == toString<double>(toDoubleNumber(second)); return doubleToString(toDoubleNumber(first)) == doubleToString(toDoubleNumber(second));
} }
bool MathLib::isNotEqual(const std::string &first, const std::string &second) bool MathLib::isNotEqual(const std::string &first, const std::string &second)

View File

@ -34,17 +34,9 @@ public:
typedef long long bigint; typedef long long bigint;
static bigint toLongNumber(const std::string & str); static bigint toLongNumber(const std::string & str);
static std::string longToString(const bigint value);
static double toDoubleNumber(const std::string & str); static double toDoubleNumber(const std::string & str);
static std::string doubleToString(const double value);
template<typename T>
static std::string toString(const T &d) {
std::ostringstream result;
result.precision(8);
result << d;
if (isNullValue(result.str()))
return std::string("0");
return result.str();
}
static bool isInt(const std::string & str); static bool isInt(const std::string & str);
static bool isFloat(const std::string &str); static bool isFloat(const std::string &str);

View File

@ -744,9 +744,9 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
result = MathLib::calculate(tok->str(), tok->strAt(2), cop); result = MathLib::calculate(tok->str(), tok->strAt(2), cop);
else if (cop == '<') { else if (cop == '<') {
if (tok->previous()->str() != "<<" && rightInt > 0) // Ensure that its not a shift operator as used for streams if (tok->previous()->str() != "<<" && rightInt > 0) // Ensure that its not a shift operator as used for streams
result = MathLib::toString<MathLib::bigint>(leftInt << rightInt); result = MathLib::longToString(leftInt << rightInt);
} else if (rightInt > 0) } else if (rightInt > 0)
result = MathLib::toString<MathLib::bigint>(leftInt >> rightInt); result = MathLib::longToString(leftInt >> rightInt);
if (!result.empty()) { if (!result.empty()) {
ret = true; ret = true;
@ -809,7 +809,7 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
if (tok->type() == Token::eChar && if (tok->type() == Token::eChar &&
Token::Match(tok->previous(), "(|&&|%oror% %any% ==|!=|<=|<|>=|> %num% &&|%oror%|)")) { Token::Match(tok->previous(), "(|&&|%oror% %any% ==|!=|<=|<|>=|> %num% &&|%oror%|)")) {
tok->str(MathLib::toString(tok->str()[1] & 0xff)); tok->str(MathLib::longToString(tok->str()[1] & 0xff));
} }
if (tok->isNumber()) { if (tok->isNumber()) {

View File

@ -399,7 +399,7 @@ static Token *splitDefinitionFromTypedef(Token *tok)
name = tok1->next()->str(); name = tok1->next()->str();
else { // create a unique name else { // create a unique name
static unsigned int count = 0; static unsigned int count = 0;
name = "Unnamed" + MathLib::toString<unsigned int>(count++); name = "Unnamed" + MathLib::longToString(count++);
} }
tok->next()->insertToken(name); tok->next()->insertToken(name);
} else } else
@ -2147,7 +2147,7 @@ void Tokenizer::simplifyLineMacro()
{ {
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
if (tok->str() == "__LINE__") if (tok->str() == "__LINE__")
tok->str(MathLib::toString(tok->linenr())); tok->str(MathLib::longToString(tok->linenr()));
} }
} }
@ -2402,7 +2402,7 @@ void Tokenizer::arraySize()
if (addlength || Token::Match(tok, "%var% [ ] = %str% ;")) { if (addlength || Token::Match(tok, "%var% [ ] = %str% ;")) {
tok = tok->next(); tok = tok->next();
std::size_t sz = tok->strAt(3).length() - 1; std::size_t sz = tok->strAt(3).length() - 1;
tok->insertToken(MathLib::toString<unsigned int>((unsigned int)sz)); tok->insertToken(MathLib::longToString((unsigned int)sz));
addlength = false; addlength = false;
tok = tok->tokAt(5); tok = tok->tokAt(5);
} }
@ -2428,7 +2428,7 @@ void Tokenizer::arraySize()
} }
if (sz != 0) if (sz != 0)
tok->insertToken(MathLib::toString<unsigned int>(sz)); tok->insertToken(MathLib::longToString(sz));
tok = end->next() ? end->next() : end; tok = end->next() ? end->next() : end;
} }
@ -2500,7 +2500,7 @@ void Tokenizer::simplifyTemplates()
Token * const tok3 = tok->next(); Token * const tok3 = tok->next();
const unsigned int sizeOfResult = sizeOfType(tok3->tokAt(3)); const unsigned int sizeOfResult = sizeOfType(tok3->tokAt(3));
tok3->deleteNext(4); tok3->deleteNext(4);
tok3->insertToken(MathLib::toString<unsigned int>(sizeOfResult)); tok3->insertToken(MathLib::longToString(sizeOfResult));
} }
} }
@ -3057,7 +3057,7 @@ bool Tokenizer::simplifySizeof()
continue; continue;
} }
sizeOfVar[varId] = MathLib::toString<unsigned int>(size); sizeOfVar[varId] = MathLib::longToString(size);
} }
else if (Token::Match(tok->tokAt(-3), "[;{}(,] struct %type% %var% [;,)]")) { else if (Token::Match(tok->tokAt(-3), "[;{}(,] struct %type% %var% [;,)]")) {
@ -3070,14 +3070,14 @@ bool Tokenizer::simplifySizeof()
if (size == 0) if (size == 0)
continue; continue;
sizeOfVar[varId] = MathLib::toString<unsigned long>(size * static_cast<unsigned long>(MathLib::toLongNumber(tok->strAt(2)))); sizeOfVar[varId] = MathLib::longToString(size * static_cast<unsigned long>(MathLib::toLongNumber(tok->strAt(2))));
} }
else if (Token::Match(tok->previous(), "%type% %var% [ %num% ] [,)]") || else if (Token::Match(tok->previous(), "%type% %var% [ %num% ] [,)]") ||
Token::Match(tok->tokAt(-2), "%type% * %var% [ %num% ] [,)]")) { Token::Match(tok->tokAt(-2), "%type% * %var% [ %num% ] [,)]")) {
Token tempTok(0); Token tempTok(0);
tempTok.str("*"); tempTok.str("*");
sizeOfVar[varId] = MathLib::toString<unsigned long>(sizeOfType(&tempTok)); sizeOfVar[varId] = MathLib::longToString(sizeOfType(&tempTok));
} }
else if (Token::Match(tok->previous(), "%type% %var% [ ] = %str% ;")) { else if (Token::Match(tok->previous(), "%type% %var% [ ] = %str% ;")) {
@ -3085,7 +3085,7 @@ bool Tokenizer::simplifySizeof()
if (size == 0) if (size == 0)
continue; continue;
sizeOfVar[varId] = MathLib::toString<unsigned int>(size); sizeOfVar[varId] = MathLib::longToString(size);
} }
} }
} }
@ -3216,7 +3216,7 @@ bool Tokenizer::simplifySizeof()
} }
if (Token::simpleMatch(tok->next(), "( * )")) { if (Token::simpleMatch(tok->next(), "( * )")) {
tok->str(MathLib::toString<unsigned long>(sizeOfType(tok->tokAt(2)))); tok->str(MathLib::longToString(sizeOfType(tok->tokAt(2))));
tok->deleteNext(3); tok->deleteNext(3);
ret = true; ret = true;
} }
@ -3238,7 +3238,7 @@ bool Tokenizer::simplifySizeof()
else if (Token::Match(tok, "sizeof ( %type% )")) { else if (Token::Match(tok, "sizeof ( %type% )")) {
unsigned int size = sizeOfType(tok->tokAt(2)); unsigned int size = sizeOfType(tok->tokAt(2));
if (size > 0) { if (size > 0) {
tok->str(MathLib::toString<unsigned int>(size)); tok->str(MathLib::longToString(size));
tok->deleteNext(3); tok->deleteNext(3);
ret = true; ret = true;
} }
@ -3267,7 +3267,7 @@ bool Tokenizer::simplifySizeof()
} }
if (sz > 0) { if (sz > 0) {
tok->str(MathLib::toString<size_t>(sz)); tok->str(MathLib::longToString(sz));
Token::eraseTokens(tok, tok->next()->link()->next()); Token::eraseTokens(tok, tok->next()->link()->next());
ret = true; ret = true;
} }
@ -3885,7 +3885,7 @@ void Tokenizer::removeRedundantFor()
// get the correct end value // get the correct end value
Token *tok2 = tok->next()->link(); Token *tok2 = tok->next()->link();
tok2->insertToken(";"); tok2->insertToken(";");
tok2->insertToken(MathLib::toString(num2)); tok2->insertToken(MathLib::longToString(num2));
tok2->insertToken("="); tok2->insertToken("=");
tok2->insertToken(varname); tok2->insertToken(varname);
tok2->next()->varId(varid); tok2->next()->varId(varid);
@ -6058,7 +6058,7 @@ bool Tokenizer::simplifyKnownVariablesGetData(unsigned int varid, Token **_tok2,
value = tok2->strAt(6); value = tok2->strAt(6);
valueVarId = tok2->tokAt(6)->varId(); valueVarId = tok2->tokAt(6)->varId();
} else } else
value = MathLib::toString(MathLib::toLongNumber(tok2->strAt(6)) + 1); value = MathLib::longToString(MathLib::toLongNumber(tok2->strAt(6)) + 1);
// Skip for-body.. // Skip for-body..
tok3 = tok2->previous()->link()->next()->link()->next(); tok3 = tok2->previous()->link()->next()->link()->next();
@ -7199,7 +7199,7 @@ void Tokenizer::simplifyEnum()
enumValueEnd = tok1->next(); enumValueEnd = tok1->next();
} else { } else {
// value is previous numeric value + 1 // value is previous numeric value + 1
tok1->insertToken(MathLib::toString<MathLib::bigint>(lastValue)); tok1->insertToken(MathLib::longToString(lastValue));
enumValue = tok1->next(); enumValue = tok1->next();
} }
} else if (Token::Match(tok1->previous(), ",|{ %type% = %num% ,|}")) { } else if (Token::Match(tok1->previous(), ",|{ %type% = %num% ,|}")) {
@ -7816,7 +7816,7 @@ void Tokenizer::simplifyMathFunctions()
tok->deleteThis(); tok->deleteThis();
// Convert string into a number // Convert string into a number
tok->str(MathLib::toString(MathLib::toLongNumber(tok->strValue()))); tok->str(MathLib::longToString(MathLib::toLongNumber(tok->strValue())));
// Delete remaining ) // Delete remaining )
tok->deleteNext(); tok->deleteNext();
@ -8376,7 +8376,7 @@ void Tokenizer::simplifyStructDecl()
if (Token::Match(tok->next(), "*|&| %type% ,|;|[")) { if (Token::Match(tok->next(), "*|&| %type% ,|;|[")) {
std::string name; std::string name;
name = "Anonymous" + MathLib::toString<unsigned int>(count++); name = "Anonymous" + MathLib::longToString(count++);
tok1->insertToken(name); tok1->insertToken(name);

View File

@ -83,21 +83,21 @@ private:
ASSERT_EQUALS("256", MathLib::add("0xff", "1")); ASSERT_EQUALS("256", MathLib::add("0xff", "1"));
ASSERT_EQUALS("249", MathLib::add("250", "-1")); ASSERT_EQUALS("249", MathLib::add("250", "-1"));
ASSERT_EQUALS("251", MathLib::add("250", "1")); ASSERT_EQUALS("251", MathLib::add("250", "1"));
ASSERT_EQUALS("-2" , MathLib::add("-1.", "-1")); ASSERT_EQUALS("-2.0" , MathLib::add("-1.", "-1"));
ASSERT_EQUALS("-1" , MathLib::add("0", "-1")); ASSERT_EQUALS("-1" , MathLib::add("0", "-1"));
ASSERT_EQUALS("1" , MathLib::add("1", "0")); ASSERT_EQUALS("1" , MathLib::add("1", "0"));
ASSERT_EQUALS("0" , MathLib::add("0", "0.")); ASSERT_EQUALS("0.0" , MathLib::add("0", "0."));
ASSERT_EQUALS("1.0000001" , MathLib::add("1", "0.00000001")); // #4016 ASSERT_EQUALS("1.00000001" , MathLib::add("1", "0.00000001")); // #4016
ASSERT_EQUALS("30666.22" , MathLib::add("30666.22", "0.0")); // #4068 ASSERT_EQUALS("30666.22" , MathLib::add("30666.22", "0.0")); // #4068
// subtraction // subtraction
ASSERT_EQUALS("254", MathLib::subtract("0xff", "1")); ASSERT_EQUALS("254", MathLib::subtract("0xff", "1"));
ASSERT_EQUALS("251", MathLib::subtract("250", "-1")); ASSERT_EQUALS("251", MathLib::subtract("250", "-1"));
ASSERT_EQUALS("249", MathLib::subtract("250", "1")); ASSERT_EQUALS("249", MathLib::subtract("250", "1"));
ASSERT_EQUALS("0" , MathLib::subtract("-1.", "-1")); ASSERT_EQUALS("0.0" , MathLib::subtract("-1.", "-1"));
ASSERT_EQUALS("1" , MathLib::subtract("0", "-1")); ASSERT_EQUALS("1" , MathLib::subtract("0", "-1"));
ASSERT_EQUALS("1" , MathLib::subtract("1", "0")); ASSERT_EQUALS("1" , MathLib::subtract("1", "0"));
ASSERT_EQUALS("0" , MathLib::subtract("0", "0.")); ASSERT_EQUALS("0.0" , MathLib::subtract("0", "0."));
ASSERT_EQUALS("0.99999999" , MathLib::subtract("1", "0.00000001")); // #4016 ASSERT_EQUALS("0.99999999" , MathLib::subtract("1", "0.00000001")); // #4016
ASSERT_EQUALS("30666.22" , MathLib::subtract("30666.22", "0.0")); // #4068 ASSERT_EQUALS("30666.22" , MathLib::subtract("30666.22", "0.0")); // #4068
ASSERT_EQUALS("0.0" , MathLib::subtract("0.0", "0.0")); ASSERT_EQUALS("0.0" , MathLib::subtract("0.0", "0.0"));
@ -107,11 +107,10 @@ private:
ASSERT_EQUALS("-11.96" , MathLib::multiply("-2.3", "5.2")); ASSERT_EQUALS("-11.96" , MathLib::multiply("-2.3", "5.2"));
ASSERT_EQUALS("3000" , MathLib::multiply("1E3", "3")); ASSERT_EQUALS("3000" , MathLib::multiply("1E3", "3"));
ASSERT_EQUALS("3000" , MathLib::multiply("1E+3", "3")); ASSERT_EQUALS("3000" , MathLib::multiply("1E+3", "3"));
ASSERT_EQUALS("3000" , MathLib::multiply("1.0E3", "3")); ASSERT_EQUALS("3000.0" , MathLib::multiply("1.0E3", "3"));
ASSERT_EQUALS("-3000" , MathLib::multiply("-1.0E3", "3")); ASSERT_EQUALS("-3000.0" , MathLib::multiply("-1.0E3", "3"));
ASSERT_EQUALS("-3000" , MathLib::multiply("-1.0E+3", "3")); ASSERT_EQUALS("-3000.0" , MathLib::multiply("-1.0E+3", "3"));
ASSERT_EQUALS("0" , MathLib::multiply("-1.0E+3", "0")); ASSERT_EQUALS("0.0" , MathLib::multiply("+1.0E+3", "0"));
ASSERT_EQUALS("0" , MathLib::multiply("+1.0E+3", "0"));
ASSERT_EQUALS("2147483648" , MathLib::multiply("2","1073741824")); ASSERT_EQUALS("2147483648" , MathLib::multiply("2","1073741824"));
ASSERT_EQUALS("536870912" , MathLib::multiply("512","1048576")); ASSERT_EQUALS("536870912" , MathLib::multiply("512","1048576"));
@ -121,8 +120,8 @@ private:
ASSERT_EQUALS("5" , MathLib::divide("-10", "-2")); ASSERT_EQUALS("5" , MathLib::divide("-10", "-2"));
ASSERT_EQUALS("-2.5", MathLib::divide("-10.", "4")); ASSERT_EQUALS("-2.5", MathLib::divide("-10.", "4"));
ASSERT_EQUALS("2.5" , MathLib::divide("-10.", "-4")); ASSERT_EQUALS("2.5" , MathLib::divide("-10.", "-4"));
ASSERT_EQUALS("5" , MathLib::divide("25.5", "5.1")); ASSERT_EQUALS("5.0" , MathLib::divide("25.5", "5.1"));
ASSERT_EQUALS("7" , MathLib::divide("21.", "3")); ASSERT_EQUALS("7.0" , MathLib::divide("21.", "3"));
ASSERT_EQUALS("1" , MathLib::divide("3", "2")); ASSERT_EQUALS("1" , MathLib::divide("3", "2"));
ASSERT_THROW(MathLib::divide("123", "0"), InternalError); // throw ASSERT_THROW(MathLib::divide("123", "0"), InternalError); // throw
MathLib::divide("123", "0.0"); // don't throw MathLib::divide("123", "0.0"); // don't throw
@ -133,10 +132,10 @@ private:
void calculate1() const { // mod void calculate1() const { // mod
ASSERT_EQUALS("0" , MathLib::calculate("2" , "1" , '%')); ASSERT_EQUALS("0" , MathLib::calculate("2" , "1" , '%'));
ASSERT_EQUALS("0" , MathLib::calculate("2.0" , "1.0" , '%')); ASSERT_EQUALS("0.0" , MathLib::calculate("2.0" , "1.0" , '%'));
ASSERT_EQUALS("2" , MathLib::calculate("12" , "5" , '%')); ASSERT_EQUALS("2" , MathLib::calculate("12" , "5" , '%'));
ASSERT_EQUALS("1" , MathLib::calculate("100" , "3" , '%')); ASSERT_EQUALS("1" , MathLib::calculate("100" , "3" , '%'));
ASSERT_EQUALS("12" , MathLib::calculate("12.0" , "13.0" , '%')); ASSERT_EQUALS("12.0" , MathLib::calculate("12.0" , "13.0" , '%'));
ASSERT_EQUALS("1.3" , MathLib::calculate("5.3" , "2.0" , '%')); ASSERT_EQUALS("1.3" , MathLib::calculate("5.3" , "2.0" , '%'));
ASSERT_EQUALS("1.7" , MathLib::calculate("18.5" , "4.2" , '%')); ASSERT_EQUALS("1.7" , MathLib::calculate("18.5" , "4.2" , '%'));
ASSERT_THROW(MathLib::calculate("123", "0", '%'), InternalError); // throw ASSERT_THROW(MathLib::calculate("123", "0", '%'), InternalError); // throw
@ -149,47 +148,47 @@ private:
// ------------------ // ------------------
// from hex // from hex
ASSERT_EQUALS(10 , MathLib::toLongNumber("0xa")); ASSERT_EQUALS(10 , MathLib::toLongNumber("0xa"));
ASSERT_EQUALS(10995 , MathLib::toLongNumber("0x2AF3")); ASSERT_EQUALS(10995 , MathLib::toLongNumber("0x2AF3"));
ASSERT_EQUALS(-10 , MathLib::toLongNumber("-0xa")); ASSERT_EQUALS(-10 , MathLib::toLongNumber("-0xa"));
ASSERT_EQUALS(-10995, MathLib::toLongNumber("-0x2AF3")); ASSERT_EQUALS(-10995, MathLib::toLongNumber("-0x2AF3"));
ASSERT_EQUALS(10 , MathLib::toLongNumber("+0xa")); ASSERT_EQUALS(10 , MathLib::toLongNumber("+0xa"));
ASSERT_EQUALS(10995 , MathLib::toLongNumber("+0x2AF3")); ASSERT_EQUALS(10995 , MathLib::toLongNumber("+0x2AF3"));
// from octal // from octal
ASSERT_EQUALS(8 , MathLib::toLongNumber("010")); ASSERT_EQUALS(8 , MathLib::toLongNumber("010"));
ASSERT_EQUALS(8 , MathLib::toLongNumber("+010")); ASSERT_EQUALS(8 , MathLib::toLongNumber("+010"));
ASSERT_EQUALS(-8 , MathLib::toLongNumber("-010")); ASSERT_EQUALS(-8 , MathLib::toLongNumber("-010"));
ASSERT_EQUALS(125 , MathLib::toLongNumber("0175")); ASSERT_EQUALS(125 , MathLib::toLongNumber("0175"));
ASSERT_EQUALS(125 , MathLib::toLongNumber("+0175")); ASSERT_EQUALS(125 , MathLib::toLongNumber("+0175"));
ASSERT_EQUALS(-125 , MathLib::toLongNumber("-0175")); ASSERT_EQUALS(-125 , MathLib::toLongNumber("-0175"));
// from binary // from binary
ASSERT_EQUALS(0 , MathLib::toLongNumber("0b0")); ASSERT_EQUALS(0 , MathLib::toLongNumber("0b0"));
ASSERT_EQUALS(1 , MathLib::toLongNumber("0b1")); ASSERT_EQUALS(1 , MathLib::toLongNumber("0b1"));
ASSERT_EQUALS(1 , MathLib::toLongNumber("+0b1")); ASSERT_EQUALS(1 , MathLib::toLongNumber("+0b1"));
ASSERT_EQUALS(-1 , MathLib::toLongNumber("-0b1")); ASSERT_EQUALS(-1 , MathLib::toLongNumber("-0b1"));
ASSERT_EQUALS(215 , MathLib::toLongNumber("0b11010111")); ASSERT_EQUALS(215 , MathLib::toLongNumber("0b11010111"));
ASSERT_EQUALS(-215 , MathLib::toLongNumber("-0b11010111")); ASSERT_EQUALS(-215 , MathLib::toLongNumber("-0b11010111"));
ASSERT_EQUALS(215 , MathLib::toLongNumber("0B11010111")); ASSERT_EQUALS(215 , MathLib::toLongNumber("0B11010111"));
// from base 10 // from base 10
ASSERT_EQUALS(10 , MathLib::toLongNumber("10")); ASSERT_EQUALS(10 , MathLib::toLongNumber("10"));
ASSERT_EQUALS(10 , MathLib::toLongNumber("10.")); ASSERT_EQUALS(10 , MathLib::toLongNumber("10."));
ASSERT_EQUALS(10 , MathLib::toLongNumber("10.0")); ASSERT_EQUALS(10 , MathLib::toLongNumber("10.0"));
ASSERT_EQUALS(100 , MathLib::toLongNumber("10E+1")); ASSERT_EQUALS(100 , MathLib::toLongNumber("10E+1"));
ASSERT_EQUALS(1 , MathLib::toLongNumber("10E-1")); ASSERT_EQUALS(1 , MathLib::toLongNumber("10E-1"));
ASSERT_EQUALS(100 , MathLib::toLongNumber("+10E+1")); ASSERT_EQUALS(100 , MathLib::toLongNumber("+10E+1"));
ASSERT_EQUALS(-1 , MathLib::toLongNumber("-10E-1")); ASSERT_EQUALS(-1 , MathLib::toLongNumber("-10E-1"));
ASSERT_EQUALS(100 , MathLib::toLongNumber("+10.E+1")); ASSERT_EQUALS(100 , MathLib::toLongNumber("+10.E+1"));
ASSERT_EQUALS(-1 , MathLib::toLongNumber("-10.E-1")); ASSERT_EQUALS(-1 , MathLib::toLongNumber("-10.E-1"));
ASSERT_EQUALS(100 , MathLib::toLongNumber("+10.0E+1")); ASSERT_EQUALS(100 , MathLib::toLongNumber("+10.0E+1"));
ASSERT_EQUALS(-1 , MathLib::toLongNumber("-10.0E-1")); ASSERT_EQUALS(-1 , MathLib::toLongNumber("-10.0E-1"));
// ----------------- // -----------------
// to double number: // to double number:
// ----------------- // -----------------
ASSERT_EQUALS_DOUBLE(10.0 , MathLib::toDoubleNumber("10")); ASSERT_EQUALS_DOUBLE(10.0 , MathLib::toDoubleNumber("10"));
ASSERT_EQUALS_DOUBLE(1000.0, MathLib::toDoubleNumber("10E+2")); ASSERT_EQUALS_DOUBLE(1000.0, MathLib::toDoubleNumber("10E+2"));
ASSERT_EQUALS_DOUBLE(100.0 , MathLib::toDoubleNumber("1.0E+2")); ASSERT_EQUALS_DOUBLE(100.0 , MathLib::toDoubleNumber("1.0E+2"));
ASSERT_EQUALS_DOUBLE(-100.0, MathLib::toDoubleNumber("-1.0E+2")); ASSERT_EQUALS_DOUBLE(-100.0, MathLib::toDoubleNumber("-1.0E+2"));