Re: [boost] Portable signbit macro/function?

----Original Message---- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Peter Dimov Sent: 04 August 2006 11:39 To: boost@lists.boost.org Subject: Re: [boost] Portable signbit macro/function?
Johan Råde wrote:
I still find it hard to believe that the volatile are needed ;-)
It is not.
If volatile is not present, then you can't instantiate the template with T="volatile float" for example. (Similarly you need the "const" so that you can invoke with T="const float".) I suspect that for this application that doesn't matter, but that Gennaro was so used to using the safe form: reinterpret_cast<const volatile char*>(&s) to get at the bytes of an object in a template, that he just wrote it automatically. -- Martin Bonner Martin.Bonner@Pitechnology.com Pi Technology, Milton Hall, Ely Road, Milton, Cambridge, CB4 6WZ, ENGLAND Tel: +44 (0)1223 203894

Martin Bonner wrote:
Johan Råde wrote:
I still find it hard to believe that the volatile are needed ;-)
It is not.
If volatile is not present, then you can't instantiate the template with T="volatile float" for example. (Similarly you need the "const" so that you can invoke with T="const float".)
template<class T, class S> T binary_cast( S const & s ) { T t; memcpy( &t, &s, sizeof(T) ); return t; } You need the const on s to be able to pass rvalues such as 1.0, not for const lvalues. It is true that binary_cast will fail to compile if you pass a volatile object as source, this is intentional; accessing a volatile object as a sequence of bytes can be dangerous if that volatile object is an I/O port. You definitely don't need a volatile on t, it only inhibits useful optimizations.

Here is a new version of signbit, taking input from Peter Dimov into account: template<class T, class S> T binary_cast(const S& s) { BOOST_STATIC_ASSERT(sizeof(S) == sizeof(T)); T t; memcpy(&t, &s, sizeof(S)); return t; } const boost::uint32_t signbit_mask = binary_cast<boost::uint32_t>(1.0f) ^ binary_cast<boost::uint32_t>(-1.0f); inline bool signbit(float x) { return binary_cast<boost::uint32_t>(x) & signbit_mask; } inline bool signbit(double x) { return signbit(static_cast<float>(x)); } inline bool signbit(long double x) { return signbit(static_cast<float>(x)); } The code should work on any platform with 1. IEEE 754 or some similar representation 2. sizeof(float) == 4 3. casts between different numeric types preserve the sign bit, also for non-finite numbers. The function is intended to be used when there is no predefined signbit function or macro. --Johan Råde

Peter Dimov wrote:
Martin Bonner wrote:
Johan Råde wrote:
I still find it hard to believe that the volatile are needed ;-)
It is not.
If volatile is not present, then you can't instantiate the template with T="volatile float" for example. (Similarly you need the "const" so that you can invoke with T="const float".)
template<class T, class S> T binary_cast( S const & s ) { T t; memcpy( &t, &s, sizeof(T) ); return t; }
So you were talking about T. Sorry. :-) Since binary_cast doesn't appear to be safe for use in generic code, it seems reasonable to assume that a programmer invoking binary_cast<const float> or binary_cast<volatile float> expects a return type of const float or volatile float, respectively. But this is impossible. R-values of type float are never cv-qualified. It doesn't make sense to support such incorrect signatures to be produced (even though it's trivially possible by using remove_cv once to remove the error or twice to remove the potential compiler warning about a cv-qualified float return type.)

On Fri, 4 Aug 2006 12:00:16 +0100, "Martin Bonner" <martin.bonner@pitechnology.com> wrote:
----Original Message---- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Peter Dimov Sent: 04 August 2006 11:39 To: boost@lists.boost.org Subject: Re: [boost] Portable signbit macro/function?
Johan Råde wrote:
I still find it hard to believe that the volatile are needed ;-)
It is not.
If volatile is not present, then you can't instantiate the template with T="volatile float" for example. (Similarly you need the "const" so that you can invoke with T="const float".)
I suspect that for this application that doesn't matter, but that Gennaro was so used to using the safe form: reinterpret_cast<const volatile char*>(&s) to get at the bytes of an object in a template, that he just wrote it automatically.
Yes :-) And I didn't use boost::addressof because it uses char, not unsigned char (there are endless debates here, especially after C99 has made some properties of signed char explicit; in any case you are safe at home with unsigned; God knows where you are with plain char). I should add that I didn't write a template, just something resembling one :-) And the code was meant to throw an idea, not to be so carefully analyzed (which is welcome, anyway). It's important, too, that some care is taken to have the value in memory, not in a register (think for instance of Intel's native format); the latter may happen implicitly when passing the floating point as argument. In any case, I just used "one" and "minus one", and as local variables: passing a generic value opens a whole new can of worms. -- [ Gennaro Prota, C++ developer for hire ]

Gennaro Prota wrote:
On Fri, 4 Aug 2006 12:00:16 +0100, "Martin Bonner" <martin.bonner@pitechnology.com> wrote:
----Original Message---- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Peter Dimov Sent: 04 August 2006 11:39 To: boost@lists.boost.org Subject: Re: [boost] Portable signbit macro/function?
Johan Råde wrote:
I still find it hard to believe that the volatile are needed ;-)
It is not.
If volatile is not present, then you can't instantiate the template with T="volatile float" for example. (Similarly you need the "const" so that you can invoke with T="const float".)
I suspect that for this application that doesn't matter, but that Gennaro was so used to using the safe form: reinterpret_cast<const volatile char*>(&s) to get at the bytes of an object in a template, that he just wrote it automatically.
Yes :-)
One might make the argument that adding volatile (automatically) almost never leads to safety of any kind. :-)
And I didn't use boost::addressof because it uses char, not unsigned char (there are endless debates here, especially after C99 has made some properties of signed char explicit; in any case you are safe at home with unsigned; God knows where you are with plain char).
You are safe with plain char, see 3.9/2, although unsigned char is arguably a better practice style-wise.

On Fri, 4 Aug 2006 16:00:12 +0300, "Peter Dimov" <pdimov@mmltd.net> wrote:
And I didn't use boost::addressof because it uses char [...]
You are safe with plain char, see 3.9/2, although unsigned char is arguably a better practice style-wise.
I don't think so: http://tinyurl.com/zlxg6 (tiny address refers to message #46 of <http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/90be8a86531e936> ) -- [ Gennaro Prota, C++ developer for hire ]
participants (4)
-
Gennaro Prota
-
Johan Råde
-
Martin Bonner
-
Peter Dimov