I'm working on a software design in which I'd like to leverage Boost.Units. Some of the units I'd like to use represent time, however, I'm inclined to use the C++11 std::chrono units for those since they're standard.
I'm wondering if there's any clean integration between Boost.Units and chrono or whether I have to resort to writing my own converters and lose type safety by just copying scalar values between the types.
Are there any best practices for this issue?
If you just want to convert a std::chrono duration to a boost time quantity you can use the following template function:
using time_quantity = boost::units::quantity<si::time, double>;
template<class _Period1, class _Type>
time_quantity toBoostTime( chrono::duration<_Type, _Period1> in)
{
return time_quantity::from_value(double(in.count()) * double(_Period1::num) / double(_Period1::den) );
}
One thing to note is that the returned time_quantity will always be in seconds and the storage type will be of type double. If any of those two are a problem, the template can be adapted.
Example:
namespace bu = boost::units;
namespace sc = std::chrono;
using time_quantity_ms = bu::quantity<decltype(bu::si::milli * bu::si::second), int32_t>;
std::cout << "Test 1: " << toBoostTime(sc::seconds(10)) << std::endl;
std::cout << "Test 2: " << toBoostTime(sc::milliseconds(10)) << std::endl;
std::cout << "Test 3: " << static_cast<time_quantity_ms>(toBoostTime(sc::milliseconds(10))) << std::endl;
/* OUTPUT */
Test 1: 10 s
Test 2: 0.01 s
Test 3: 10 ms
This may not be a perfect answer, but boost::chrono provides an example of how to integrate it with a units system they define in the example itself (devel) (version at time of writing).
Essentially, based on the boost.units examples for quaternion and complex numbers it should be possible to define the same functions for the std::chrono units, though it may require additional code for new user-defined units.
There is also a similar, though slightly different question regarding boost::date_time which may also have useful information.
Sorry this isn't a full answer, but perhaps it will be a start someone else can complete!
Related
I have just started using boost::multiprecision trying to speed up some calculations previously done in Matlab. I found quite an unexpected problem, though. My calculations involve complex numbers, so I am using cpp_complex_50 type (e.g. cpp_complex_50 A, B;)
At some point I need to use boost::math::tools::bracket_and_solve_root() function, which requires that the function it works on returns real values. Here comes my problem... I cannot convert my complex multiprecision variable A.real() to any type that is real, eg. to cpp_dec_float_50 type or even double. The task should be streightforward, but I am virtually drowned in error complaints from my compiler (MSVC2015), and cannot solve it. Any hints at how to convert the data are more than welcome.
A somewhat connected question is the problem of initialization of cpp_complex_50 type variables with real values. At the moment I can only use data of type double at initialization, which means I am loosing some accuracy at the initialization stage already, e.g.:
cpp_complex_50 A = 4.0 * boost::math::constants::pi<double>(); // it works
but
cpp_complex_50 A = 4.0 * boost::math::constants::pi<cpp_dec_float_50>(); // It does NOT work
Any hints are needed. I am stuck at this, despite nice initial results.
Regards
Pawel
cpp_complex uses cpp_bin_float.
Live On Compiler Explorer
#include <boost/multiprecision/cpp_complex.hpp>
#include <iostream>
namespace bmp = boost::multiprecision;
int main() {
using Complex = bmp::cpp_complex_100;
using Real = Complex::value_type;
Real r = 4.0 * boost::math::constants::pi<Real>();
Complex b(r, {});
// or
b = r.convert_to<Complex>();
std::cout << b.str(100) << std::endl;
}
Prints
12.56637061435917295385057353311801153678867759750042328389977836923126562514483599451213930136846827
Following valuable comment from sehe... the code
cpp_complex_50 A = 4.0 * boost::math::constants::pi<cpp_bin_float_50>();
cout << A << endl;
works, producing:
12.5663706143591729538505735331180115367886775975
Similarely,
cpp_bin_float_50 B = A.real();
cout << B << endl;
works as well, printing the same.
I am converting from Fortran to C++ . In Fortran on a 2D array ie A(1000,3) i can do the following:
A(1,:)=(x0,y0,z0)
I have searched online and haven't found anything close to that for C++ so I can vectorize some operations. Any help would be appreciated.
The C++ language does not include a built-in matrix type, but includes all the tools you need to build one. Fortunately, that does not mean you need to go and build one all by yourself. Indeed, that would be a bit like reinventing the wheel.
I suggest you rely on one of the existing C++ open source matrix/vector packages, rather than defining ad hoc types manually. One possibility consists of using the Armadillo library.
Armadillo Wikipedia article
Armadillo online documentation
What you want to do can be done like this:
A.row(0) = rowvec{x0, y0, z0};
Example of self-contained source code below:
#include <armadillo>
#include <iostream>
using arma::Mat;
using arma::vec;
using arma::rowvec;
using arma::colvec;
int main(int argc, const char* argv[])
{
Mat<double> A = Mat<double>(1000, 3, arma::fill::zeros);
std::cout << "Shape of matrix A: " <<
A.n_rows << "x" << A.n_cols << std::endl;
double x0 = 1.5;
double y0 = 2.5;
double z0 = 3.5;
A.row(0) = rowvec{x0, y0, z0}; // HERE
std::cout << " A(0,0)=" << A(0,0) << " A(0,1)=" << A(0,1)
<< " A(0,2)=" << A(0,2) << std::endl;
std::cout << " A(1,0)=" << A(1,0) << " A(1,1)=" << A(1,1)
<< " A(1,2)=" << A(1,2) << std::endl;
return 0;
}
The specialized libraries go much further than this. For example, you can write a matrix product just like P=A*B, and the library will gracefully call the appropriate highly optimized BLAS/LAPACK backend routines for you. You can remain blissfully ignorant of the sad facts that the backend is Fortran-based and thus insists on numbering array elements from 1 not 0, and also insists on storing 2-dimensional arrays in contiguous columns, unlike C/C++ which prefers contiguous rows.
Of course it will take some time to learn about one the existing libraries, but it is unfortunately possible that writing/debugging your own type system will take even more time.
Alternatively, if you insist on designing/using your own C++ linear algebra package, you could do worse than getting a copy of this book:
"The C++ Programming Language, 4th edition"
by Bjarne Stroustrup, ISBN 978-0321-563842.
As you probably know, the C++ initial design effort, and a good chunk of the subsequent language evolution was led by this author. The 4th edition of his book includes a chapter 29 (taking only 30 pages) whose title is: "A matrix design". Chapter 29 makes extensive use of "advanced" features of C++11 such as template types and operator overloading.
Regarding elementary C++ types:
Using an array of std::arrays assume that you know the size of your matrix at compile time. This is a restriction that was fortunately removed from modern versions of Fortran.
Using a vector of vector would allocate the memory space of the matrix as N separate areas, and that would be both less time-efficient and incompatible with BLAS/LAPACK backend libraries.
If using std::array containers and using std::array::operator= you could do this:
std::array<std::array<int, 3>, 1000> A;
int x0, y0, z0;
A[0] = std::array<int, 3>{x0, y0, z0};
In C++11 you still have to use std::localtime and std::gmtime as indirection to print a std::chrono::time_point. These functions are not safe to use in a multithreaded environment as introduced with C++11 because they return a pointer to an internal static struct. This is especially annoying since C++11 introduced the convenient function std::put_time which is nearly unusable for the same reason.
Why is this so fundamental broken or do I overlook something?
According to N2661, the paper that added <chrono>:
This paper does not offer calendrical services except for a minimal
mapping to and from C's time_t.
As this paper does not propose a date/time library, nor specify epochs, it also does not address leap seconds. However, a date/time
library will find this to be an excellent foundation on which to
build.
This paper does not propose a general purpose physical quantities
library.
This paper proposes a solid foundation that, in the future, could provide a compatible starting point for a general physical units
library. While such a future library might take any of several forms,
the present proposal stops well short of actually being a physical
units library. This proposal is time-specific, and continues to be
motivated by the time-related needs of the threading library.
The major goal of this proposal is to satisfy the needs of the
standard library threading API in a manner which is easy to use, safe
to use, efficient, and flexible enough to not be obsolete 10 or even
100 years from now. Every feature contained in this proposal is here
for a specific reason with practical use cases as motivation. Things
that fell into the category of "cool", or "that sounds like it might
be useful", or "very useful but not needed by this interface" have not
been included. Such items might appear in other proposals, and
possibly target a TR.
Note that the major goal of <chrono> is "to satisfy the needs of the standard library threading API", which does not require calendar services.
localtime and gmtime have internal storage that is static, which means they are not threadsafe (we have to return a pointer to a data structure, so it either has to be allocated dynamically, a static value or a global value - since allocating dynamically would leak memory, that is not a reasonable solution, meaning that it has to be a global or static variable [theoretically, one could allocate and store in TLS, and make it threadsafe that way]).
Most systems do have threadsafe alternatives, but they are not part of the standard library. For example, Linux/Posix has localtime_r and gmtime_r, which takes an extra parameter for the result. See for example
http://pubs.opengroup.org/onlinepubs/7908799/xsh/gmtime.html
Similarly, Microsoft libraries have gmtime_s, which is also re-entrant and works in a similar way (passing in the output parameter as an input). See http://msdn.microsoft.com/en-us/library/3stkd9be.aspx
As to why the standard C++11 library doesn't use these functions? That you'd have to ask the people who wrote that specification - I expect it's portability and convenience, but I'm not entirely sure.
There is no threadsafe alternative to std::localtime and std::gmtime because you didn't propose one and marshal it through the entire standardization process. And neither did anyone else.
chronos only calendar code is code that wraps existing time_t functions. Standardizing or writing new ones was outside of the domain of the chrono project. Doing such standardization would require more time, more effort, and add more dependencies. Simply wrapping each time_t function was simple, had few dependencies, and quick.
They focused their effort narrowly. And they succeeded at what they focused on.
I encourage you to start working on <calendar> or joining such an effort to create a robust calendaring API for std. Good luck and godspeed!
If you are willing to use a free, open-source 3rd party library, here is a way to print std::chrono::system_clock::time_point in UTC:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
std::cout << system_clock::now() << " UTC\n";
}
This is a thread-safe alternative to std::gmtime using modern C++ syntax.
For a modern, thread-safe std::localtime replacement, you need this closely related higher level timezone library and the syntax looks like this:
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
std::cout << make_zoned(current_zone(), system_clock::now()) << "\n";
}
Both of these will output with whatever precision your system_clock supports, for example:
2016-07-05 10:03:01.608080 EDT
(microseconds on macOS)
These libraries go far beyond a gmtime and localtime replacement. For example, do you want to see the current date in the Julian calendar?
#include "julian.h"
#include <iostream>
int
main()
{
using namespace std::chrono;
std::cout << julian::year_month_day(date::floor<date::days>(system_clock::now())) << "\n";
}
2016-06-22
How about the current GPS time?
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
std::cout << std::chrono::system_clock::now() << " UTC\n";
std::cout << gps_clock::now() << " GPS\n";
}
2016-07-05 14:13:02.138091 UTC
2016-07-05 14:13:19.138524 GPS
https://github.com/HowardHinnant/date
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0355r0.html
Update
The "date.h" and "tz.h" libraries are now in the draft C++2a specification, with very minor changes, and where we hope 'a' is '0'. They will live in the header <chrono> and under namespace std::chrono (and there will not be a date namespace).
As others had mentioned, there is really no threadsafe convenience and portable time formatting approach in any available C++ standard, but there is some archaic preprocessor technique I found usable (thanks to Andrei Alexandrescu at CppCon 2015 slide 17 & 18):
std::mutex gmtime_call_mutex;
template< size_t For_Separating_Instantiations >
std::tm const * utc_impl( std::chrono::system_clock::time_point const & tp )
{
thread_local static std::tm tm = {};
std::time_t const time = std::chrono::system_clock::to_time_t( tp );
{
std::unique_lock< std::mutex > ul( gmtime_call_mutex );
tm = *std::gmtime( &time );
}
return &tm;
}
#ifdef __COUNTER__
#define utc( arg ) utc_impl<__COUNTER__>( (arg) )
#else
#define utc( arg ) utc_impl<__LINE__>( (arg) )
#endif
Here we declare function with size_t template argument and returning pointer to static member std::tm. Now each call of this function with different template argument create a new function with brand new static std::tm variable. If __COUNTER__ macro is defined, it should be replaced by incremented integer value each time it is used, otherwise we use __LINE__ macro and in this case better to be sure that we do not call macro utc twice in one line.
Global gmtime_call_mutex protect non-threadsafe std::gmtime call in each instantiation, and at least in Linux shouldn't be a performance problem as lock acquiring is firstly performed as running around spinlock, and in our case should never end up with real thread lock.
thread_local ensures that different threads running same code with utc calls will still working with different std::tm variables.
Example of usage:
void work_with_range(
std::chrono::system_clock::time_point from = {}
, std::chrono::system_clock::time_point to = {}
)
{
std::cout << "Will work with range from "
<< ( from == decltype(from)()
? std::put_time( nullptr, "beginning" )
: std::put_time( utc( from ), "%Y-%m-%d %H:%M:%S" )
)
<< " to "
<< ( to == decltype(to)()
? std::put_time( nullptr, "end" )
: std::put_time( utc( to ), "%Y-%m-%d %H:%M:%S" )
)
<< "."
<< std::endl;
// ...
}
Boost: not entirely sure if this is thread safe, but it seems so:
#include "boost/date_time/posix_time/posix_time.hpp"
std::wstring stamp = boost::posix_time::to_iso_wstring(
boost::posix_time::second_clock::local_time());
std::wstring stamp = boost::posix_time::to_iso_wstring(
boost::posix_time::second_clock::universal_time());
See https://www.boost.org/doc/libs/1_75_0/doc/html/date_time/examples.html
I would like to use a boost::units in a project to use dimensional analysis and automatic conversions between unit systems. I would like to express quantities in the code with standard engineering units, that are often scaled versions of other units. Let me explain this with an example.
Suppose I define the following system
typedef make_system<
us::foot_base_unit,
us::pound_base_unit,
si::second_base_unit>::type my_system;
BOOST_UNITS_STATIC_CONSTANT(feet,length);
BOOST_UNITS_STATIC_CONSTANT(pound,mass);
Then length units would be defined in feet, force in lb*ft*s^-2 and pressure in lb*ft^-1*s^-2.
However, I would like to use force in pound-force units and pressure in PSI which are pound-force per square inch. I thought I could use scaled units to express these and use them interchangeably but this doesn't seem to be the case.
I tried this:
struct poundforcescale {
typedef double value_type;
double value() const { return 32.174049; }
};
typedef make_scaled_unit<force, poundforcescale>::type poundForce;
namespace boost {
namespace units {
std::string name_string(const field::poundForce&) { return "pound-force"; }
std::string symbol_string(const field::poundForce&) { return "lbf"; }
}
}
Which compiled without a problem. But then When I tried to use the scaled unit like this:
poundForce poundForceInst;
quantity<field::poundForce> f2 = 1*poundForceInst;
quantity<field::force> f3 = f2;
The compilation failed with an "no viable conversion error". I thought that the point of scaled units was to make these conversions automatically. And also the documentation made me think that I only needed to define name_string and symbol_string to be able to print the pound-force quantities, but this
std::cout << "f2 = " << f2 << std::endl;
resulted in a "no member named symbol in boost::units::scale_list_dim" error. Apparently overloading these functions doesn't work for scaled units.
Maybe I should define another system like this
typedef make_system<
us::foot_base_unit,
us::pound_force_base_unit,
si::second_base_unit>::type my_system;
But I would need conversions anyway if I want to express length in ft and pressure in psi.
I would be glad if someone has a better solution.
I did not really expect the following example to work, but indeed it does (g++ 4.6.4, with --std=c++0x):
#include <boost/multiprecision/float128.hpp>
#include <blitz/array.h>
#include <fftw3.h>
int main(int /*argc*/, char** /*argv*/)
{
//these are the same
std::cout << sizeof(std::complex<boost::multiprecision::float128>) << " " << sizeof(fftwq_complex) << std::endl;
typedef std::vector< std::complex<boost::multiprecision::float128> > boost128cvec;
//typedef std::vector<std::complex<boost::multiprecision::float128> , fftw::allocator< std::complex<boost::multiprecision::float128> > > boost128cvec;
//declare a std::vector consisting of std::complex<boost::multiprecision::float128>
boost128cvec test_vector3(12);
//casting its data storatge to fftwq_complex*
fftwq_complex* test_ptr3 = reinterpret_cast<fftwq_complex*>(test_vector3.data());
//also create a view to the same data as a blitz::Array
blitz::Array<std::complex<boost::multiprecision::float128>, 1> test_array3(test_vector3.data(), blitz::TinyVector<int, 1>(12), blitz::neverDeleteData);
test_vector3[3] = std::complex<boost::multiprecision::float128>(1.23,4.56);
//this line would not work with std::vector
test_array3 = sin(test_array3);
//this line would not work with the built-in type __float128
test_vector3[4] = sin(test_vector3[3]);
//all of those print the same numbers
std::cout << "fftw::vector: " << test_vector3[3].real() << " + i " << test_vector3[3].imag() << std::endl;
std::cout << "fftw_complex: " << (long double)test_ptr3[3][0] << " + i " << (long double)test_ptr3[3][1] << std::endl;
std::cout << "blitz: " << test_array3(3).real() << " + i " << test_array3(3).imag() << std::endl << std::endl;
}
Two remarks:
The goal is to be able to use both fftw and blitz::Array operations on the same data without the need to copy them around while at the same time being able to use generic funcionst like sin() also for complex variables with quad precision
The blitz-part works fine, which is expected. But the surprise (to me) was, that the fftwq_complex* part also works fine.
The fftw::allocator is a simple replacement to std::allocator which will use fftwq_malloc to assure correct simd alignment, but that is not important for this question, so I left it out (at least I think that this is not important for this question)
My Question is: How thin is the ice I'm stepping on?
You're pretty much save:
std::vector is compatible with a C array (you can access a pointer to the first element via vector.data(), as answered in this question
std::complex<T> is designed to be compatible with a Array of form T[2], which is compatible with FFTW. This is described in the FFTW documentation
C++ has its own complex template class, defined in the standard header file. Reportedly, the C++ standards committee has recently agreed to mandate that the storage format used for this type be binary-compatible with the C99 type, i.e. an array T[2] with consecutive real [0] and imaginary [1] parts. (See report http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2002/n1388.pdf WG21/N1388.) Although not part of the official standard as of this writing, the proposal stated that: “This solution has been tested with all current major implementations of the standard library and shown to be working.” To the extent that this is true, if you have a variable complex *x, you can pass it directly to FFTW via reinterpret_cast(x).
The only thing to keep in mind is that the data() gets invalidated if you add values to your vector.
For the last part there is the compatiblity between boost::multiprecision::float128 and __float128. The boost documentation gives no guarantee about this.
What can be done however, is to add some static asserts in your code, which fails if the conversion is not possible. This could look like this:
static_assert(std::is_standard_layout<float128>::value,"no standard type");
static_assert(sizeof(float128) == sizeof(__float128),"size mismatch");
Where sizeof guarantees the same size of the boost type and __float128, and is_standard_layout checks that:
A pointer to a standard-layout class may be converted (with reinterpret_cast) to a pointer to its first non-static data member and vice versa.
Of course, this only gives hints if it works in the end, as you cannot say if the type is really a __float128, but ab boost states their type is a thin wrapper around it, it should be fine. If their are changes in design or structure of float128, the static assertions should fail.