Skip to content

Commit

Permalink
add better options for optimal string on multiplier generation (#93)
Browse files Browse the repository at this point in the history
* add better options for optimal string on multiplier generation

* Automated formatting of repo files (#94)

* add some case insensitive unit test for two character units. (#91)

* add some case insensitive unit test for two character units.

* Automated formatting of repo files (#92)

Co-authored-by: Philip Top <[email protected]>
Co-authored-by: HELICS-bot <[email protected]>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: HELICS-bot <[email protected]>

* Automated formatting of repo files

Co-authored-by: Philip Top <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: HELICS-bot <[email protected]>

* add more test for string shortening

* Automated formatting of repo files (#95)

Co-authored-by: Philip Top <[email protected]>
Co-authored-by: HELICS-bot <[email protected]>

* move some testing functions into a separate definition

* Automated formatting of repo files (#96)

Co-authored-by: Philip Top <[email protected]>
Co-authored-by: HELICS-bot <[email protected]>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: HELICS-bot <[email protected]>
  • Loading branch information
3 people authored Oct 26, 2020
1 parent e047efb commit ec86399
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 9 deletions.
4 changes: 4 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ else()
target_compile_definitions(
test_unit_strings PUBLIC -DTEST_FILE_FOLDER="${TEST_FILE_FOLDER}"
)

target_compile_definitions(test_unit_strings PUBLIC -DENABLE_UNIT_TESTING=1)
target_compile_definitions(test_leadingNumbers PUBLIC -DENABLE_UNIT_TESTING=1)

target_compile_definitions(
test_conversions2 PUBLIC -DTEST_FILE_FOLDER="${TEST_FILE_FOLDER}"
)
Expand Down
13 changes: 13 additions & 0 deletions test/test_conversions1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,4 +678,17 @@ TEST(nat_gas_units, psig)

val = convert(14.6, precise::pressure::psig, precise::pressure::atm, 14.8);
EXPECT_NEAR(val, 2.0, 0.01);

val = convert(
10,
precise_unit(2.0, precise::pressure::psig),
precise::pressure::psig);
EXPECT_NEAR(val, 20.0, 0.01);
}

TEST(invalid_conversions, invalid)
{
using namespace units;
double val = detail::extraValidConversions(2.3, precise::m, precise::lb);
EXPECT_TRUE(std::isnan(val));
}
34 changes: 34 additions & 0 deletions test/test_unit_strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -937,3 +937,37 @@ TEST(defaultUnits, singleCharacter)
EXPECT_EQ(precise::cd, default_unit("J"));
EXPECT_EQ(precise::K, default_unit("\xC8"));
}

TEST(stringGeneration, test1)
{
auto res = detail::testing::testCleanUpString(
detail::testing::testUnitSequenceGeneration(2100.0, "m^-3"), 0);
EXPECT_EQ(res, "2.1L^-1");
}

TEST(stringCleanup, test1)
{
auto res = detail::testing::testCleanUpString("0.000000045lb", 0);
EXPECT_EQ(res, "0.000000045lb");

res = detail::testing::testCleanUpString("0.0000000000000045lb", 0);
EXPECT_EQ(res, "0.0000000000000045lb");

res = detail::testing::testCleanUpString("1.00000000000009lb", 0);
EXPECT_EQ(res, "1lb");

res = detail::testing::testCleanUpString("1.00000000000019lb", 0);
EXPECT_EQ(res, "1.00000000000019lb");

res = detail::testing::testCleanUpString("1.00000009000009lb", 0);
EXPECT_EQ(res, "1.00000009lb");

res = detail::testing::testCleanUpString("100000009000009lb", 0);
EXPECT_EQ(res, "100000009000009lb");

res = detail::testing::testCleanUpString("1.0000000000000lb", 0);
EXPECT_EQ(res, "1lb");

res = detail::testing::testCleanUpString("1.0000000000000", 0);
EXPECT_EQ(res, "1");
}
5 changes: 5 additions & 0 deletions units/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ else(UNITS_HEADER_ONLY)
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_link_libraries(units-static PRIVATE compile_flags_target)

if(UNITS_ENABLE_TESTS)
target_compile_definitions(units-static PUBLIC -DENABLE_UNIT_TESTING=1)
endif()

add_library(units::units ALIAS units-static)
add_library(units::static ALIAS units-static)
if(UNITS_INSTALL)
Expand Down
129 changes: 120 additions & 9 deletions units/units.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 +439,14 @@ static std::string getMultiplierString(double multiplier, bool numOnly = false)
return std::string(1, si->second);
}
}
int X; // the exponent
int P = 18; // the desired precision

std::frexp(multiplier, &X);

std::stringstream ss;
ss << std::setprecision(18);
ss << multiplier;

ss << std::setprecision(P) << multiplier;
auto rv = ss.str();
// modify some improper strings that cause issues later on
if (rv == "inf") {
Expand All @@ -463,7 +468,7 @@ static std::string generateUnitSequence(double mux, std::string seq)
mux *= 1000.0;
}
} else if (seq.compare(0, 4, "m^-3") == 0) {
if (mux > 10.0) {
if (mux > 100.0) {
seq.replace(0, 4, "L^-1");
mux /= 1000.0;
}
Expand Down Expand Up @@ -850,7 +855,7 @@ static void escapeString(std::string& str)
}
}
// clean up the unit string and add a commodity if necessary
std::string
static std::string
clean_unit_string(std::string propUnitString, std::uint32_t commodity)
{
using spair = std::tuple<const char*, const char*, int, int>;
Expand Down Expand Up @@ -881,11 +886,103 @@ std::string
!isDigitCharacter(propUnitString.front())) {
return propUnitString;
}
// TODO(PT) do some additional number clean up if there is a number in
// front
// if (!propUnitString.empty() && isDigitCharacter(propUnitString.front()))
// {
// }

if (!propUnitString.empty() && isDigitCharacter(propUnitString.front())) {
// search for a bunch of zeros in a row
std::size_t indexingloc{0};

auto zloc = propUnitString.find("00000");
while (zloc != std::string::npos) {
indexingloc = zloc + 5;
auto nloc = propUnitString.find_first_not_of('0', zloc + 5);
if (nloc != std::string::npos) {
if (propUnitString[nloc] != '.') {
if (!isDigitCharacter(propUnitString[nloc]) ||
(propUnitString.size() > nloc + 1 &&
!isDigitCharacter(propUnitString[nloc + 1]))) {
if (isDigitCharacter(propUnitString[nloc])) {
++nloc;
}

auto dloc = propUnitString.find_last_of('.', zloc);

if (dloc != std::string::npos && dloc - nloc > 15) {
bool valid = true;
if (dloc == zloc - 1) {
--zloc;
auto ploc = dloc;
valid = false;
while (true) {
if (ploc > 0) {
--ploc;
if (!isDigitCharacter(
propUnitString[ploc])) {
break;
}
if (propUnitString[ploc] != '0') {
valid = true;
break;
}
}
}
} else {
auto ploc = dloc + 1;
while (ploc < zloc) {
if (!isDigitCharacter(
propUnitString[ploc])) {
valid = false;
break;
}
++ploc;
}
}
if (valid) {
propUnitString.erase(zloc, nloc - zloc);
indexingloc = zloc + 1;
}
}
}
}
} else {
auto dloc = propUnitString.find_last_of('.', zloc);

if (dloc != std::string::npos) {
bool valid = true;
if (dloc == zloc - 1) {
--zloc;
auto ploc = dloc;
valid = false;
while (true) {
if (ploc > 0) {
--ploc;
if (!isDigitCharacter(propUnitString[ploc])) {
break;
}
if (propUnitString[ploc] != '0') {
valid = true;
break;
}
}
}
} else {
auto ploc = dloc + 1;
while (ploc < zloc) {
if (!isDigitCharacter(propUnitString[ploc])) {
valid = false;
break;
}
++ploc;
}
}
if (valid) {
propUnitString.erase(zloc, std::string::npos);
indexingloc = zloc + 1;
}
}
}
zloc = propUnitString.find("00000", indexingloc);
}
}

if (commodity != 0) {
std::string cString = getCommodityName(
Expand Down Expand Up @@ -1839,6 +1936,7 @@ static double readNumericalWords(const std::string& ustring, size_t& index)
return val;
}

#ifdef ENABLE_UNIT_TESTING
namespace detail {
namespace testing {
// generate a number from a number sequence
Expand All @@ -1850,9 +1948,22 @@ namespace detail {
{
return readNumericalWords(test, index);
}

std::string
testUnitSequenceGeneration(double mul, const std::string& test)
{
return generateUnitSequence(mul, test);
}
std::string
testCleanUpString(std::string testString, std::uint32_t commodity)
{
return clean_unit_string(std::move(testString), commodity);
}
} // namespace testing
} // namespace detail

#endif

/** Words of SI prefixes
https://physics.nist.gov/cuu/Units/prefixes.html
https://physics.nist.gov/cuu/Units/binary.html
Expand Down
9 changes: 9 additions & 0 deletions units/units.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2045,14 +2045,23 @@ namespace constants {
} // namespace atomic
} // namespace constants

#ifdef ENABLE_UNIT_TESTING
namespace detail {
/// A namespace specifically for unit testing some components
namespace testing {
// generate a number from a number sequence
double testLeadingNumber(const std::string& test, size_t& index);
// generate a number from words
double testNumericalWords(const std::string& test, size_t& index);
// test the unit string generation
std::string
testUnitSequenceGeneration(double mul, const std::string& test);

// test the string cleanup
std::string
testCleanUpString(std::string testString, std::uint32_t commodity);
} // namespace testing
} // namespace detail
#endif

} // namespace units

0 comments on commit ec86399

Please sign in to comment.