diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 3dbfb34b..52c60505 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -35,3 +35,5 @@ add_example(capacitor_time_curve) add_example(clcpp_response) add_example(conversion_factor) add_example(kalman_filter-alpha_beta_filter_example2) + +add_subdirectory(alternative_namespaces) diff --git a/example/alternative_namespaces/CMakeLists.txt b/example/alternative_namespaces/CMakeLists.txt new file mode 100644 index 00000000..9d5d3286 --- /dev/null +++ b/example/alternative_namespaces/CMakeLists.txt @@ -0,0 +1,31 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Mateusz Pusz +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +function(add_example target) + add_executable(${target}_alt ${target}.cpp) + target_link_libraries(${target}_alt PRIVATE mp::units) +endfunction() + +add_example(box_example) +add_example(capacitor_time_curve) +add_example(clcpp_response) +add_example(conversion_factor) diff --git a/example/alternative_namespaces/box_example.cpp b/example/alternative_namespaces/box_example.cpp new file mode 100644 index 00000000..795697da --- /dev/null +++ b/example/alternative_namespaces/box_example.cpp @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +namespace length { + +template +using m = units::si::length; + +template +using mm = units::si::length; + +} // namespace length + +namespace acceleration { + +template +using mps2 = units::si::acceleration; + +template +constexpr mps2<> g{static_cast(9.80665)}; + +} // namespace acceleration + +namespace force { + +template +using N = units::si::force; + +} + +namespace mass { + +template +using kg = units::si::mass; + +} + +namespace density { + +template +using kgpm3 = units::si::density; + +} + +namespace volume { + +template +using m3 = units::si::volume; + +} +} // namespace + +struct Box { + static constexpr density::kgpm3<> air_density{1.225}; + + length::m<> length; + length::m<> width; + length::m<> height; + + struct contents { + density::kgpm3<> density = air_density; + } contents; + + Box(const length::m<>& l, const length::m<>& w, const length::m<>& h) : length{l}, width{w}, height{h} {} + + force::N<> filled_weight() const + { + const volume::m3<> volume = length * width * height; + const mass::kg<> mass = contents.density * volume; + return mass * acceleration::g<>; + } + + length::m<> fill_level(const mass::kg<>& measured_mass) const + { + return height * (measured_mass * acceleration::g<>) / filled_weight(); + } + + volume::m3<> spare_capacity(const mass::kg<>& measured_mass) const + { + return (height - fill_level(measured_mass)) * width * length; + } + + void set_contents_density(const density::kgpm3<>& density_in) + { + assert(density_in > air_density); + contents.density = density_in; + } + +}; + +#include + +using namespace units::si::literals; +int main() +{ + auto box = Box{1000.0q_mm, 500.0q_mm, 200.0q_mm}; + box.set_contents_density(1000.0q_kgpm3); + + auto fill_time = 200.0q_s; // time since starting fill + auto measured_mass = 20.0q_kg; // measured mass at fill_time + + std::cout << "mpusz/units box example...\n"; + std::cout << "fill height at " << fill_time << " = " << box.fill_level(measured_mass) << " (" + << (box.fill_level(measured_mass) / box.height) * 100 << "% full)\n"; + std::cout << "spare_capacity at " << fill_time << " = " << box.spare_capacity(measured_mass) << '\n'; + std::cout << "input flow rate after " << fill_time << " = " << measured_mass / fill_time << '\n'; + std::cout << "float rise rate = " << box.fill_level(measured_mass) / fill_time << '\n'; + auto fill_time_left = (box.height / box.fill_level(measured_mass) - 1) * fill_time; + std::cout << "box full E.T.A. at current flow rate = " << fill_time_left << '\n'; +} diff --git a/example/alternative_namespaces/capacitor_time_curve.cpp b/example/alternative_namespaces/capacitor_time_curve.cpp new file mode 100644 index 00000000..9ef501d7 --- /dev/null +++ b/example/alternative_namespaces/capacitor_time_curve.cpp @@ -0,0 +1,80 @@ +/* + Copyright (c) 2003-2020 Andy Little. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses./ +*/ + +/* + capacitor discharge curve using compile_time + physical_quantities +*/ + +#include +#include +#include +#include +#include +#include + +namespace { +namespace voltage { + +template +using V = units::si::voltage; + +template +using mV = units::si::voltage; + +template +using uV = units::si::voltage; + +template +using nV = units::si::voltage; + +template +using pV = units::si::voltage; + +} // namespace voltage +} // namespace + +using namespace units::si::literals; + +int main() +{ + std::cout << "mpusz/units capacitor time curve example...\n"; + std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield); + std::cout.precision(3); + + constexpr auto C = 0.47q_uF; + constexpr auto V0 = 5.0q_V; + constexpr auto R = 4.7q_kR; + + for (auto t = 0q_ms; t <= 50q_ms; ++t) { + const auto Vt = V0 * std::exp(-t / (R * C)); + + std::cout << "at " << t << " voltage is "; + + if (Vt >= 1q_V) + std::cout << Vt; + else if (Vt >= 1q_mV) + std::cout << voltage::mV<>{Vt}; + else if (Vt >= 1q_uV) + std::cout << voltage::uV<>{Vt}; + else if (Vt >= 1q_nV) + std::cout << voltage::nV<>{Vt}; + else + std::cout << voltage::pV<>{Vt}; + std::cout << "\n"; + } +} diff --git a/example/alternative_namespaces/clcpp_response.cpp b/example/alternative_namespaces/clcpp_response.cpp new file mode 100644 index 00000000..94a26faa --- /dev/null +++ b/example/alternative_namespaces/clcpp_response.cpp @@ -0,0 +1,236 @@ +/* + Copyright (c) 2003-2019 Andy Little. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses./ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { +namespace length { + +template +using m = units::si::length; + +template +using mm = units::si::length; + +template +using fm = units::si::length; + +template +using km = units::si::length; + +template +using AU = units::si::length; + +template +using in = units::si::length; + +template +using angstrom = units::si::length; + +template +using ch = units::si::length; + +template +using fathom = units::si::length; + +template +using fathom_us = units::si::length; + +template +using ft = units::si::length; + +template +using ft_us = units::si::length; + +template +using ly = units::si::length; + +template +using mi = units::si::length; + +template +using mi_naut = units::si::length; + +template +using pc = units::si::length; + +template +using pica_comp = units::si::length; + +template +using pica_prn = units::si::length; + +template +using point_comp = units::si::length; + +template +using point_prn = units::si::length; + +template +using rd = units::si::length; + +template +using yd = units::si::length; + +} // namespace length + +namespace time { + +template +using s = units::si::time; + +template +using min = units::si::time; + +template +using h = units::si::time; + +} // namespace time + +namespace area { + +template +using m2 = units::si::area; + +template +using fm2 = units::si::area; + +} // namespace area +} // namespace + + +using namespace units::si::literals; +using namespace units::international; + +void simple_quantities() +{ + using distance = length::m<>; + using time = time::s<>; + + constexpr distance km = 1.0q_km; + constexpr distance miles = 1.0q_mi; + + constexpr time sec = 1q_s; + constexpr time min = 1q_min; + constexpr time hr = 1q_h; + + std::cout << "A physical quantities library can choose the simple\n"; + std::cout << "option to provide output using a single type for each base unit:\n\n"; + std::cout << km << '\n'; + std::cout << miles << '\n'; + std::cout << sec << '\n'; + std::cout << min << '\n'; + std::cout << hr << "\n\n"; +} + +void quantities_with_typed_units() +{ + constexpr length::km<> km = 1.0q_km; + constexpr length::mi<> miles = 1.0q_mi; + + std::cout.precision(6); + + constexpr time::s<> sec = 1q_s; + constexpr time::min<> min = 1q_min; + constexpr time::h<> hr = 1q_h; + + std::cout << "A more flexible option is to provide separate types for each unit,\n\n"; + std::cout << km << '\n'; + std::cout << miles << '\n'; + std::cout << sec << '\n'; + std::cout << min << '\n'; + std::cout << hr << "\n\n"; + + constexpr length::m<> meter = 1q_m; + std::cout << "then a wide range of pre-defined units can be defined and converted,\n" + " for consistency and repeatability across applications:\n\n"; + + std::cout << meter << '\n'; + + std::cout << " = " << length::AU<>(meter) << '\n'; + std::cout << " = " << length::angstrom<>(meter) << '\n'; + std::cout << " = " << length::ch<>(meter) << '\n'; + std::cout << " = " << length::fathom<>(meter) << '\n'; + std::cout << " = " << length::fathom_us<>(meter) << '\n'; + std::cout << " = " << length::ft<>(meter) << '\n'; + std::cout << " = " << length::ft_us<>(meter) << '\n'; + std::cout << " = " << length::in<>(meter) << '\n'; + std::cout << " = " << length::ly<>(meter) << '\n'; + std::cout << " = " << length::mi<>(meter) << '\n'; + std::cout << " = " << length::mi_naut<>(meter) << '\n'; + std::cout << " = " << length::pc<>(meter) << '\n'; + std::cout << " = " << length::pica_comp<>(meter) << '\n'; + std::cout << " = " << length::pica_prn<>(meter) << '\n'; + std::cout << " = " << length::point_comp<>(meter) << '\n'; + std::cout << " = " << length::point_prn<>(meter) << '\n'; + std::cout << " = " << length::rd<>(meter) << '\n'; + std::cout << " = " << length::yd<>(meter) << '\n'; +} + +void calcs_comparison() +{ + std::cout.precision(20); + std::cout << "\nA distinct unit for each type is efficient and accurate\n" + "when adding two values of the same very big\n" + "or very small type:\n\n"; + + length::fm L1A = 2q_fm; + length::fm L2A = 3q_fm; + length::fm LrA = L1A + L2A; + + std::cout << L1A << " + " << L2A << " = " << LrA << "\n\n"; + + std::cout << "The single unit method must convert large\n" + "or small values in other units to the base unit.\n" + "This is both inefficient and inaccurate\n\n"; + + length::m L1B = L1A; + length::m L2B = L2A; + length::m LrB = L1B + L2B; + + std::cout << L1B << " + " << L2B << " = " << LrB << "\n\n"; + + std::cout << "In multiplication and division:\n\n"; + + area::fm2 ArA = L1A * L2A; + std::cout << L1A << " * " << L2A << " = " << ArA << "\n\n"; + + std::cout << "similar problems arise\n\n"; + + area::m2 ArB = L1B * L2B; + std::cout << L1B << " * " << L2B << "\n = " << ArB << '\n'; +} + +int main() +{ + std::cout << "This demo was originally posted on com.lang.c++.moderated in 2006\n"; + std::cout << "http://compgroups.net/comp.lang.c++.moderated/dimensional-analysis-units/51712\n"; + std::cout << "Here converted to use mpusz/units library.\n\n"; + + simple_quantities(); + quantities_with_typed_units(); + calcs_comparison(); +} diff --git a/example/alternative_namespaces/conversion_factor.cpp b/example/alternative_namespaces/conversion_factor.cpp new file mode 100644 index 00000000..259dfa38 --- /dev/null +++ b/example/alternative_namespaces/conversion_factor.cpp @@ -0,0 +1,79 @@ +/* + Copyright (c) 2003-2020 Andy Little. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses./ +*/ + +#include +#include + +/* + get conversion factor from one dimensionally equivalent + quantity type to another +*/ + +namespace { + +template + requires units::equivalent_dim +inline constexpr std::common_type_t conversion_factor(Target, Source) +{ + // get quantities looking like inputs but with Q::rep that doesn't have narrowing conversion + typedef std::common_type_t rep; + typedef units::quantity source; + typedef units::quantity target; + return target{source{1}}.count(); +} + +// get at the units text of the quantity, without its numeric value +inline auto constexpr units_str(const units::Quantity AUTO& q) +{ + typedef std::remove_cvref_t qtype; + return units::detail::unit_text(); +} + +} // namespace + +namespace { + +namespace length { + +template +using m = units::si::length; + +template +using mm = units::si::length; + +} // namespace length +} // namespace + +using namespace units::si::literals; + +int main() +{ + std::cout << "conversion factor in mpusz/units...\n\n"; + + constexpr length::m<> lengthA = 2.0q_m; + constexpr length::mm<> lengthB = lengthA; + + std::cout << "lengthA( " << lengthA << " ) and lengthB( " << lengthB << " )\n" + << "represent the same length in different units.\n\n"; + + std::cout << "therefore ratio lengthA / lengthB == " << lengthA / lengthB << "\n\n"; + + std::cout << "conversion factor from lengthA::unit of " + << units_str(lengthA) << " to lengthB::unit of " << units_str(lengthB) << " :\n\n" + << "lengthB.count( " << lengthB.count() << " ) == lengthA.count( " << lengthA.count() + << " ) * conversion_factor( " << conversion_factor(lengthB, lengthA) << " )\n"; +} diff --git a/example/box_example.cpp b/example/box_example.cpp index 795697da..36dc96da 100644 --- a/example/box_example.cpp +++ b/example/box_example.cpp @@ -1,118 +1,82 @@ #include +#include #include #include #include #include #include #include +#include #include namespace { -namespace length { +using namespace units; +using namespace units::si::literals; -template -using m = units::si::length; +using m = si::metre; +using kg = si::kilogram; +using N = si::newton; +using m3 = si::cubic_metre; +using kgpm3 = si::kilogram_per_metre_cub; -template -using mm = units::si::length; +inline constexpr auto g = si::standard_gravity; -} // namespace length - -namespace acceleration { - -template -using mps2 = units::si::acceleration; - -template -constexpr mps2<> g{static_cast(9.80665)}; - -} // namespace acceleration - -namespace force { - -template -using N = units::si::force; - -} - -namespace mass { - -template -using kg = units::si::mass; - -} - -namespace density { - -template -using kgpm3 = units::si::density; - -} - -namespace volume { - -template -using m3 = units::si::volume; - -} } // namespace struct Box { - static constexpr density::kgpm3<> air_density{1.225}; + static constexpr auto air_density = 1.225q_kgpm3; - length::m<> length; - length::m<> width; - length::m<> height; + si::length length; + si::length width; + si::length height; struct contents { - density::kgpm3<> density = air_density; + si::density density = air_density; } contents; - Box(const length::m<>& l, const length::m<>& w, const length::m<>& h) : length{l}, width{w}, height{h} {} + constexpr Box(const si::length& l, const si::length& w, const si::length& h) : length{l}, width{w}, height{h} {} - force::N<> filled_weight() const + constexpr si::force filled_weight() const { - const volume::m3<> volume = length * width * height; - const mass::kg<> mass = contents.density * volume; - return mass * acceleration::g<>; + const si::volume volume = length * width * height; + const si::mass mass = contents.density * volume; + return mass * g; } - length::m<> fill_level(const mass::kg<>& measured_mass) const + constexpr si::length fill_level(const si::mass& measured_mass) const { - return height * (measured_mass * acceleration::g<>) / filled_weight(); + return height * (measured_mass * g) / filled_weight(); } - volume::m3<> spare_capacity(const mass::kg<>& measured_mass) const + constexpr si::volume spare_capacity(const si::mass& measured_mass) const { return (height - fill_level(measured_mass)) * width * length; } - void set_contents_density(const density::kgpm3<>& density_in) + constexpr void set_contents_density(const si::density& density_in) { assert(density_in > air_density); contents.density = density_in; } - }; #include -using namespace units::si::literals; int main() { - auto box = Box{1000.0q_mm, 500.0q_mm, 200.0q_mm}; + auto box = Box(1000.0q_mm, 500.0q_mm, 200.0q_mm); box.set_contents_density(1000.0q_kgpm3); - auto fill_time = 200.0q_s; // time since starting fill - auto measured_mass = 20.0q_kg; // measured mass at fill_time + const auto fill_time = 200.0q_s; // time since starting fill + const auto measured_mass = 20.0q_kg; // measured mass at fill_time - std::cout << "mpusz/units box example...\n"; + std::cout << "mp-units box example...\n"; std::cout << "fill height at " << fill_time << " = " << box.fill_level(measured_mass) << " (" << (box.fill_level(measured_mass) / box.height) * 100 << "% full)\n"; std::cout << "spare_capacity at " << fill_time << " = " << box.spare_capacity(measured_mass) << '\n'; std::cout << "input flow rate after " << fill_time << " = " << measured_mass / fill_time << '\n'; std::cout << "float rise rate = " << box.fill_level(measured_mass) / fill_time << '\n'; - auto fill_time_left = (box.height / box.fill_level(measured_mass) - 1) * fill_time; + const auto fill_time_left = (box.height / box.fill_level(measured_mass) - 1) * fill_time; std::cout << "box full E.T.A. at current flow rate = " << fill_time_left << '\n'; } diff --git a/example/capacitor_time_curve.cpp b/example/capacitor_time_curve.cpp index 9ef501d7..550aa498 100644 --- a/example/capacitor_time_curve.cpp +++ b/example/capacitor_time_curve.cpp @@ -27,32 +27,12 @@ #include #include -namespace { -namespace voltage { - -template -using V = units::si::voltage; - -template -using mV = units::si::voltage; - -template -using uV = units::si::voltage; - -template -using nV = units::si::voltage; - -template -using pV = units::si::voltage; - -} // namespace voltage -} // namespace - -using namespace units::si::literals; - int main() { - std::cout << "mpusz/units capacitor time curve example...\n"; + using namespace units; + using namespace units::si; + + std::cout << "mp-units capacitor time curve example...\n"; std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield); std::cout.precision(3); @@ -61,20 +41,20 @@ int main() constexpr auto R = 4.7q_kR; for (auto t = 0q_ms; t <= 50q_ms; ++t) { - const auto Vt = V0 * std::exp(-t / (R * C)); + const Voltage auto Vt = V0 * std::exp(-t / (R * C)); std::cout << "at " << t << " voltage is "; if (Vt >= 1q_V) std::cout << Vt; else if (Vt >= 1q_mV) - std::cout << voltage::mV<>{Vt}; + std::cout << quantity_cast(Vt); else if (Vt >= 1q_uV) - std::cout << voltage::uV<>{Vt}; + std::cout << quantity_cast(Vt); else if (Vt >= 1q_nV) - std::cout << voltage::nV<>{Vt}; + std::cout << quantity_cast(Vt); else - std::cout << voltage::pV<>{Vt}; + std::cout << quantity_cast(Vt); std::cout << "\n"; } } diff --git a/example/clcpp_response.cpp b/example/clcpp_response.cpp index 94a26faa..6e5e86c4 100644 --- a/example/clcpp_response.cpp +++ b/example/clcpp_response.cpp @@ -27,115 +27,23 @@ #include namespace { -namespace length { -template -using m = units::si::length; - -template -using mm = units::si::length; - -template -using fm = units::si::length; - -template -using km = units::si::length; - -template -using AU = units::si::length; - -template -using in = units::si::length; - -template -using angstrom = units::si::length; - -template -using ch = units::si::length; - -template -using fathom = units::si::length; - -template -using fathom_us = units::si::length; - -template -using ft = units::si::length; - -template -using ft_us = units::si::length; - -template -using ly = units::si::length; - -template -using mi = units::si::length; - -template -using mi_naut = units::si::length; - -template -using pc = units::si::length; - -template -using pica_comp = units::si::length; - -template -using pica_prn = units::si::length; - -template -using point_comp = units::si::length; - -template -using point_prn = units::si::length; - -template -using rd = units::si::length; - -template -using yd = units::si::length; - -} // namespace length - -namespace time { - -template -using s = units::si::time; - -template -using min = units::si::time; - -template -using h = units::si::time; - -} // namespace time - -namespace area { - -template -using m2 = units::si::area; - -template -using fm2 = units::si::area; - -} // namespace area -} // namespace - - -using namespace units::si::literals; -using namespace units::international; +using namespace units; void simple_quantities() { - using distance = length::m<>; - using time = time::s<>; + using namespace units::si; + using namespace units::international; + + using distance = length; + using duration = si::time; constexpr distance km = 1.0q_km; constexpr distance miles = 1.0q_mi; - constexpr time sec = 1q_s; - constexpr time min = 1q_min; - constexpr time hr = 1q_h; + constexpr duration sec = 1q_s; + constexpr duration min = 1q_min; + constexpr duration hr = 1q_h; std::cout << "A physical quantities library can choose the simple\n"; std::cout << "option to provide output using a single type for each base unit:\n\n"; @@ -148,14 +56,17 @@ void simple_quantities() void quantities_with_typed_units() { - constexpr length::km<> km = 1.0q_km; - constexpr length::mi<> miles = 1.0q_mi; + using namespace units::si; + using namespace units::international; + + constexpr length km = 1.0q_km; + constexpr length miles = 1.0q_mi; std::cout.precision(6); - constexpr time::s<> sec = 1q_s; - constexpr time::min<> min = 1q_min; - constexpr time::h<> hr = 1q_h; + constexpr si::time sec = 1q_s; + constexpr si::time min = 1q_min; + constexpr si::time hr = 1q_h; std::cout << "A more flexible option is to provide separate types for each unit,\n\n"; std::cout << km << '\n'; @@ -164,42 +75,44 @@ void quantities_with_typed_units() std::cout << min << '\n'; std::cout << hr << "\n\n"; - constexpr length::m<> meter = 1q_m; + constexpr length meter = 1q_m; std::cout << "then a wide range of pre-defined units can be defined and converted,\n" " for consistency and repeatability across applications:\n\n"; std::cout << meter << '\n'; - std::cout << " = " << length::AU<>(meter) << '\n'; - std::cout << " = " << length::angstrom<>(meter) << '\n'; - std::cout << " = " << length::ch<>(meter) << '\n'; - std::cout << " = " << length::fathom<>(meter) << '\n'; - std::cout << " = " << length::fathom_us<>(meter) << '\n'; - std::cout << " = " << length::ft<>(meter) << '\n'; - std::cout << " = " << length::ft_us<>(meter) << '\n'; - std::cout << " = " << length::in<>(meter) << '\n'; - std::cout << " = " << length::ly<>(meter) << '\n'; - std::cout << " = " << length::mi<>(meter) << '\n'; - std::cout << " = " << length::mi_naut<>(meter) << '\n'; - std::cout << " = " << length::pc<>(meter) << '\n'; - std::cout << " = " << length::pica_comp<>(meter) << '\n'; - std::cout << " = " << length::pica_prn<>(meter) << '\n'; - std::cout << " = " << length::point_comp<>(meter) << '\n'; - std::cout << " = " << length::point_prn<>(meter) << '\n'; - std::cout << " = " << length::rd<>(meter) << '\n'; - std::cout << " = " << length::yd<>(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; + std::cout << " = " << quantity_cast(meter) << '\n'; } void calcs_comparison() { + using namespace units::si; + std::cout.precision(20); std::cout << "\nA distinct unit for each type is efficient and accurate\n" "when adding two values of the same very big\n" "or very small type:\n\n"; - length::fm L1A = 2q_fm; - length::fm L2A = 3q_fm; - length::fm LrA = L1A + L2A; + Length AUTO L1A = 2.q_fm; + Length AUTO L2A = 3.q_fm; + Length AUTO LrA = L1A + L2A; std::cout << L1A << " + " << L2A << " = " << LrA << "\n\n"; @@ -207,28 +120,30 @@ void calcs_comparison() "or small values in other units to the base unit.\n" "This is both inefficient and inaccurate\n\n"; - length::m L1B = L1A; - length::m L2B = L2A; - length::m LrB = L1B + L2B; + length L1B = L1A; + length L2B = L2A; + length LrB = L1B + L2B; std::cout << L1B << " + " << L2B << " = " << LrB << "\n\n"; std::cout << "In multiplication and division:\n\n"; - area::fm2 ArA = L1A * L2A; + Area AUTO ArA = L1A * L2A; std::cout << L1A << " * " << L2A << " = " << ArA << "\n\n"; std::cout << "similar problems arise\n\n"; - area::m2 ArB = L1B * L2B; + Area AUTO ArB = L1B * L2B; std::cout << L1B << " * " << L2B << "\n = " << ArB << '\n'; } +} // namespace + int main() { std::cout << "This demo was originally posted on com.lang.c++.moderated in 2006\n"; std::cout << "http://compgroups.net/comp.lang.c++.moderated/dimensional-analysis-units/51712\n"; - std::cout << "Here converted to use mpusz/units library.\n\n"; + std::cout << "Here converted to use mp-units library.\n\n"; simple_quantities(); quantities_with_typed_units(); diff --git a/example/conversion_factor.cpp b/example/conversion_factor.cpp index 259dfa38..82e71e30 100644 --- a/example/conversion_factor.cpp +++ b/example/conversion_factor.cpp @@ -16,6 +16,7 @@ */ #include +#include #include /* @@ -36,44 +37,23 @@ inline constexpr std::common_type_t return target{source{1}}.count(); } -// get at the units text of the quantity, without its numeric value -inline auto constexpr units_str(const units::Quantity AUTO& q) -{ - typedef std::remove_cvref_t qtype; - return units::detail::unit_text(); -} - } // namespace -namespace { - -namespace length { - -template -using m = units::si::length; - -template -using mm = units::si::length; - -} // namespace length -} // namespace - -using namespace units::si::literals; - int main() { - std::cout << "conversion factor in mpusz/units...\n\n"; + using namespace units::si; - constexpr length::m<> lengthA = 2.0q_m; - constexpr length::mm<> lengthB = lengthA; + std::cout << "conversion factor in mp-units...\n\n"; - std::cout << "lengthA( " << lengthA << " ) and lengthB( " << lengthB << " )\n" + constexpr length lengthA = 2.0q_m; + constexpr length lengthB = lengthA; + + std::cout << fmt::format("lengthA( {} ) and lengthB( {} )\n", lengthA, lengthB) << "represent the same length in different units.\n\n"; - std::cout << "therefore ratio lengthA / lengthB == " << lengthA / lengthB << "\n\n"; + std::cout << fmt::format("therefore ratio lengthA / lengthB == {}\n\n", lengthA / lengthB); - std::cout << "conversion factor from lengthA::unit of " - << units_str(lengthA) << " to lengthB::unit of " << units_str(lengthB) << " :\n\n" - << "lengthB.count( " << lengthB.count() << " ) == lengthA.count( " << lengthA.count() - << " ) * conversion_factor( " << conversion_factor(lengthB, lengthA) << " )\n"; + std::cout << fmt::format("conversion factor from lengthA::unit of {:%q} to lengthB::unit of {:%q}:\n\n", lengthA, lengthB) + << fmt::format("lengthB.count( {} ) == lengthA.count( {} ) * conversion_factor( {} )\n", + lengthB.count(), lengthA.count(), conversion_factor(lengthB, lengthA)); }