12 if (character >=
'a' && character <=
'z') {
15 if (character >=
'A' && character <=
'Z') {
18 if (character >=
'0' && character <=
'9') {
21 return character ==
'_';
28 for (
char character :
name) {
38DimensionSignature::DimensionSignature(Exponents exponents)
39 : exponents_(std::move(exponents)) {
40 for (
auto iterator = exponents_.begin(); iterator != exponents_.end();) {
41 if (iterator->second.is_zero()) {
42 iterator = exponents_.erase(iterator);
49DimensionSignature DimensionSignature::base(std::string name) {
51 exponents.emplace(std::move(name),
Rational(1));
52 return DimensionSignature(std::move(exponents));
55DimensionSignature DimensionSignature::multiplied_by(
56 const DimensionSignature& other)
const {
57 Exponents result = exponents_;
58 for (
const auto& entry : other.exponents_) result[entry.first] = result[entry.first] + entry.second;
59 return DimensionSignature(std::move(result));
62DimensionSignature DimensionSignature::divided_by(
63 const DimensionSignature& other)
const {
64 Exponents result = exponents_;
65 for (
const auto& entry : other.exponents_) result[entry.first] = result[entry.first] - entry.second;
66 return DimensionSignature(std::move(result));
69DimensionSignature DimensionSignature::raised_to(
const Rational& exponent)
const {
71 for (
const auto& entry : exponents_) result.emplace(entry.first, entry.second * exponent);
72 return DimensionSignature(std::move(result));
75std::string DimensionSignature::to_string()
const {
76 if (exponents_.empty())
return "1";
77 std::ostringstream output;
79 for (
const auto& entry : exponents_) {
80 if (!first) output <<
'*';
81 output << entry.first;
82 if (entry.second !=
Rational(1)) output <<
'^' << entry.second.to_string();
88UnitSystem::UnitSystem() {
89 const auto length = DimensionSignature::base(
"m");
90 const auto mass = DimensionSignature::base(
"kg");
91 const auto time = DimensionSignature::base(
"s");
92 const auto current = DimensionSignature::base(
"A");
93 const auto temperature = DimensionSignature::base(
"K");
94 const auto amount = DimensionSignature::base(
"mol");
95 const auto luminous_intensity = DimensionSignature::base(
"cd");
97 units_.emplace(
"m", UnitDefinition{length,
Rational(1)});
98 units_.emplace(
"kg", UnitDefinition{mass,
Rational(1)});
99 units_.emplace(
"s", UnitDefinition{time,
Rational(1)});
100 units_.emplace(
"A", UnitDefinition{current,
Rational(1)});
101 units_.emplace(
"K", UnitDefinition{temperature,
Rational(1)});
102 units_.emplace(
"mol", UnitDefinition{amount,
Rational(1)});
103 units_.emplace(
"cd", UnitDefinition{luminous_intensity,
Rational(1)});
104 units_.emplace(
"km", UnitDefinition{length,
Rational(1000)});
105 units_.emplace(
"cm", UnitDefinition{length,
Rational(1, 100)});
106 units_.emplace(
"mm", UnitDefinition{length,
Rational(1, 1000)});
107 units_.emplace(
"min", UnitDefinition{time,
Rational(60)});
108 units_.emplace(
"h", UnitDefinition{time,
Rational(3600)});
109 units_.emplace(
"g", UnitDefinition{mass,
Rational(1, 1000)});
112Result<void> UnitSystem::declare_base_unit(
const std::string& name) {
114 return Result<void>::failure(
115 CasErrc::InvalidArgument,
"unit name is invalid", kUnitOperation);
117 if (units_.find(name) != units_.end()) {
118 return Result<void>::failure(
119 CasErrc::InvalidArgument,
"unit name is already declared", kUnitOperation);
121 units_.emplace(name, UnitDefinition{DimensionSignature::base(name),
Rational(1)});
122 return Result<void>::success();
125Result<void> UnitSystem::declare_derived_unit(
126 const std::string& name, UnitDefinition definition) {
129 return Result<void>::failure(
130 CasErrc::InvalidArgument,
"derived unit definition is invalid", kUnitOperation);
132 if (units_.find(name) != units_.end()) {
133 return Result<void>::failure(
134 CasErrc::InvalidArgument,
"unit name is already declared", kUnitOperation);
136 units_.emplace(name, std::move(definition));
137 return Result<void>::success();
140Result<UnitDefinition> UnitSystem::resolve(
const std::string& name)
const {
141 const auto iterator = units_.find(name);
142 if (iterator == units_.end()) {
143 return Result<UnitDefinition>::failure(
144 CasErrc::UnitInvalid,
"unit is not declared: " + name, kUnitOperation);
146 return Result<UnitDefinition>::success(iterator->second);
149Result<Rational> UnitSystem::conversion_factor(
150 const std::string& source,
const std::string& target)
const {
151 auto source_unit = resolve(source);
152 if (!source_unit)
return Result<Rational>::failure(source_unit.error());
153 auto target_unit = resolve(target);
154 if (!target_unit)
return Result<Rational>::failure(target_unit.error());
155 if (source_unit.value().dimension != target_unit.value().dimension) {
156 return Result<Rational>::failure(
157 CasErrc::DimensionMismatch,
158 "unit conversion requires equal dimensions", kUnitOperation);
160 return Result<Rational>::success(
161 source_unit.value().scale_to_base / target_unit.value().scale_to_base);
bool valid_unit_name(const std::string &name)
bool valid_unit_character(char character)
constexpr const char * kUnitOperation
@ Rational
Rational numbers
std::string UnitDefinition definition
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name