examples, alternative namespaces : Part2 of put alternative namespace definitions in local headers.

examples, clcpp_response,alternative_namespaces::clcpp_response : use fmt functions for showing precision of quantities
examples, alternative namespaces : combined the alternative namespace quantity typedefs in header files.
examples, alternative namespaces : add simple timer example
This commit is contained in:
Andy Little
2020-03-19 11:43:12 +00:00
committed by Mateusz Pusz
parent c886590b03
commit 6b7e5893d2
13 changed files with 283 additions and 182 deletions

View File

@@ -29,3 +29,4 @@ add_example(box_example)
add_example(capacitor_time_curve) add_example(capacitor_time_curve)
add_example(clcpp_response) add_example(clcpp_response)
add_example(conversion_factor) add_example(conversion_factor)
add_example(timer)

View File

@@ -0,0 +1,14 @@
#pragma once
#include <units/physical/si/area.h>
namespace area {
template<typename Rep = double>
using m2 = units::si::area<units::si::square_metre, Rep>;
template<typename Rep = double>
using fm2 = units::si::area<units::si::square_femtometre, Rep>;
} // namespace area

View File

@@ -11,7 +11,6 @@
using namespace units::experimental; using namespace units::experimental;
struct Box { struct Box {
static constexpr auto air_density = density::kg_per_m3<>{1.225}; static constexpr auto air_density = density::kg_per_m3<>{1.225};

View File

@@ -23,31 +23,11 @@
#include <units/physical/si/capacitance.h> #include <units/physical/si/capacitance.h>
#include <units/physical/si/resistance.h> #include <units/physical/si/resistance.h>
#include <units/physical/si/time.h> #include <units/physical/si/time.h>
#include <units/physical/si/voltage.h> #include "./voltage.h"
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>
namespace { using namespace units::experimental;
namespace voltage {
template<typename Rep = double>
using V = units::si::voltage<units::si::volt, Rep>;
template<typename Rep = double>
using mV = units::si::voltage<units::si::millivolt, Rep>;
template<typename Rep = double>
using uV = units::si::voltage<units::si::microvolt, Rep>;
template<typename Rep = double>
using nV = units::si::voltage<units::si::nanovolt, Rep>;
template<typename Rep = double>
using pV = units::si::voltage<units::si::picovolt, Rep>;
} // namespace voltage
} // namespace
using namespace units::si::literals; using namespace units::si::literals;
int main() int main()

View File

@@ -15,127 +15,30 @@
along with this program. If not, see http://www.gnu.org/licenses./ along with this program. If not, see http://www.gnu.org/licenses./
*/ */
#include <units/physical/iau/length.h>
#include <units/physical/imperial/length.h>
#include <units/physical/international/length.h>
#include <units/physical/si/area.h>
#include <units/physical/si/length.h>
#include <units/physical/si/time.h>
#include <units/physical/si/volume.h>
#include <units/physical/typographic/length.h>
#include <units/physical/us/length.h>
#include <iostream> #include <iostream>
#include <units/format.h>
namespace { #include "./length.h"
namespace length { #include "./volume.h"
#include "./time.h"
template<typename Rep = double> #include "./area.h"
using m = units::si::length<units::si::metre, Rep>; #include "./units_str.h"
template<typename Rep = double>
using mm = units::si::length<units::si::millimetre, Rep>;
template<typename Rep = double>
using fm = units::si::length<units::si::femtometre, Rep>;
template<typename Rep = double>
using km = units::si::length<units::si::kilometre, Rep>;
template<typename Rep = double>
using AU = units::si::length<units::si::astronomical_unit, Rep>;
template<typename Rep = double>
using in = units::si::length<units::international::inch, Rep>;
template<typename Rep = double>
using angstrom = units::si::length<units::iau::angstrom, Rep>;
template<typename Rep = double>
using ch = units::si::length<units::imperial::chain, Rep>;
template<typename Rep = double>
using fathom = units::si::length<units::international::fathom, Rep>;
template<typename Rep = double>
using fathom_us = units::si::length<units::us::fathom, Rep>;
template<typename Rep = double>
using ft = units::si::length<units::international::foot, Rep>;
template<typename Rep = double>
using ft_us = units::si::length<units::us::foot, Rep>;
template<typename Rep = double>
using ly = units::si::length<units::iau::light_year, Rep>;
template<typename Rep = double>
using mi = units::si::length<units::international::mile, Rep>;
template<typename Rep = double>
using mi_naut = units::si::length<units::international::nautical_mile, Rep>;
template<typename Rep = double>
using pc = units::si::length<units::iau::parsec, Rep>;
template<typename Rep = double>
using pica_comp = units::si::length<units::typographic::pica_comp, Rep>;
template<typename Rep = double>
using pica_prn = units::si::length<units::typographic::pica_prn, Rep>;
template<typename Rep = double>
using point_comp = units::si::length<units::typographic::point_comp, Rep>;
template<typename Rep = double>
using point_prn = units::si::length<units::typographic::point_prn, Rep>;
template<typename Rep = double>
using rd = units::si::length<units::imperial::rod, Rep>;
template<typename Rep = double>
using yd = units::si::length<units::international::yard, Rep>;
} // namespace length
namespace time {
template<typename Rep = double>
using s = units::si::time<units::si::second, Rep>;
template<typename Rep = double>
using min = units::si::time<units::si::minute, Rep>;
template<typename Rep = double>
using h = units::si::time<units::si::hour, Rep>;
} // namespace time
namespace area {
template<typename Rep = double>
using m2 = units::si::area<units::si::square_metre, Rep>;
template<typename Rep = double>
using fm2 = units::si::area<units::si::square_femtometre, Rep>;
} // namespace area
} // namespace
using namespace units::si::literals; using namespace units::si::literals;
using namespace units::international; using namespace units::international;
using namespace units::experimental;
void simple_quantities() void simple_quantities()
{ {
using distance = length::m<>; using distance = length::m<>;
using time = time::s<>; using q_time = q_time::s<>;
constexpr distance km = 1.0q_km; constexpr distance km = 1.0q_km;
constexpr distance miles = 1.0q_mi; constexpr distance miles = 1.0q_mi;
constexpr time sec = 1q_s; constexpr q_time sec = 1q_s;
constexpr time min = 1q_min; constexpr q_time min = 1q_min;
constexpr time hr = 1q_h; constexpr q_time hr = 1q_h;
std::cout << "A physical quantities library can choose the simple\n"; 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 << "option to provide output using a single type for each base unit:\n\n";
@@ -151,11 +54,9 @@ void quantities_with_typed_units()
constexpr length::km<> km = 1.0q_km; constexpr length::km<> km = 1.0q_km;
constexpr length::mi<> miles = 1.0q_mi; constexpr length::mi<> miles = 1.0q_mi;
std::cout.precision(6); constexpr q_time::s<> sec = 1q_s;
constexpr q_time::min<> min = 1q_min;
constexpr time::s<> sec = 1q_s; constexpr q_time::h<> hr = 1q_h;
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 << "A more flexible option is to provide separate types for each unit,\n\n";
std::cout << km << '\n'; std::cout << km << '\n';
@@ -192,16 +93,14 @@ void quantities_with_typed_units()
void calcs_comparison() void calcs_comparison()
{ {
std::cout.precision(20);
std::cout << "\nA distinct unit for each type is efficient and accurate\n" std::cout << "\nA distinct unit for each type is efficient and accurate\n"
"when adding two values of the same very big\n" "when adding two values of the same very big\n"
"or very small type:\n\n"; "or very small type:\n\n";
length::fm<float> L1A = 2q_fm; length::fm<float> L1A = 2.q_fm;
length::fm<float> L2A = 3q_fm; length::fm<float> L2A = 3.q_fm;
length::fm<float> LrA = L1A + L2A; length::fm<float> LrA = L1A + L2A;
fmt::print("{:%.30Q %q}\n + {:%.30Q %q}\n = {:%.30Q %q}\n\n",L1A,L2A,LrA);
std::cout << L1A << " + " << L2A << " = " << LrA << "\n\n";
std::cout << "The single unit method must convert large\n" std::cout << "The single unit method must convert large\n"
"or small values in other units to the base unit.\n" "or small values in other units to the base unit.\n"
@@ -210,23 +109,22 @@ void calcs_comparison()
length::m<float> L1B = L1A; length::m<float> L1B = L1A;
length::m<float> L2B = L2A; length::m<float> L2B = L2A;
length::m<float> LrB = L1B + L2B; length::m<float> LrB = L1B + L2B;
fmt::print("{:%.30Q %q}\n + {:%.30Q %q}\n = {:%.30Q %q}\n\n",L1B,L2B,LrB);
std::cout << L1B << " + " << L2B << " = " << LrB << "\n\n";
std::cout << "In multiplication and division:\n\n"; std::cout << "In multiplication and division:\n\n";
area::fm2<float> ArA = L1A * L2A; area::fm2<float> ArA = L1A * L2A;
std::cout << L1A << " * " << L2A << " = " << ArA << "\n\n"; fmt::print("{:%.30Q %q}\n * {:%.30Q %q}\n = {:%.30Q %q}\n\n",L1A,L2A,ArA);
std::cout << "similar problems arise\n\n"; std::cout << "similar problems arise\n\n";
area::m2<float> ArB = L1B * L2B; area::m2<float> ArB = L1B * L2B;
std::cout << L1B << " * " << L2B << "\n = " << ArB << '\n'; fmt::print("{:%.30Q %q}\n * {:%.30Q %q}\n = {:%.30Q %q}\n\n",L1B,L2B,ArB);
} }
int main() int main()
{ {
std::cout << "This demo was originally posted on com.lang.c++.moderated in 2006\n"; std::cout << "This demo was originally posted on comp.lang.c++.moderated in 2006\n";
std::cout << "http://compgroups.net/comp.lang.c++.moderated/dimensional-analysis-units/51712\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 mpusz/units library.\n\n";

View File

@@ -15,7 +15,9 @@
along with this program. If not, see http://www.gnu.org/licenses./ along with this program. If not, see http://www.gnu.org/licenses./
*/ */
#include <units/physical/si/length.h>
#include "./units_str.h"
#include "./length.h"
#include <iostream> #include <iostream>
/* /*
@@ -36,29 +38,10 @@ inline constexpr std::common_type_t<typename Target::rep, typename Source::rep>
return target{source{1}}.count(); 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<decltype(q)> qtype;
return units::detail::unit_text<typename qtype::dimension, typename qtype::unit>();
}
} // namespace
namespace {
namespace length {
template<typename Rep = double>
using m = units::si::length<units::si::metre, Rep>;
template<typename Rep = double>
using mm = units::si::length<units::si::millimetre, Rep>;
} // namespace length
} // namespace } // namespace
using namespace units::si::literals; using namespace units::si::literals;
using namespace units::experimental;
int main() int main()
{ {

View File

@@ -3,6 +3,11 @@
#pragma once #pragma once
#include <units/physical/si/length.h> #include <units/physical/si/length.h>
#include <units/physical/imperial/length.h>
#include <units/physical/international/length.h>
#include <units/physical/typographic/length.h>
#include <units/physical/us/length.h>
#include <units/physical/iau/length.h>
namespace units{ namespace units{
namespace experimental{ namespace experimental{
@@ -15,6 +20,67 @@ using m = units::si::length<units::si::metre, Rep>;
template<typename Rep = double> template<typename Rep = double>
using mm = units::si::length<units::si::millimetre, Rep>; using mm = units::si::length<units::si::millimetre, Rep>;
template<typename Rep = double>
using fm = units::si::length<units::si::femtometre, Rep>;
template<typename Rep = double>
using km = units::si::length<units::si::kilometre, Rep>;
template<typename Rep = double>
using AU = units::si::length<units::si::astronomical_unit, Rep>;
template<typename Rep = double>
using in = units::si::length<units::international::inch, Rep>;
template<typename Rep = double>
using angstrom = units::si::length<units::iau::angstrom, Rep>;
template<typename Rep = double>
using ch = units::si::length<units::imperial::chain, Rep>;
template<typename Rep = double>
using fathom = units::si::length<units::international::fathom, Rep>;
template<typename Rep = double>
using fathom_us = units::si::length<units::us::fathom, Rep>;
template<typename Rep = double>
using ft = units::si::length<units::international::foot, Rep>;
template<typename Rep = double>
using ft_us = units::si::length<units::us::foot, Rep>;
template<typename Rep = double>
using ly = units::si::length<units::iau::light_year, Rep>;
template<typename Rep = double>
using mi = units::si::length<units::international::mile, Rep>;
template<typename Rep = double>
using mi_naut = units::si::length<units::international::nautical_mile, Rep>;
template<typename Rep = double>
using pc = units::si::length<units::iau::parsec, Rep>;
template<typename Rep = double>
using pica_comp = units::si::length<units::typographic::pica_comp, Rep>;
template<typename Rep = double>
using pica_prn = units::si::length<units::typographic::pica_prn, Rep>;
template<typename Rep = double>
using point_comp = units::si::length<units::typographic::point_comp, Rep>;
template<typename Rep = double>
using point_prn = units::si::length<units::typographic::point_prn, Rep>;
template<typename Rep = double>
using rd = units::si::length<units::imperial::rod, Rep>;
template<typename Rep = double>
using yd = units::si::length<units::international::yard, Rep>;
} // namespace length } // namespace length
}} // units::experimental }} // units::experimental

View File

@@ -0,0 +1,21 @@
#pragma once
#include <units/physical/si/time.h>
// named qtime due to conflict with time_t time(time_t*)
namespace q_time {
template<typename Rep = double>
using s = units::si::time<units::si::second, Rep>;
template<typename Rep = double>
using ms = units::si::time<units::si::millisecond, Rep>;
template<typename Rep = double>
using min = units::si::time<units::si::minute, Rep>;
template<typename Rep = double>
using h = units::si::time<units::si::hour, Rep>;
} // namespace time

View File

@@ -0,0 +1,35 @@
#include <iostream>
#include "./timer.h"
/*
simple timer, useful for perf timing etc
*/
using namespace units::experimental;
using namespace units::si::literals;
int main()
{
std::cout << "Simple timer using mpusz/units ...\n";
auto const period = 0.5q_s;
auto const duration = 10 * period;
timer t;
auto const start_time = t();
std::cout << "Started at " << start_time <<'\n';
auto prev = start_time;
for (auto now = t(); (now - start_time) < duration; now = t() ) {
if ( (now - prev ) >= period ){
prev = now;
std::cout << "tick (" << now << ")\n";;
}
}
t.stop();
std::cout << "finished at " << t() << '\n';
}

View File

@@ -0,0 +1,64 @@
#pragma once
/*
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 "./time.h"
#include <ctime>
namespace units{ namespace experimental{
class timer{
public:
timer(): running(true)
{
start_time = std::clock();
}
void restart()
{
running = true;
start_time = std::clock();
}
void stop()
{
if (running){
stop_time = std::clock();
running = false;
}
}
q_time::ms<> operator ()()const
{
std::clock_t const wanted = running ? std::clock() : stop_time;
static constexpr auto divider = 1000.0 / CLOCKS_PER_SEC;
return q_time::ms<>(
difftime(wanted , start_time)
) * divider;
}
bool is_running() const {return running;}
bool is_stopped() const {return !running;}
private:
bool running;
std::clock_t start_time,stop_time;
};
} }//units::experimental

View File

@@ -0,0 +1,11 @@
#pragma once
#include <units/physical/dimensions.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
// 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<decltype(q)> qtype;
return units::detail::unit_text<typename qtype::dimension, typename qtype::unit>();
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include <units/physical/si/voltage.h>
namespace units{
namespace experimental{
namespace voltage {
template<typename Rep = double>
using V = units::si::voltage<units::si::volt, Rep>;
template<typename Rep = double>
using mV = units::si::voltage<units::si::millivolt, Rep>;
template<typename Rep = double>
using uV = units::si::voltage<units::si::microvolt, Rep>;
template<typename Rep = double>
using nV = units::si::voltage<units::si::nanovolt, Rep>;
template<typename Rep = double>
using pV = units::si::voltage<units::si::picovolt, Rep>;
} // namespace voltage
}} // units::experimental

View File

@@ -24,6 +24,7 @@
#include <units/physical/si/volume.h> #include <units/physical/si/volume.h>
#include <units/physical/typographic/length.h> #include <units/physical/typographic/length.h>
#include <units/physical/us/length.h> #include <units/physical/us/length.h>
#include <units/format.h>
#include <iostream> #include <iostream>
namespace { namespace {
@@ -105,36 +106,33 @@ void calcs_comparison()
{ {
using namespace units::si; using namespace units::si;
std::cout.precision(20);
std::cout << "\nA distinct unit for each type is efficient and accurate\n" std::cout << "\nA distinct unit for each type is efficient and accurate\n"
"when adding two values of the same very big\n" "when adding two values of the same very big\n"
"or very small type:\n\n"; "or very small type:\n\n";
Length AUTO L1A = 2.q_fm; length<femtometre,float> L1A = 2.q_fm;
Length AUTO L2A = 3.q_fm; length<femtometre,float> L2A = 3.q_fm;
Length AUTO LrA = L1A + L2A; length<femtometre,float> LrA = L1A + L2A;
fmt::print("{:%.30Q %q}\n + {:%.30Q %q}\n = {:%.30Q %q}\n\n",L1A,L2A,LrA);
std::cout << L1A << " + " << L2A << " = " << LrA << "\n\n";
std::cout << "The single unit method must convert large\n" std::cout << "The single unit method must convert large\n"
"or small values in other units to the base unit.\n" "or small values in other units to the base unit.\n"
"This is both inefficient and inaccurate\n\n"; "This is both inefficient and inaccurate\n\n";
length<metre> L1B = L1A; length<metre,float> L1B = L1A;
length<metre> L2B = L2A; length<metre,float> L2B = L2A;
length<metre> LrB = L1B + L2B; length<metre,float> LrB = L1B + L2B;
fmt::print("{:%.30Q %q}\n + {:%.30Q %q}\n = {:%.30Q %q}\n\n",L1B,L2B,LrB);
std::cout << L1B << " + " << L2B << " = " << LrB << "\n\n";
std::cout << "In multiplication and division:\n\n"; std::cout << "In multiplication and division:\n\n";
Area AUTO ArA = L1A * L2A; area<square_femtometre,float> ArA = L1A * L2A;
std::cout << L1A << " * " << L2A << " = " << ArA << "\n\n"; fmt::print("{:%.30Q %q}\n * {:%.30Q %q}\n = {:%.30Q %q}\n\n",L1A,L2A,ArA);
std::cout << "similar problems arise\n\n"; std::cout << "similar problems arise\n\n";
Area AUTO ArB = L1B * L2B; area<square_metre,float> ArB = L1B * L2B;
std::cout << L1B << " * " << L2B << "\n = " << ArB << '\n'; fmt::print("{:%.30Q %q}\n * {:%.30Q %q}\n = {:%.30Q %q}\n\n",L1B,L2B,ArB);
} }
} // namespace } // namespace