[gem5-dev] Change in gem5/gem5[develop]: base: Fix scientific number conversion in base/str

2021-02-19 Thread Daniel Carvalho (Gerrit) via gem5-dev
Daniel Carvalho has submitted this change. (  
https://gem5-review.googlesource.com/c/public/gem5/+/38775 )


Change subject: base: Fix scientific number conversion in base/str
..

base: Fix scientific number conversion in base/str

Previously converting scientific numbers to non-floating
numbers would yield incorrect results, because the
underlying conversion was using stoll and stoull, which
do not deal with scientific numbers properly. Therefore,
converting to_number("8.234e+08", val) would yield
val=8, which is blatantly wrong (expected 82340).

This was fixed by searching for "e" within the string to
be converted.

To make sure all double and scientific number conversions
are correct, a few extra tests were added.

Change-Id: I6a9599d8473909d274326b6f8c268e3603044ab4
Signed-off-by: Daniel R. Carvalho 
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/38775
Reviewed-by: Bobby R. Bruce 
Maintainer: Bobby R. Bruce 
Tested-by: kokoro 
---
M src/base/str.hh
M src/base/str.test.cc
2 files changed, 74 insertions(+), 0 deletions(-)

Approvals:
  Bobby R. Bruce: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass



diff --git a/src/base/str.hh b/src/base/str.hh
index 40fd780..d91761d 100644
--- a/src/base/str.hh
+++ b/src/base/str.hh
@@ -112,6 +112,10 @@
   std::is_signed::value, T>
 __to_number(const std::string &value)
 {
+// Cannot parse scientific numbers
+if (value.find('e') != std::string::npos) {
+throw std::invalid_argument("Cannot convert scientific to  
integral");

+}
 // start big and narrow it down if needed, determine the base  
dynamically

 long long r = std::stoll(value, nullptr, 0);
 if (r < std::numeric_limits::lowest()
@@ -126,6 +130,10 @@
   !std::is_signed::value, T>
 __to_number(const std::string &value)
 {
+// Cannot parse scientific numbers
+if (value.find('e') != std::string::npos) {
+throw std::invalid_argument("Cannot convert scientific to  
integral");

+}
 // start big and narrow it down if needed, determine the base  
dynamically

 unsigned long long r = std::stoull(value, nullptr, 0);
 if (r > std::numeric_limits::max())
@@ -137,6 +145,10 @@
 typename std::enable_if_t::value, T>
 __to_number(const std::string &value)
 {
+// Cannot parse scientific numbers
+if (value.find('e') != std::string::npos) {
+throw std::invalid_argument("Cannot convert scientific to  
integral");

+}
 auto r = __to_number::type>(value);
 return static_cast(r);
 }
diff --git a/src/base/str.test.cc b/src/base/str.test.cc
index f0cd483..d3cbc3d 100644
--- a/src/base/str.test.cc
+++ b/src/base/str.test.cc
@@ -285,6 +285,58 @@
 EXPECT_FALSE(to_number(input, output));
 }

+/** Test that a double that can be converted to int is always rounded  
down. */

+TEST(StrTest, ToNumberUnsigned8BitIntRoundDown)
+{
+uint8_t output;
+std::string input_1 = "2.99";
+EXPECT_TRUE(to_number(input_1, output));
+EXPECT_EQ(2, output);
+
+std::string input_2 = "3.99";
+EXPECT_TRUE(to_number(input_2, output));
+EXPECT_EQ(3, output);
+}
+
+/**
+ * Test that a double can still be converted to int as long as it is below
+ * the numerical limit + 1.
+ */
+TEST(StrTest, ToNumber8BitUnsignedLimit)
+{
+uint8_t output;
+std::string input = "255.99";
+EXPECT_TRUE(to_number(input, output));
+EXPECT_EQ(255, output);
+}
+
+/**
+ * Test that a double cannot be converted to int when it passes the  
numerical

+ * limit.
+ */
+TEST(StrTest, ToNumber8BitUnsignedOutOfRange)
+{
+uint8_t output;
+std::string input = "256.99";
+EXPECT_FALSE(to_number(input, output));
+}
+
+/** Test that a scientific number cannot be converted to int. */
+TEST(StrTest, ToNumberUnsignedScientific)
+{
+uint32_t output;
+std::string input = "8.234e+08";
+EXPECT_FALSE(to_number(input, output));
+}
+
+/** Test that a negative scientific number cannot be converted to int. */
+TEST(StrTest, ToNumberIntScientificNegative)
+{
+int32_t output;
+std::string input = "-8.234e+08";
+EXPECT_FALSE(to_number(input, output));
+}
+
 TEST(StrTest, ToNumber64BitInt)
 {
 int64_t output;
@@ -379,6 +431,16 @@
 EXPECT_EQ(expected_output, output);
 }

+/** Test that a scientific number is converted properly to double. */
+TEST(StrTest, ToNumberScientific)
+{
+double output;
+std::string input = "8.234e+08";
+double expected_output = 82340;
+EXPECT_TRUE(to_number(input, output));
+EXPECT_EQ(expected_output, output);
+}
+
 /*
  * The "to_bool" function takes a string, "true" or "false"
  * (case-insenstive), and sets the second argument to the bool equivilent.



5 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the  
submitted one.

--
To view, visit https://gem5-review.googleso

[gem5-dev] Change in gem5/gem5[develop]: base: Fix scientific number conversion in base/str

2021-02-12 Thread Daniel Carvalho (Gerrit) via gem5-dev
Daniel Carvalho has uploaded this change for review. (  
https://gem5-review.googlesource.com/c/public/gem5/+/41333 )



Change subject: base: Fix scientific number conversion in base/str
..

base: Fix scientific number conversion in base/str

Previously converting scientific numbers to non-floating
numbers would yield incorrect results, because the
underlying conversion was using stoll and stoull, which
do not deal with scientific numbers properly. Therefore,
converting to_number("8.234e+08", val) would yield
val=8, which is blatantly wrong (expected 82340).

This was fixed by searching for "e" within the string to
be converted.

To make sure all double and scientific number conversions
are correct, a few extra tests were added.

Change-Id: I6a9599d8473909d274326b6f8c268e3603044ab4
Signed-off-by: Daniel R. Carvalho 

base: fixup

Change-Id: I7191c8b591f26db0eb6a4ac63a4998ed442a94dc

base: fixup

Change-Id: I35adc188ec958d7c5a4de97121f28a7c3145c132
---
M src/base/str.hh
M src/base/str.test.cc
2 files changed, 74 insertions(+), 0 deletions(-)



diff --git a/src/base/str.hh b/src/base/str.hh
index 40fd780..d91761d 100644
--- a/src/base/str.hh
+++ b/src/base/str.hh
@@ -112,6 +112,10 @@
   std::is_signed::value, T>
 __to_number(const std::string &value)
 {
+// Cannot parse scientific numbers
+if (value.find('e') != std::string::npos) {
+throw std::invalid_argument("Cannot convert scientific to  
integral");

+}
 // start big and narrow it down if needed, determine the base  
dynamically

 long long r = std::stoll(value, nullptr, 0);
 if (r < std::numeric_limits::lowest()
@@ -126,6 +130,10 @@
   !std::is_signed::value, T>
 __to_number(const std::string &value)
 {
+// Cannot parse scientific numbers
+if (value.find('e') != std::string::npos) {
+throw std::invalid_argument("Cannot convert scientific to  
integral");

+}
 // start big and narrow it down if needed, determine the base  
dynamically

 unsigned long long r = std::stoull(value, nullptr, 0);
 if (r > std::numeric_limits::max())
@@ -137,6 +145,10 @@
 typename std::enable_if_t::value, T>
 __to_number(const std::string &value)
 {
+// Cannot parse scientific numbers
+if (value.find('e') != std::string::npos) {
+throw std::invalid_argument("Cannot convert scientific to  
integral");

+}
 auto r = __to_number::type>(value);
 return static_cast(r);
 }
diff --git a/src/base/str.test.cc b/src/base/str.test.cc
index a064a87..d1d1677 100644
--- a/src/base/str.test.cc
+++ b/src/base/str.test.cc
@@ -285,6 +285,58 @@
 EXPECT_FALSE(to_number(input, output));
 }

+/** Test that a double that can be converted to int is always rounded  
down. */

+TEST(StrTest, ToNumberUnsigned8BitIntRoundDown)
+{
+uint8_t output;
+std::string input_1 = "2.99";
+EXPECT_TRUE(to_number(input_1, output));
+EXPECT_EQ(2, output);
+
+std::string input_2 = "3.99";
+EXPECT_TRUE(to_number(input_2, output));
+EXPECT_EQ(3, output);
+}
+
+/**
+ * Test that a double can still be converted to int as long as it is below
+ * the numerical limit + 1.
+ */
+TEST(StrTest, ToNumber8BitUnsignedLimit)
+{
+uint8_t output;
+std::string input = "255.99";
+EXPECT_TRUE(to_number(input, output));
+EXPECT_EQ(255, output);
+}
+
+/**
+ * Test that a double cannot be converted to int when it passes the  
numerical

+ * limit.
+ */
+TEST(StrTest, ToNumber8BitUnsignedOutOfRange)
+{
+uint8_t output;
+std::string input = "256.99";
+EXPECT_FALSE(to_number(input, output));
+}
+
+/** Test that a scientific number cannot be converted to int. */
+TEST(StrTest, ToNumberUnsignedScientific)
+{
+uint32_t output;
+std::string input = "8.234e+08";
+EXPECT_FALSE(to_number(input, output));
+}
+
+/** Test that a negative scientific number cannot be converted to int. */
+TEST(StrTest, ToNumberIntScientificNegative)
+{
+int32_t output;
+std::string input = "-8.234e+08";
+EXPECT_FALSE(to_number(input, output));
+}
+
 TEST(StrTest, ToNumber64BitInt)
 {
 int64_t output;
@@ -355,6 +407,16 @@
 EXPECT_EQ(expected_output, output);
 }

+/** Test that a scientific number is converted properly to double. */
+TEST(StrTest, ToNumberScientific)
+{
+double output;
+std::string input = "8.234e+08";
+double expected_output = 82340;
+EXPECT_TRUE(to_number(input, output));
+EXPECT_EQ(expected_output, output);
+}
+
 /*
  * The "to_bool" function takes a string, "true" or "false"
  * (case-insenstive), and sets the second argument to the bool equivilent.

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/41333
To unsubscribe, or for help writing mail filters, visit  
https://gem5-review.googlesource.com/settings


Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I35adc188ec958d7c5a4de97121f28a7c