We're working with boost::units as well, not for roots as you are, but generally through some fluid dynamics applications, necessarily calculations along these lines. We don't do roots, but frequently the calculations will momentarily undimension the value() from a thin-proxied-.NET-wrapper (in our case) to get it from a given BaseValue if you will before placing it back in the correct base dimension, which is necessarily compile-time-safe for the upcoming calculation, which is what we like about the library. I don't know if that helps give you any insight how to employ boost::units...
While I certainly understand the need here, I think in the general sense the only solution is to use the underlying *values* (not dimensioned quantities) under the hood, and where an algorithm can be used with dimensioned quantities, then provide a forwarding wrapper that checks the type/dimension safety of the arguments and result and internally forwards to the unchecked version. For example, I'm sure I'm missing something, but I don't see any traits classes in Boost.Units to calculate the result of an arithmetic expression involving dimensioned quantities? Plus I don't really want to make Boost.Math dependent upon Boost.Units.Lately I am using Boost.Units quite intensively for defining lots of
thermodynamic functions. The other day I needed a root finding algorithm
that can work on one of these functions. I look at couple of libraries,and
I ended up rolling and adaptor that adimensionalizes the function on
Boost.Units quantities, etc, etc.
Then I though, hey! we have Boost.Math tools, even root finding algorithms,
and these functions are *very* generic as Boost is supposed to be. And I
found the function:
boost::math::tools::bracket_and_solve_root
which has the perfect underlying algorithm for the application.
I started programming and after several compilation errors I realized that,
as happened before, the functions are not generic enough. For example the
arguments are
bracket_and_solve_root( F f, const T& guess, const T& factor, bool rising,
Tol tol, boost::uintmax_t& max_iter);
in my case "guess" is an argument type of type
boost::units::quantity<si::meter> but then "factor" has to be a *different*
type. For this function to be generic one need that factor is of new type
parameter.
In my opinion the function should be
template<typename F, typename T, typename Fact, typename Tol>
bracket_and_solve_root( F f, const T& guess, const T& factor, bool rising,
Tol tol, boost::uintmax_t& max_iter);
to begin with (and then there is a chain of other internal changes).
What do you think? should I open a bug ticket?
Let's put it in more abstract way: T*T=T should not be a requirement for a
root algorithm to work.
Once and for all, can we give a name to the model type of which Boost.Units
quantity models for? so the library writers stop assuming that T*T=T for
numeric values and can improve half-way generic libraries?
Other numeric libraries that suffer from this deficiency are
Boost.Accumulators, Boost.Geometry, and Boost.Interval among the ones I
tried. I think this issues should be addressed, not only to make them work
with Boost.Units but also to bring those libraries to a higher level of
generality.
Just curious, but what's wrong with providing your own thin wrapper that forwards to the undimensioned function?
And finally, this reminds me that we never did ask for a review of the Math "tools" including these root finding algorithms, so officially, this function is an implementation of Boost.Math - albeit a minimally documented one. The code is solid, but as mentioned in the intro to the tools section - these are details - so we reserve the right to change the interface if required - or a better interface comes along - not that we ever have.... yet! ;)
John.
_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users