31 if (name.back() ==
'-') {
44 const auto dim_name = name[1];
45 const int dim_no = dim_name -
'a';
106 auto pos = double_string.find_first_of(
"+-", 1);
108 if (pos != std::string::npos && double_string.find_last_of(
"eE", pos) == std::string::npos) {
109 double_string.insert(pos,
"e");
111 return std::stod(double_string);
116 double nominator_prefix_factor = 1.0;
117 int nominator_power = 1;
120 if (nominator_name.front() >=
'1' && nominator_name.front() <=
'9') {
121 unit->mul_factor(1 / std::stod(nominator_name));
125 std::string nom_name = nominator_name;
126 auto nominator =
table.find(nominator_name);
129 if (nominator ==
table.end()) {
130 int changed_nominator_name = 1;
132 while (changed_nominator_name) {
133 changed_nominator_name = 0;
135 auto res = std::mismatch(it.first.begin(),
137 nominator_name.begin(),
138 nominator_name.end());
139 if (res.first == it.first.end()) {
140 changed_nominator_name = 1;
141 nominator_prefix_factor *= it.second;
142 nominator_name.erase(nominator_name.begin(),
143 nominator_name.begin() +
144 static_cast<std::ptrdiff_t
>(it.first.size()));
149 if (nominator_name.empty()) {
151 auto res = std::mismatch(it.first.begin(), it.first.end(), nom_name.begin());
152 if (res.first == it.first.end()) {
153 unit->mul_factor(it.second);
161 char nominator_back = nominator_name.back();
162 if (nominator_back >=
'2' && nominator_back <=
'9') {
163 nominator_power = nominator_back -
'0';
164 nominator_name.pop_back();
167 nominator =
table.find(nominator_name);
170 if (nominator ==
table.end()) {
171 if (nominator_name.back() ==
's') {
172 nominator_name.pop_back();
174 nominator =
table.find(nominator_name);
180 if (nominator ==
table.end()) {
181 std::string ss = fmt::format(
"Unit {} not defined!", nominator_name);
182 throw std::runtime_error(ss);
184 for (
int i = 0; i < nominator_power; i++) {
185 unit->mul_factor(nominator_prefix_factor * nominator->second->get_factor());
186 unit->add_nominator_dims(nominator->second->get_dimensions());
193 std::string denominator_name) {
194 double denominator_prefix_factor = 1.0;
195 int denominator_power = 1;
198 if (denominator_name.front() >=
'1' && denominator_name.front() <=
'9') {
199 unit->mul_factor(std::stod(denominator_name));
203 std::string denom_name = denominator_name;
204 auto denominator =
table.find(denominator_name);
207 if (denominator ==
table.end()) {
208 bool changed_denominator_name =
true;
210 while (changed_denominator_name) {
211 changed_denominator_name =
false;
213 auto res = std::mismatch(it.first.begin(),
215 denominator_name.begin(),
216 denominator_name.end());
217 if (res.first == it.first.end()) {
218 changed_denominator_name =
true;
219 denominator_prefix_factor *= it.second;
220 denominator_name.erase(denominator_name.begin(),
221 denominator_name.begin() +
222 static_cast<std::ptrdiff_t
>(it.first.size()));
227 if (denominator_name.empty()) {
229 auto res = std::mismatch(it.first.begin(), it.first.end(), denom_name.begin());
230 if (res.first == it.first.end()) {
231 unit->mul_factor(it.second);
239 char denominator_back = denominator_name.back();
240 if (denominator_back >=
'2' && denominator_back <=
'9') {
241 denominator_power = denominator_back -
'0';
242 denominator_name.pop_back();
245 denominator =
table.find(denominator_name);
248 if (denominator ==
table.end()) {
249 if (denominator_name.back() ==
's') {
250 denominator_name.pop_back();
252 denominator =
table.find(denominator_name);
256 if (denominator ==
table.end()) {
257 std::string ss = fmt::format(
"Unit {} not defined!", denominator_name);
258 throw std::runtime_error(ss);
260 for (
int i = 0; i < denominator_power; i++) {
261 unit->mul_factor(1.0 / (denominator_prefix_factor * denominator->second->get_factor()));
262 unit->add_denominator_dims(denominator->second->get_dimensions());
270 if (
table.find(unit->get_name()) !=
table.end()) {
271 std::stringstream ss_unit_string;
272 ss_unit_string << fmt::format(
"{:g} {}",
274 fmt::join(unit->get_nominator_unit(),
""));
275 if (!unit->get_denominator_unit().empty()) {
276 ss_unit_string << fmt::format(
"/{}", fmt::join(unit->get_denominator_unit(),
""));
278 throw std::runtime_error(fmt::format(
"Redefinition of units ({}) to {} is not allowed.",
280 ss_unit_string.str()));
284 auto unit_nominator = unit->get_nominator_unit();
285 auto only_base_unit_nominator =
286 unit_nominator.size() == 1 && unit_nominator.front().size() == 3 &&
287 (unit_nominator.front().front() ==
'*' && unit_nominator.front().back() ==
'*');
288 if (only_base_unit_nominator) {
290 auto const index = unit_nominator.front()[1] -
'a';
294 table.insert({unit->get_name(), unit});
298 for (
const auto& it: unit->get_nominator_unit()) {
301 for (
const auto& it: unit->get_denominator_unit()) {
304 table.insert({unit->get_name(), unit});
308 prefixes.insert({prfx->get_name(), prfx->get_factor()});
312 std::vector<std::pair<std::string, std::shared_ptr<Unit>>> sorted_elements(
table.begin(),
314 std::sort(sorted_elements.begin(), sorted_elements.end());
315 for (
const auto& it: sorted_elements) {
316 units_details << fmt::format(
"{} {:g}: {}\n",
318 it.second->get_factor(),
319 fmt::join(it.second->get_dimensions(),
" "));
324 bool first_print =
true;
329 base_units_details << it;
331 base_units_details <<
' ' << it;
335 base_units_details <<
'\n';