Skip to content
2 changes: 1 addition & 1 deletion config/cppcheck_suppressions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ unusedFunction:units/x12_conv.cpp:1009
passedByValue:units/units.cpp:224
passedByValue:units/units.cpp:1160
passedByValue:units/units.cpp:1177
passedByValue:units/units.cpp:3067
passedByValue:units/units.cpp:3069
passedByValue:units/units.hpp:413
passedByValue:units/units.hpp:590
passedByValue:units/units.hpp:1020
Expand Down
22 changes: 11 additions & 11 deletions python/units_python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ NB_MODULE(units_llnl_ext, mod)
units::precise::generate_custom_count_unit(
static_cast<std::uint16_t>(value));
} else {
def = def * (units::unit_from_string(key).pow(value));
def = def * (units::default_unit(key).pow(value));
}
}
new (dim) Dimension{def};
Expand Down Expand Up @@ -827,34 +827,34 @@ NB_MODULE(units_llnl_ext, mod)
}
if (!custom) {
if (base.meter() != 0) {
dictionary["meters"] = base.meter();
dictionary["Length"] = base.meter();
}
if (base.kg() != 0) {
dictionary["kilogram"] = base.kg();
dictionary["Mass"] = base.kg();
}
if (base.second() != 0) {
dictionary["second"] = base.second();
dictionary["Time"] = base.second();
}
if (base.ampere() != 0) {
dictionary["ampere"] = base.ampere();
dictionary["Electric Current"] = base.ampere();
}
if (base.kelvin() != 0) {
dictionary["kelvin"] = base.kelvin();
dictionary["Temperature"] = base.kelvin();
}
if (base.mole() != 0) {
dictionary["mole"] = base.mole();
dictionary["Amount of Substance"] = base.mole();
}
if (base.candela() != 0) {
dictionary["candela"] = base.candela();
dictionary["Luminous Intensity"] = base.candela();
}
if (base.currency() != 0) {
dictionary["currency"] = base.currency();
dictionary["Currency"] = base.currency();
}
if (base.count() != 0) {
dictionary["count"] = base.count();
dictionary["Count"] = base.count();
}
if (base.radian() != 0) {
dictionary["radian"] = base.radian();
dictionary["Angle"] = base.radian();
}
if (base.is_per_unit()) {
dictionary["per_unit"] = 1;
Expand Down
5 changes: 3 additions & 2 deletions test/python/test_dimensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,16 @@ def test_dimensions_decompose1():
d1 = Dimension("volume")
decomposition = d1.decompose()

assert decomposition["meters"] == 3
assert decomposition["Length"] == 3


def test_dimensions_decompose2():
u1 = Unit("$ per watt radian")
dim = u1.dimension
decomposition = dim.decompose()

print(f"dim={decomposition}")
dim2 = Dimension(decomposition)
print(f"dim2={dim2.decompose()}")
assert dim2 == dim
assert dim2.default_unit == u1

Expand Down
10 changes: 0 additions & 10 deletions test/test_measurement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,16 +499,6 @@ TEST(PreciseMeasurement, unaryOps)
EXPECT_EQ(z.units(), x.units());
}

TEST(PreciseMeasurement, countAddition)
{
auto m1 = 1.0 * precise::Hz;
auto m2 = 1.0 * unit_from_string("baud");
auto m3 = 1.0 * precise::Bq;

auto m4 = m1 + m2 + m3;
auto str = to_string(m4);
}

TEST(PreciseMeasurement, doubleOps)
{
auto freq = 9.0 / precise::s;
Expand Down
25 changes: 25 additions & 0 deletions test/test_measurement_strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,31 @@ TEST(MeasurementToString, simple)
EXPECT_EQ(to_string(meas), "45 m");
}

TEST(PreciseMeasurement, countAddition)
{
auto m1 = 1.0 * precise::Hz;
auto m2 = 1.0 * unit_from_string("baud");
auto m3 = 1.0 * precise::Bq;

auto m4 = m1 + m2 + m3;
auto str = to_string(m4);
}

TEST(MeasurementToString, one)
{
auto s1 = to_string(
units::precise_measurement(10, units::precise_unit(units::one)));
EXPECT_EQ(s1, "10");
auto s2 = to_string(
units::precise_measurement(0, units::precise_unit(units::one)));
EXPECT_EQ(s2, "0");

auto s3 = to_string(units::measurement(10, units::unit(units::one)));
EXPECT_EQ(s3, "10");
auto s4 = to_string(units::measurement(0, units::unit(units::one)));
EXPECT_EQ(s4, "0");
}

TEST(MeasurementToString, test)
{
measurement density = 10.0 * kg / m.pow(3);
Expand Down
49 changes: 33 additions & 16 deletions units/units.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1744,13 +1744,15 @@ std::string
std::stringstream ss;
ss.precision(12);
ss << measure.value();
ss << ' ';
auto str = to_string(measure.units(), match_flags);
if (isNumericalStartCharacter(str.front())) {
str.insert(str.begin(), '(');
str.push_back(')');
if (!str.empty()) {
ss << ' ';
if (isNumericalStartCharacter(str.front())) {
str.insert(str.begin(), '(');
str.push_back(')');
}
ss << str;
}
ss << str;
return ss.str();
}

Expand Down Expand Up @@ -4906,29 +4908,33 @@ static precise_unit
static precise_unit
checkSpecialUnits(const std::string& unit_string, std::uint64_t match_flags)
{
precise_unit bunit;
// lets try checking for meter next which is one of the most common
// reasons for getting here
auto fnd = findWordOperatorSep(unit_string, "meter");
if (fnd != std::string::npos) {
std::string ustring = unit_string;
ustring.erase(fnd, 5);
auto bunit = unit_from_string_internal(ustring, match_flags);
bunit = unit_from_string_internal(ustring, match_flags);
if (is_valid(bunit)) {
return precise::m * bunit;
}
}

// detect another somewhat common situation often amphour or ampsecond
if (unit_string.compare(0, 3, "amp") == 0) {
auto bunit = unit_from_string_internal(
bunit = unit_from_string_internal(
unit_string.substr(3), match_flags | minimum_partition_size3);
if (is_valid(bunit)) {
return precise::A * bunit;
}
}
if (unit_string.front() == '%') {
auto bunit = default_unit(unit_string.substr(1));
if (is_valid(bunit)) {
return precise::percent * precise::pu * bunit;
if ((match_flags & no_default_units) == 0) {
bunit = default_unit(unit_string.substr(1));
if (is_valid(bunit)) {
return precise::percent * precise::pu * bunit;
}
}
bunit = unit_from_string_internal(
unit_string.substr(1), match_flags | minimum_partition_size3);
Expand All @@ -4937,9 +4943,11 @@ static precise_unit
}
}
if (unit_string.compare(0, 2, "pu") == 0) {
auto bunit = default_unit(unit_string.substr(2));
if (is_valid(bunit)) {
return precise::pu * bunit;
if ((match_flags & no_default_units) == 0) {
bunit = default_unit(unit_string.substr(2));
if (is_valid(bunit)) {
return precise::pu * bunit;
}
}
bunit = unit_from_string_internal(
unit_string.substr(2), match_flags | minimum_partition_size3);
Expand Down Expand Up @@ -5542,9 +5550,11 @@ static precise_unit unit_from_string_internal(
if (!is_valid(b_unit)) {
if ((unit_string[sep] == '*') &&
(a_unit == precise::pu || a_unit == precise::percent)) {
b_unit = default_unit(unit_string.substr(sep + 1));
if (is_valid(b_unit)) {
return a_unit * b_unit;
if ((match_flags & no_default_units) == 0) {
b_unit = default_unit(unit_string.substr(sep + 1));
if (is_valid(b_unit)) {
return a_unit * b_unit;
}
}
}
return precise::invalid;
Expand Down Expand Up @@ -6119,6 +6129,9 @@ precise_unit default_unit(std::string unit_type)
if (unit_type.compare(0, 10, "quantityof") == 0) {
return default_unit(unit_type.substr(10));
}
if (unit_type.compare(0, 9, "measureof") == 0) {
return default_unit(unit_type.substr(9));
}
if (unit_type.compare(0, 6, "rateof") == 0) {
return default_unit(unit_type.substr(6)) / precise::s;
}
Expand Down Expand Up @@ -6169,6 +6182,10 @@ precise_unit default_unit(std::string unit_type)
unit_type.substr(0, unit_type.size() - strlen("rate"))) /
precise::s;
}
auto retunit = unit_from_string(unit_type, no_default_units);
if (is_valid(retunit)) {
return precise_unit(retunit.base_units());
}
return precise::invalid;
}

Expand Down
3 changes: 2 additions & 1 deletion units/units.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1933,7 +1933,8 @@ enum unit_conversion_flags : std::uint64_t {
(1U << 24U), // counter for skipping commodity check vi of
// nothing at 25, 24 through 26 are connected
no_commodities = (1U << 26U), //!< skip commodity checks
// 27-31 are unused as of yet
no_default_units = (1U << 27U), //!< skip any check of default unit types
// 28-31 are unused as of yet
partition_check1 = (1ULL << 32U), //!< counter for skipping partitioning
// nothing at 28, 27 through 29 are connected to limit partition
// depth
Expand Down
8 changes: 6 additions & 2 deletions units/units_conversion_maps.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3248,7 +3248,7 @@ std::array<std::pair<const char*, precise_unit>, 233>

// Mostly from https://en.wikipedia.org/wiki/International_System_of_Units
UNITS_CPP14_CONSTEXPR_OBJECT
std::array<std::pair<const char*, precise_unit>, 247> defined_measurement_types{
std::array<std::pair<const char*, precise_unit>, 251> defined_measurement_types{
{
{"", precise::defunit},
{"arb", precise::defunit},
Expand Down Expand Up @@ -3283,8 +3283,8 @@ std::array<std::pair<const char*, precise_unit>, 247> defined_measurement_types{
{"temp", precise::K},
{"thermodynamictemperature", precise::K},
{"thermalconductivity", precise::W / precise::m / precise::K},
{"amount", precise::mol},
{"amountofsubstance", precise::mol},
{"amount", precise::mol},
{"substance", precise::mol},
{"sub", precise::mol},
{"luminousintensity", precise::cd},
Expand Down Expand Up @@ -3498,5 +3498,9 @@ std::array<std::pair<const char*, precise_unit>, 247> defined_measurement_types{
{"information", precise::bit},
{"unitless", precise::one},
{"numeric", precise::one},
{"currency", precise::currency},
{"value", precise::currency},
{"money", precise::currency},
{"count", precise::count},
}};
} // namespace UNITS_NAMESPACE
Loading