std_min/std_max reference return value is problematic with boost::interval

Eric, The recent changes to the new std_min/std_max caused some unexpected problems in uBLAS. I have narrowed them down to support for boost::numeric::interval in uBLAS. This is picked up by ublas/libs/test7. This test is however not at present part of the regression run. The new std_max (or std_min) is implemented by returning a constant reference to the return value of std::max. This should be OK as std::max similarly returns a const reference to one of its const reference parameters. For gcc this causes some problems when the type is a boost::numeric::interval. The test case is very simple. #include <boost/numeric/interval.hpp> #include <boost/minmax.hpp> int main() { boost::numeric::interval<float> a,b,c; c = boost::std_max(a, a); } gcc (2.95.3 and 3.3.1) is only warning "returning reference to temporary". I am surprised this doesn't show up in more cases. Why gcc thinks it needs a temporary here is beyond me Michael -- ___________________________________ Michael Stevens Systems Engineering ___________________________________

Michael Stevens wrote:
The test case is very simple.
#include <boost/numeric/interval.hpp> #include <boost/minmax.hpp>
int main() { boost::numeric::interval<float> a,b,c; c = boost::std_max(a, a); }
gcc (2.95.3 and 3.3.1) is only warning "returning reference to temporary". I am surprised this doesn't show up in more cases. Why gcc thinks it needs a temporary here is beyond me
Yup, Dave anticipated this problem, and fixing it is on my To-Do list. The problem is due to the fact that max is overloaded for the interval type to return a non-reference: template<class T, class Policies> inline interval<T, Policies> max (const interval<T, Policies>& x, const interval<T, Policies>& y) { typedef interval<T, Policies> I; if (interval_lib::detail::test_input(x, y)) return I::empty(); return I(std_max(x.lower(), y.lower()), std_max(x.upper(), y.upper()), true); } The fix is to detect whether the unqualified call to max returns an lvalue or not and define the return type of std_max appropriately. Easy enough. What strikes me as odd with this overload, though, is that max(a,b) in this case will return something that is not equal to either a or b. That seems counter-intuitive. Is this right? -- Eric Niebler Boost Consulting www.boost-consulting.com

Le lun 08/03/2004 à 20:08, Eric Niebler a écrit :
Michael Stevens wrote:
The test case is very simple.
#include <boost/numeric/interval.hpp> #include <boost/minmax.hpp>
int main() { boost::numeric::interval<float> a,b,c; c = boost::std_max(a, a); }
gcc (2.95.3 and 3.3.1) is only warning "returning reference to temporary". I am surprised this doesn't show up in more cases. Why gcc thinks it needs a temporary here is beyond me
[...]
The fix is to detect whether the unqualified call to max returns an lvalue or not and define the return type of std_max appropriately. Easy enough.
What strikes me as odd with this overload, though, is that max(a,b) in this case will return something that is not equal to either a or b. That seems counter-intuitive. Is this right?
Yes this is right :-) In interval arithmetic, all the functions are usually defined by canonical set extensions. It is also the case for max. Consequently max(A,B) is the interval {max(a,b); a in A and b in B}. When A and B don't overlap, the result is A or B. But it isn't the case when they overlap. And it isn't as much counter-intuitive as you seem to think. How would you define max(A,B) when you have neither A < B nor A > B (it happens when A and B overlap)? Getting A or B in that case would be counter-intuitive. Regards, Guillaume

Le lun 08/03/2004 à 18:53, Michael Stevens a écrit :
Eric,
The recent changes to the new std_min/std_max caused some unexpected problems in uBLAS. I have narrowed them down to support for boost::numeric::interval in uBLAS. This is picked up by ublas/libs/test7. This test is however not at present part of the regression run.
The new std_max (or std_min) is implemented by returning a constant reference to the return value of std::max. This should be OK as std::max similarly returns a const reference to one of its const reference parameters. For gcc this causes some problems when the type is a boost::numeric::interval. The test case is very simple.
#include <boost/numeric/interval.hpp> #include <boost/minmax.hpp>
int main() { boost::numeric::interval<float> a,b,c; c = boost::std_max(a, a); }
gcc (2.95.3 and 3.3.1) is only warning "returning reference to temporary". I am surprised this doesn't show up in more cases. Why gcc thinks it needs a temporary here is beyond me
Hi, The reason is: the return type of the function max(interval const &, interval const &) is not a constant reference, it is a temporary (since the maximum of two intervals is not one of these two intervals when they overlap). Consequently, since std_max has been defined so that it returns a reference, it can't be used when one argument is an interval and GCC is right to complain. Consequently, having std_min and std_max functions was not a good solution. Is it possible to have macros that behave like them (that way there would be no return type problem)? However, in the particular case of uBLAS, the problem lies elsewhere imho. At lines 620-621, 688-689, 753-754 of ublas/traits.hpp in the equals function, uBLAS should not be using the norm_inf function. Indeed norm_inf relies on abs(interval); and what is really needed is a norm_inf_for_equals function that would rely on norm(interval). The same problem will also appear later with complex intervals. This solution should solve the issue with uBLAS. But the more general issue of the return type of std_min and std_max is still here. Regards, Guillaume
participants (3)
-
Eric Niebler
-
Guillaume Melquiond
-
Michael Stevens