Skip to content

Commit

Permalink
[DLG] Changed string_to_double_vector, it can now read nans and infs
Browse files Browse the repository at this point in the history
  • Loading branch information
diegolodares committed Dec 30, 2023
1 parent b99a5b1 commit 6fc9431
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 35 deletions.
17 changes: 13 additions & 4 deletions lion/foundation/string_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,19 @@ inline std::string num2str(const T &num)
// maintaining the precision of the number's type.
//

std::ostringstream ss;
ss.precision(std::numeric_limits<T>::max_digits10);
ss << num;
return ss.str();
if constexpr (std::is_integral_v<T>) {
// integral types don't have decimal places
return std::to_string(num);
}
else {
// floating-point types go with their max. decimal precision
static_assert(std::is_floating_point_v<T>);

std::ostringstream ss;
ss.precision(std::numeric_limits<T>::max_digits10);
ss << num;
return ss.str();
}
}

template<typename It>
Expand Down
41 changes: 26 additions & 15 deletions lion/foundation/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
constexpr double& Value(double& val);
constexpr const double& Value(const double& val);


inline bool to_bool(const std::string &str)
{
if (str == "1") {
Expand Down Expand Up @@ -89,24 +90,34 @@ constexpr T wrap_to_180(T ang);
template<typename T>
constexpr T wrap_to_360(T ang);

template<typename scalar_type = double>
inline std::vector<scalar_type> string_to_double_vector(std::string s)

template<typename T = double,
typename std::enable_if_t<std::is_floating_point_v<T> >* = nullptr>
inline std::vector<T> string_to_double_vector(std::string str)
{
std::vector<scalar_type> result;
s = std::regex_replace(s, std::regex(","), " ");
s = std::regex_replace(s, std::regex("\n"), " ");
std::string::size_type sz;
while ( s.find_first_of("0123456789") != std::string::npos )
{
if constexpr (std::is_same_v<scalar_type,double>)
result.push_back(std::stod(s,&sz));
else if constexpr (std::is_same_v<scalar_type,float>)
result.push_back(std::stof(s,&sz));

s = s.substr(sz);
std::vector<T> ret;
while (true) {
const auto str_length = str.length();
if (str_length == 0u) {
break;
}

std::size_t pos;
if constexpr (std::is_same_v<T, double>) {
ret.push_back(std::stod(str, &pos));
}
else {
static_assert(std::is_same_v<T, float>);
ret.push_back(std::stof(str, &pos));
}

while (pos != str_length && (str[pos] == ',' || str[pos] == ';' || str[pos] == '\n')) {
++pos;
}
str = str.substr(pos);
}

return result;
return ret;
}


Expand Down
19 changes: 13 additions & 6 deletions lion/foundation/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ constexpr T smooth_neg(const T &x, S eps2)
}


template<bool ActuallySmooth, bool UseSinAtanFormula, typename T, typename S>
template<bool ActuallySmooth, bool UseSmoothAbsFormula, typename T, typename S>
constexpr T smooth_sign(const T &x, S eps)
{
//
Expand All @@ -235,7 +235,7 @@ constexpr T smooth_sign(const T &x, S eps)
//

if constexpr (ActuallySmooth) {
if constexpr (UseSinAtanFormula) {
if constexpr (UseSmoothAbsFormula) {

return x / smooth_abs(x, eps * eps);
}
Expand All @@ -244,6 +244,13 @@ constexpr T smooth_sign(const T &x, S eps)

return tanh(x / eps);
}

// another one that we used before, "sinatan", I leave it
// commented here to not lose it
//using std::sin;
//using std::atan;
//return sin(atan(x / eps));

}
else {
(void)eps;
Expand All @@ -253,7 +260,7 @@ constexpr T smooth_sign(const T &x, S eps)
}


template<bool ActuallySmooth, bool UseSinAtanFormula, typename T, typename S>
template<bool ActuallySmooth, bool UseSmoothAbsFormula, typename T, typename S>
constexpr T smooth_sign_derivative(const T &x, S eps)
{
//
Expand All @@ -264,7 +271,7 @@ constexpr T smooth_sign_derivative(const T &x, S eps)
//

if constexpr (ActuallySmooth) {
if constexpr (UseSinAtanFormula) {
if constexpr (UseSmoothAbsFormula) {
using std::sqrt;

return eps * eps / ((eps * eps + x * x) * sqrt(eps * eps + x * x));
Expand Down Expand Up @@ -398,7 +405,7 @@ constexpr T smooth_clamp(const T &x, const T1 &lo, const T2 &hi, S eps2)
}
}

template<bool ActuallySmooth, bool UseSinAtanFormula, typename T, typename S>
template<bool ActuallySmooth, bool UseSmoothAbsFormula, typename T, typename S>
constexpr T smooth_step(const T &x, S eps)
{
//
Expand All @@ -409,7 +416,7 @@ constexpr T smooth_step(const T &x, S eps)
//

if constexpr (ActuallySmooth) {
return S{ 0.5 } * (S{ 1 } + smooth_sign<ActuallySmooth, UseSinAtanFormula>(x, eps));
return S{ 0.5 } * (S{ 1 } + smooth_sign<ActuallySmooth, UseSmoothAbsFormula>(x, eps));
}
else {
return x >= S{ 0 } ? T{ 1 } : T{ 0 };
Expand Down
37 changes: 27 additions & 10 deletions test/foundation/utils_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,34 @@

TEST(utils_test, string_to_double_vector)
{
const std::string s = "1.02324355, 5.0624692 \n -7.354634, \n 5.23035234392, 243.242532425";

std::vector<double> v = string_to_double_vector(s);

std::vector<double> v_expected = { 1.02324355,5.0624692,-7.354634,5.23035234392,243.242532425 };

EXPECT_EQ(v.size(), v_expected.size());

for (size_t i = 0; i < v.size(); ++i)
EXPECT_DOUBLE_EQ(v[i], v_expected[i]);
{
const std::string s = "1.02324355, 5.0624692 \n -7.354634, \n 5.23035234392, 243.242532425";
std::vector<double> v = string_to_double_vector(s);
std::vector<double> v_expected = { 1.02324355,5.0624692,-7.354634,5.23035234392,243.242532425 };
EXPECT_EQ(v.size(), v_expected.size());
for (size_t i = 0; i < v.size(); ++i)
EXPECT_DOUBLE_EQ(v[i], v_expected[i]);
}

{
const std::string s = "nan 1.02324355; \n INF, NAN, Inf, Nan, \n 1.897989, 33, inf";
std::vector<double> v = string_to_double_vector(s);
const auto nan = std::numeric_limits<double>::quiet_NaN();
const auto inf = std::numeric_limits<double>::infinity();
std::vector<double> v_expected = { nan, 1.02324355, inf, nan, inf, nan, 1.897989, 33, inf };
ASSERT_EQ(v.size(), v_expected.size());
for (size_t i = 0; i < v.size(); ++i) {
if (std::isnan(v_expected[i])) {
EXPECT_TRUE(std::isnan(v[i]));
}
else if (std::isinf(v_expected[i])) {
EXPECT_TRUE(std::isinf(v[i]));
}
else {
EXPECT_EQ(v[i], v_expected[i]);
}
}
}
}

TEST(utils_test, linspace)
Expand Down

0 comments on commit 6fc9431

Please sign in to comment.