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.
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.
In the code below, does each instantiation of the template function lead to separate compiled object code? In other words, if I had lots of function calls like foo<398>() would this explode the size of the binary, or can the compiler do "something smart" in this case?
Sorry for a slightly vagueish question. Pointers to the appropriate docs welcome.
template <int N>
int foo()
{
return N;
}
int main()
{
int a = foo<1>();
int b = foo<2>();
std::cout << a << ", " << b << std::endl;
}
Within each translation unit, there is a magic point of instantiation for each template specialization, and each template specialization is instantiated at most once per translation unit.
There's still a very interesting problem of how different translation units link together (and indeed the linker needs to know how C++ works and deduplicate), but at least intra-TU there's only one version of the function.
(The instantiation point is when the second phase of the two-phase lookup happens. So you only get an error once (at instantiation time), not for every time you use the specialization.)
Yes, every instantiation with a different number will generate new binary code. This is a modified version of your example that proves that both functions have different addresses.
int main()
{
int (*p1)() = &foo<1>;
int (*p2)() = &foo<3>;
std::cout << (void*)(p1) << ", " << (void*)(p2) << std::endl;
}
Here is a live example: http://ideone.com/w5peQV
EDIT: Better example by #xaxxon http://godbolt.org/g/DYXtHs
DISCLAIMER: Your original example and other trivial examples like it ARE optimizable by the compiler, the function will probably be optimized away.
But if you take addresses of your functions, have more complex code or simply disable optimizations, it is not guaranteed that it will be optimized away and your compiler WILL generate code for each instantiation.
I'm starting to use the Karma generate feature to convert double to char with a sprintf like functionality.
For that I'm using the following example:
template <typename T>
class double3_policy : public boost::spirit::karma::real_policies<T>
{
public:
template <typename T>
static unsigned int precision(T)
{
return 3;
}
};
typedef boost::spirit::karma::real_generator<double, double3_policy<double> > double3_type;
double3_type const double3 ;
using boost::spirit::karma::left_align;
using boost::spirit::karma::generate;
char *p = buffer;
generate(p, '[' << left_align(14)[double3] << left_align(14)[double3] << ']', 12345.000, 22/7.0);
*p = '\0';
The example works fine, but the precision method is static, and I not realized how to set that value dynamically. I want to specify the precision for each use, changing that at execution time. I don't mind to create all generators at start, because I want a defined number of precisions.
The problem is that I don't believe I have to create a class for each precision number when the only difference between them is a returning number. I tried to compile the class with a member method (if this was a member precision method that would be enough for me), and I think I'm stuck at this class method problem.
How can I create generator objects with diferent precisions and just use them without create more then one class? If I can use just one generator just changing a property would be even better.
If anyone had the same problem and can share the solution will be very helpful.
Thanks,
Karma generators are all about specifying grammars using (compile-time!) expression templates, like an embedded DSL.
This does indeed make it less than applicable for dynamic format specifications.
I'd suggest to use
printf
Boost Format (a "safe printf" with many more features)
FastFormat (http://www.fastformat.org/)
The only way I can see this work with Karma is by creating a custom directive for real-printing which takes the precision as an extra argument. It's not worth it (and it will kill the only benefit you had for using Karma here: performance).
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!
I'm writing porting file-io set of functions from c into a c++ class. "Magic numbers" (unnamed constants) abound.
The functions read a file header which has a number of specific entries whose locations are currently denoted by magic numbers.
I was taught by a veteran programmer a couple years back that using "magic numbers" is inherently evil, and thus, I have since tried to avoid using unnamed constants in my port. So I want to create some sort of list of constants of where the entries are stored.
So far I've come up with two solutions that seem relatively safe -- use a namespace enclosed set of constants or a namespace enclosed enum.
Can I use either solution safely? Would there be any advantages to one over the other?
e.g.
OPTION 1
namespace hdr_pos {
const unsigned int item_1_pos=4;
const unsigned int item_2_pos=8;
const unsigned int item_3_pos=12;
const unsigned int item_4_pos=24;
const unsigned int item_5_pos=32;
};
OPTION 2
namespace hdr_pos {
enum e {
item_1_pos=4,
item_2_pos=8,
item_3_pos=12,
item_4_pos=24,
item_5_pos=32
};
};
Is there anyway to prevent duplicates, to catch if I change the positions due to a future update to the file header, but forget to change one of them?
Please keep this factual and non-subjective. If there is no advantage you know of, feel free to answer that.
Note: I would use more descriptive names, of course, in my actual implementation; I just called things item_<#>_... for examples sake...
I can see two advantages to using an enum. First, some debuggers can translate constants back into enum variable names (which can make debugging easier in some cases). Also, you can declare a variable of an enumerated type which can only hold a value from that enumeration. This can give you an additional form of type checking that you wouldn't have simply by using constants.
Checking to see if a value is duplicated might depend on your particular compiler. The easiest way to do so would probably be to write an external script that will parse your enum definition and report whether or not a value is duplicated (you can run this as part of your build process if you like).
I've dealt with this situation before, for error codes.
I have seen people using enums for error codes, and this pose some issues:
you can assign an int to the enum that doesn't not correspond to any value (too bad)
the value itself is declared in a header, meaning that error code reassignment (this happens...) breaks code compatibility, you also have to take care when adding elements...
you have to define all codes in the same header, even if often times some code are naturally restricted to a small portion of the application, because enums cannot be "extended"
there is no check that a same code is not assigned twice
you cannot iterate over the various fields of an enum
When designing my error codes solution, I thus chose another road: constants in a namespace, defined in source files, which address points 2 and 3. To gain in type safety though, the constants are not int, but a specific Code class:
namespace error { class Code; }
Then I can define several error files:
// error/common.hpp
namespace error
{
extern Code const Unknown;
extern Code const LostDatabaseConnection;
extern Code const LostNASConnection;
}
// error/service1.hpp
// error/service2.hpp
I didn't solved the arbitrary cast issue though (constructor is explicit, but public), because in my case I was required to forward error codes returned by other servers, and I certainly didn't want to have to know them all (that would have been too brittle)
However I did thought about it, by making the required constructor private and enforcing the use of a builder, we're even going to get 4. and 5. in a swoop:
// error/code.hpp
namespace error
{
class Code;
template <size_t constant> Code const& Make(); // not defined here
class Code: boost::totally_ordered<Code>
{
public:
Code(): m(0) {} // Default Construction is useful, 0 is therefore invalid
bool operator<(Code const& rhs) const { return m < rhs.m; }
bool operator==(Code const& rhs) const { return m == rhs.m; }
private:
template <size_t> friend Code const& Make();
explicit Code(size_t c): m(c) { assert(c && "Code - 0 means invalid"); }
size_t m;
};
std::set<Code> const& Codes();
}
// error/privateheader.hpp (inaccessible to clients)
namespace error
{
std::set<Code>& PrivateCodes() { static std::set<Code> Set; return Set; }
std::set<Code> const& Codes() { return PrivateCodes(); }
template <size_t constant>
Code const& Make()
{
static std::pair< std::set<Code>::iterator, bool > r
= PrivateCodes().insert(Code(constant));
assert(r.second && "Make - same code redeclared");
return *(r.first);
}
}
//
// We use a macro trick to create a function whose name depends
// on the code therefore, if the same value is assigned twice, the
// linker should complain about two functions having the same name
// at the condition that both are located into the same namespace
//
#define MAKE_NEW_ERROR_CODE(name, value) \
Make<value>(); void _make_new_code_##value ();
// error/common.cpp
#include "error/common.hpp"
#include "privateheader.hpp"
namespace error
{
Code const Unkown = MAKE_NEW_ERROR_CODE(1)
/// ....
}
A tad more work (for the framework), and only link-time/run-time check of the same assignment check. Though it's easy to diagnose duplicates simply by scanning for the pattern MAKE_NEW_ERROR_CODE
Have fun!
The title of your question suggests that the main reason you have doubts about using a enum is that your constants are non-iterative. But in C++ enum types are non-iterative already. You have to jump through quite a few hoops to make an iterative enum type.
I'd say that if your constants are related by nature, then enum is a pretty good idea, regardless of whether the constants are iterative or not. The main disadvantage of enums though is total lack of type control. In many cases you might prefer to have strict control over the types of your constant values (like have them unsigned) and that's something enum can't help you with (at least yet).
One thing to keep in mind is that you can't take the address of an enum:
const unsigned* my_arbitrary_item = &item_1_pos;
If they're purely constants and require no run-time stuff (like can't init enum with non-enum value) then they should just be const unsigned ints. Of course, the enum is less typing, but that's besides the point.