Ann: Floating Point Utilities Review starts today
The review of Johan Rade's floating point utilities starts today. Code and docs can be downloaded from : http://www.boost-consulting.com/vault/index.php?action=downloadfile&filename=floating_point_utilities_v3.zip&directory=Math%20-%20Numerics& The library consists of three parts: 1) Floating point classification routines: these are optimised implementations of the C99 and C++ TR1 functions fpclassify, isinf, isnan, isnormal and isfinite. From Boost-1.35 onwards these are already a part of Boost.Math (see http://svn.boost.org/svn/boost/trunk/libs/math/doc/sf_and_dist/html/math_too...) so if accepted the two implementations will get merged. The review here should focus on the implementation used, and testing on whatever platforms you have available - in particular are there any circumstances (compiler optimisation settings etc) where this implementation breaks? 2) Sign manipulation functions: implementations of the C99 and C++ TR1 functions copysign and signbit, plus the changesign function. Two of these (signbit and copysign) are currently undocumented members of Boost.Math, and again the two implementations will get merged if this library is accepted. Again the main focus of the review here is the implementation, and testing thereof especially in the presence of compiler optimisations. 3) C++ locale facets: these will read and write non-finite numbers in a portable and round-trippable way: that is not otherwise possible with current C++ std library implementations. These are particularly useful for number-serialisation for example. Since the design is already specified by the C++ standard for these facets, your review here should focus on implementation, testing, documentation, and perhaps where in Boost these should best be placed if accepted. These look to be a useful collection of utilities, so I'll look forward to your reviews, Regards, John Maddock, Floating Point Utilities Review Manager.
John Maddock wrote:
2) Sign manipulation functions: implementations of the C99 and C++ TR1 functions copysign and signbit, plus the changesign function. Two of these (signbit and copysign) are currently undocumented members of Boost.Math
That was news to me :-) --Johan
John Maddock wrote:
3) C++ locale facets: these will read and write non-finite numbers in a portable and round-trippable way: that is not otherwise possible with current C++ std library implementations. These are particularly useful for number-serialisation for example.
Since the design is already specified by the C++ standard for these facets, your review here should focus on implementation, testing, documentation, and perhaps where in Boost these should best be placed if accepted.
Actually, there are som interface issues to be discussed here: 1. Are the trap_infinity and trap_nan flags a good idea? I added them at Robert Ramey's request, but I'm not convinced myself. The implementation is not entirely satisfactory. In the ideal implementation both nonfinite_num_put and nonfinite_num_get would report infinity or nan by setting the failbit of the stream. The problem is that the std::num_put facet don't have access to the stream state. Hence std::num_get reports infinity or nan by setting the failbit of the stream while std::num_put reports infinity or nan by throwing an exception. 2. I have chosen to implement the flags as arguments to the constructor. The flags can not be changed after the facet has been constructed. An alternative design would be to use the xalloc and iword mechanism. Then one could have an interface for changing the flags using stream manipulators. But that would require a cpp file to be added to the library. (I consider this a flaw in the design of the standard iostreams library. A design that relied on GUIDs instead of xalloc would be more flexible.) 3. nan is formatted as "nan" or "-nan" depending on the signbit. Maybe the default should be to always format nan as "nan", and have a signed_nan flag, similar to the signed_zero flag, to show the signbit when formatting nan. --Johan
Johan Råde wrote:
John Maddock wrote:
3) C++ locale facets: these will read and write non-finite numbers in a portable and round-trippable way: that is not otherwise possible with current C++ std library implementations. These are particularly useful for number-serialisation for example.
Since the design is already specified by the C++ standard for these facets, your review here should focus on implementation, testing, documentation, and perhaps where in Boost these should best be placed if accepted.
Actually, there are som interface issues to be discussed here:
1. Are the trap_infinity and trap_nan flags a good idea? I added them at Robert Ramey's request, but I'm not convinced myself. The implementation is not entirely satisfactory. In the ideal implementation both nonfinite_num_put and nonfinite_num_get would report infinity or nan by setting the failbit of the stream. The problem is that the std::num_put facet don't have access to the stream state. Hence std::num_get reports infinity or nan by setting the failbit of the stream while std::num_put reports infinity or nan by throwing an exception.
Hmm - I don't remember requesting this - of course that doesn't mean I didn't do it. I do believe that portable FP classification is necessary but I don't think it has to be an exception. I think one would expect the following behavior in a serialization library. a) option to request trap on attempt to serialize NaN. This would be implemented as part of the serialization library. b) permit portable serialization of NaNs. Implementing this would require the ability to class the the FP objects on saving and "re-create" the same type of objects when loaded. Its not clear to me that this is even possible when moving text versions of archives across architectures since not all architectures support all types NaNs. The problem came up in the context of serialization library usage but of course its really an issue with stream IO as it relates to NaNs Robert Ramey
2. I have chosen to implement the flags as arguments to the constructor. The flags can not be changed after the facet has been constructed. An alternative design would be to use the xalloc and iword mechanism. Then one could have an interface for changing the flags using stream manipulators. But that would require a cpp file to be added to the library. (I consider this a flaw in the design of the standard iostreams library. A design that relied on GUIDs instead of xalloc would be more flexible.)
3. nan is formatted as "nan" or "-nan" depending on the signbit. Maybe the default should be to always format nan as "nan", and have a signed_nan flag, similar to the signed_zero flag, to show the signbit when formatting nan.
--Johan
Robert Ramey wrote:
Johan Råde wrote:
1. Are the trap_infinity and trap_nan flags a good idea? I added them at Robert Ramey's request, but I'm not convinced myself.
Hmm - I don't remember requesting this - of course that doesn't mean I didn't do it.
You certainly did. See http://article.gmane.org/gmane.comp.lib.boost.user/19986 This post was the original motivation for writing these utilities. (Robert suggested separate classes for the trapping and non-trapping behavior. Instead I made it the same classes, but with flags to enable to trapping.) --Johan
John Maddock wrote:
The review of Johan Rade's floating point utilities starts today.
Code and docs can be downloaded from : http://www.boost-consulting.com/vault/index.php?action=downloadfile&filename=floating_point_utilities_v3.zip&directory=Math%20-%20Numerics&
Hello all, we use fp_utilities in our portable binary archive implementation to serialize floating point numbers. For doing so we found the functions fp_traits<T>_impl::get_bits() and set_bits() to be exactly what we need. In combination with Beman Dawes endian library we're able to transfer binary data between ppc-32 and x86-32 reliably. This might serve as a usecase since John Maddock pointed out serialization as a prominent application of the library. /** * save floating point types * * We simply rely on fp_traits to extract the bit pattern into an (unsigned) * integral type and store that into the stream. * * \todo treat nan values using fp_classify */ template <typename T> BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_floating_point<T>
::type save(const T & t, dummy<3> = 0) { using namespace boost::math::detail; BOOST_DEDUCED_TYPENAME fp_traits<T>::type::bits bits; fp_traits<T>::type::get_bits(t, bits); save(bits); }
As you can see our code depends on functions that apparently are not part of the public interface and I wonder why. Perhaps I overlooked something? Those interested in the full code can find it in the boost vault. To sum it up: We think the fp_utilities provide useful functionality and our tests indicate reliability that can be counted on. So thank you Johan Rade for this contribution! Best Regards, -- Christian Pfligersdorffer Software Engineering http://www.eos.info John Maddock wrote:
The review of Johan Rade's floating point utilities starts today.
[...]
3) C++ locale facets: these will read and write non-finite numbers in a portable and round-trippable way: that is not otherwise possible with current C++ std library implementations. These are particularly useful for number-serialisation for example.
Since the design is already specified by the C++ standard for these facets, your review here should focus on implementation, testing, documentation, and perhaps where in Boost these should best be placed if accepted.
These look to be a useful collection of utilities, so I'll look forward to your reviews,
Pfligersdorffer, Christian wrote:
Hello all,
we use fp_utilities in our portable binary archive implementation to serialize floating point numbers. For doing so we found the functions fp_traits<T>_impl::get_bits() and set_bits() to be exactly what we need. In combination with Beman Dawes endian library we're able to transfer binary data between ppc-32 and x86-32 reliably. This might serve as a usecase since John Maddock pointed out serialization as a prominent application of the library.
/** * save floating point types * * We simply rely on fp_traits to extract the bit pattern into an (unsigned) * integral type and store that into the stream. * * \todo treat nan values using fp_classify */ template <typename T> BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_floating_point<T>
::type save(const T & t, dummy<3> = 0) { using namespace boost::math::detail; BOOST_DEDUCED_TYPENAME fp_traits<T>::type::bits bits; fp_traits<T>::type::get_bits(t, bits); save(bits); }
As you can see our code depends on functions that apparently are not part of the public interface and I wonder why. Perhaps I overlooked something? Those interested in the full code can find it in the boost vault.
Hi Christian, You are using an undocumented internal implementation detail of the library for a purpose for which it is not intended. Be warned that the math::detail::fp_traits<T>::type::get_bits() function is *not* guaranteed to give you all bits of the floating point number. It will give you all bits if and only if there is an integer type that has the same size as the floating point you are copying from. It will not give you all bits for double if there is no uint64_t. It will not give you all bits for long double if sizeof(long double) > 8 or there is no uint64_t. The member fp_traits<T>::type::coverage will tell you whether all bits are copied. This is a typedef for either math::detail::all_bits or math::detail::not_all_bits. If the function does not copy all bits, then it will copy the most significant bits. So if you serialize and deserialize the way you describe, and fp_traits<T>::type::coverage is math::detail::not_all_bits, then your floating point numbers will be truncated. This will introduce small rounding off errors. Be careful, Johan Råde
To sum it up: We think the fp_utilities provide useful functionality and our tests indicate reliability that can be counted on. So thank you Johan Rade for this contribution!
Best Regards,
-- Christian Pfligersdorffer Software Engineering http://www.eos.info
To access the native binary representation of floating-point type T, isn't it easier & safer to use a union of T and a character array with sizeof (T) elements? Matt Pfligersdorffer, Christian wrote:
Hello all,
we use fp_utilities in our portable binary archive implementation to serialize floating point numbers. For doing so we found the functions fp_traits<T>_impl::get_bits() and set_bits() to be exactly what we need. In combination with Beman Dawes endian library we're able to transfer binary data between ppc-32 and x86-32 reliably. This might serve as a usecase since John Maddock pointed out serialization as a prominent application of the library.
/** * save floating point types * * We simply rely on fp_traits to extract the bit pattern into an (unsigned) * integral type and store that into the stream. * * \todo treat nan values using fp_classify */ template <typename T> BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_floating_point<T>
::type
save(const T & t, dummy<3> = 0) { using namespace boost::math::detail; BOOST_DEDUCED_TYPENAME fp_traits<T>::type::bits bits; fp_traits<T>::type::get_bits(t, bits); save(bits); }
As you can see our code depends on functions that apparently are not part of the public interface and I wonder why. Perhaps I overlooked something? Those interested in the full code can find it in the boost vault.
To sum it up: We think the fp_utilities provide useful functionality and our tests indicate reliability that can be counted on. So thank you Johan Rade for this contribution!
Best Regards,
-- Christian Pfligersdorffer Software Engineering http://www.eos.info
John Maddock wrote:
The review of Johan Rade's floating point utilities starts today.
[...]
3) C++ locale facets: these will read and write non-finite numbers in a portable and round-trippable way: that is not otherwise possible with current C++ std library implementations. These are particularly useful for number-serialisation for example.
Since the design is already specified by the C++ standard for these facets, your review here should focus on implementation, testing, documentation, and perhaps where in Boost these should best be placed if accepted.
These look to be a useful collection of utilities, so I'll look forward to your reviews,
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Matt Gruenke wrote:
To access the native binary representation of floating-point type T, isn't it easier & safer to use a union of T and a character array with sizeof (T) elements?
1. Doing that is not legal. The C++ standard states that only one value in a union can be active at the same time time. And it may not work with some optimizing compilers. 2. For my purposes, I needed to copy the bits, and then make integer comparisons of the copied bits. Hence I copy the bits into integers. 3. For other purposes, using an array of char and memcpy might be best. Note that memcpy is very efficient. Both MSVC and GCC knows the meaning of memcpy and generates optimized code for the copying. A memcpy of 4 bytes will result in a single move instruction. --Johan
John Maddock wrote:
The review here should focus on the implementation used, and testing on whatever platforms you have available - in particular are there any circumstances (compiler optimisation settings etc) where this implementation breaks?
Earlier versions of the code had some nonportable casts. These have been removed. There are only two things that can make the current implementation fail: 1. Unsupported floating point formats. The library supports the IEEE formats for float and double and also a number of non-IEEE formats for long double. I will add support for other floating point formats if needed. (The VAX floating point formats are not supported. These are still available on VMS, but the default on VMS is the IEEE formats. Boris Gubenko did not think there was any need to support the VAX formats.) 2. Endianness problems. The header boost/detail/endian.hpp is used (in some cases) to detect endianness. There may be bugs in that header. There may also be some hypothetical situations that that header can not deal with, for instance platforms where endianness can change at runtime, or platforms where integers and floating point numbers have different endianness. Any Boost library that depends on endian.hpp would be affected by that problem. The solution would be to improve endian.hpp. --Johan
2008/2/18, John Maddock <john@johnmaddock.co.uk>:
The review of Johan Rade's floating point utilities starts today.
Just a quick reply: Is there any plans to include efficient comparison (equality) of floating point numbers? I could not find anything related in the library docs. Thank you. Hermann O. Rodrigues
Hermann Rodrigues wrote:
2008/2/18, John Maddock <john@johnmaddock.co.uk>:
The review of Johan Rade's floating point utilities starts today.
Just a quick reply: Is there any plans to include efficient comparison (equality) of floating point numbers? I could not find anything related in the library docs.
Thank you.
Hermann O. Rodrigues
No. --Johan
Just a quick reply: Is there any plans to include efficient comparison (equality) of floating point numbers? I could not find anything related in the library docs.
Hermann O. Rodrigues
No.
--Johan
I would like to second this motion, as there are many pitfalls in doing this manually. Here is a link I found on the pitfalls involved and ways to solve them: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm Robert Kindred
Robert Kindred wrote:
Just a quick reply: Is there any plans to include efficient comparison (equality) of floating point numbers? I could not find anything related in the library docs.
Hermann O. Rodrigues No.
--Johan
I would like to second this motion, as there are many pitfalls in doing this manually. Here is a link I found on the pitfalls involved and ways to solve them:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Robert Kindred
Why don't you write code for this and submit to Boost? --Johan
"Johan Råde" <rade@maths.lth.se> wrote in message news:fqb3c8$n04$1@ger.gmane.org...
Robert Kindred wrote: []
I would like to second this motion, as there are many pitfalls in doing this manually. Here is a link I found on the pitfalls involved and ways to solve them:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm Robert Kindred Why don't you write code for this and submit to Boost?
--Johan
Thanks, Johan, are you suggesting I add this to your library? If so, I would use your traits mechanism. Robert Kindred
Robert Kindred wrote:
"Johan Råde" <rade@maths.lth.se> wrote in message news:fqb3c8$n04$1@ger.gmane.org...
Robert Kindred wrote: []
I would like to second this motion, as there are many pitfalls in doing this manually. Here is a link I found on the pitfalls involved and ways to solve them:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm Robert Kindred Why don't you write code for this and submit to Boost?
--Johan
Thanks, Johan, are you suggesting I add this to your library? If so, I would use your traits mechanism.
Robert Kindred
Of course you can do that. I'm not sure what the formal procedure is, but we could find out. Could you give a brief explanation of exactly what it is you want to add? I looked at the link, and there they discussed several different problems. --Johan
"Johan Råde" <rade@maths.lth.se> wrote in message news:fqh5ob$l9m$1@ger.gmane.org... []
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm [] Why don't you write code for this and submit to Boost?
--Johan
Thanks, Johan, are you suggesting I add this to your library? If so, I would use your traits mechanism.
Robert Kindred
Of course you can do that. I'm not sure what the formal procedure is, but we could find out. Could you give a brief explanation of exactly what it is you want to add? I looked at the link, and there they discussed several different problems. --Johan We have software we wrote in-house to run engine stands to perform data acquisition and control, according to tests specified by the Society of Automotive Engineers. Oops, I am already not brief. The short of it is that, in the real world, floating point numbers are almost never equal, even when you think they should be. Even if I convert a floating point number to a string and back again, there is a good chance the 'before' and the 'after' differ bitwise. We are using the absolute-value-epsilon approach now, but we have, I think 3 different epsilons that we use, depending on what we predict the magnitude of the compared values will be. I am looking into this Sign-Magnitude comparison routine for high-speed floating point compares. One caveat is that it would only work on IEEE floating point numbers. This seemed like a floating point utility to me, so the name of your library caught my eye. Robert Kindred
I know it's getting pretty far afield, but this reminds me of a floating point enumerator I once wrote, in order to test various numeric optimizations by perfect induction. It works much like an iterator, and can be used to cover all valid float values in a given range. Would there be interest in something like that? Again, sorry to follow a tangent, but another floating point utility I've found useful is an epsilon function. Unlike std::numeric_limits<>::epsilon(), it takes an argument. It also returns 1, for integral types (this is USEFUL - why doesn't the standard library's?!?). Matt Robert Kindred wrote:
Just a quick reply: Is there any plans to include efficient comparison (equality) of floating point numbers? I could not find anything related in the library docs.
Hermann O. Rodrigues
No.
--Johan
I would like to second this motion, as there are many pitfalls in doing this manually. Here is a link I found on the pitfalls involved and ways to solve them:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Robert Kindred
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Matt Gruenke a écrit :
Again, sorry to follow a tangent, but another floating point utility I've found useful is an epsilon function. Unlike std::numeric_limits<>::epsilon(), it takes an argument. It also returns 1, for integral types (this is USEFUL - why doesn't the standard library's?!?).
I second matt on this point. The epsilon<T>(x) function is pretty useful and is definitevly lacking from sandard library. -- Joel FALCOU Research Engineer @ Institut d'Electronique Fondamentale Université PARIS SUD XI France
Just a gentle reminder that the review of Johan Rade's floating point utilities code is currently under way, and we could use a few more reviews of these useful utilities ! :-) John Maddock.
The review of Johan Rade's floating point utilities starts today.
Code and docs can be downloaded from : http://www.boost-consulting.com/vault/index.php?action=downloadfile&filename=floating_point_utilities_v3.zip&directory=Math%20-%20Numerics&
The library consists of three parts:
1) Floating point classification routines: these are optimised implementations of the C99 and C++ TR1 functions fpclassify, isinf, isnan, isnormal and isfinite. From Boost-1.35 onwards these are already a part of Boost.Math (see http://svn.boost.org/svn/boost/trunk/libs/math/doc/sf_and_dist/html/math_too...) so if accepted the two implementations will get merged.
The review here should focus on the implementation used, and testing on whatever platforms you have available - in particular are there any circumstances (compiler optimisation settings etc) where this implementation breaks?
2) Sign manipulation functions: implementations of the C99 and C++ TR1 functions copysign and signbit, plus the changesign function. Two of these (signbit and copysign) are currently undocumented members of Boost.Math, and again the two implementations will get merged if this library is accepted.
Again the main focus of the review here is the implementation, and testing thereof especially in the presence of compiler optimisations.
3) C++ locale facets: these will read and write non-finite numbers in a portable and round-trippable way: that is not otherwise possible with current C++ std library implementations. These are particularly useful for number-serialisation for example.
Since the design is already specified by the C++ standard for these facets, your review here should focus on implementation, testing, documentation, and perhaps where in Boost these should best be placed if accepted.
These look to be a useful collection of utilities, so I'll look forward to your reviews,
Regards,
John Maddock,
Floating Point Utilities Review Manager.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
3) C++ locale facets: these will read and write non-finite numbers in a portable and round-trippable way: that is not otherwise possible with current C++ std library implementations. These are particularly useful for number-serialisation for example.
There are quite a few test failures from these, I'm hoping these are related to these facets rather than the underlying utility code: MSVC-8 (debug) Running 8 test cases... nonfinite_num_facets/legacy_test.cpp(120): error in "legacy_test": check (isnan) (b11) failed nonfinite_num_facets/legacy_test.cpp(138): error in "legacy_test": check ss.rdst ate() == std::ios_base::eofbit failed nonfinite_num_facets/legacy_test.cpp(120): error in "legacy_test": check (isnan) (b11) failed nonfinite_num_facets/legacy_test.cpp(138): error in "legacy_test": check ss.rdst ate() == std::ios_base::eofbit failed nonfinite_num_facets/legacy_test.cpp(120): error in "legacy_test": check (isnan) (b11) failed nonfinite_num_facets/legacy_test.cpp(138): error in "legacy_test": check ss.rdst ate() == std::ios_base::eofbit failed nonfinite_num_facets/legacy_test.cpp(120): error in "legacy_test": check (isnan) (b11) failed nonfinite_num_facets/legacy_test.cpp(138): error in "legacy_test": check ss.rdst ate() == std::ios_base::eofbit failed nonfinite_num_facets/legacy_test.cpp(120): error in "legacy_test": check (isnan) (b11) failed nonfinite_num_facets/legacy_test.cpp(138): error in "legacy_test": check ss.rdst ate() == std::ios_base::eofbit failed nonfinite_num_facets/legacy_test.cpp(120): error in "legacy_test": check (isnan) (b11) failed nonfinite_num_facets/legacy_test.cpp(138): error in "legacy_test": check ss.rdst ate() == std::ios_base::eofbit failed *** 12 failures detected in test suite "Master Test Suite" MSVC-8 (release + SSE2) Running 8 test cases... nonfinite_num_facets/basic_test.cpp(167): error in "basic_test": check ss.str() == s failed nonfinite_num_facets/basic_test.cpp(182): error in "basic_test": check (signbit) (b2) failed nonfinite_num_facets/basic_test.cpp(184): error in "basic_test": check (signbit) (b4) failed nonfinite_num_facets/basic_test.cpp(167): error in "basic_test": check ss.str() == s failed nonfinite_num_facets/basic_test.cpp(182): error in "basic_test": check (signbit) (b2) failed nonfinite_num_facets/basic_test.cpp(184): error in "basic_test": check (signbit) (b4) failed nonfinite_num_facets/basic_test.cpp(167): error in "basic_test": check ss.str() == s failed nonfinite_num_facets/basic_test.cpp(182): error in "basic_test": check (signbit) (b2) failed nonfinite_num_facets/basic_test.cpp(184): error in "basic_test": check (signbit) (b4) failed nonfinite_num_facets/basic_test.cpp(167): error in "basic_test": check ss.str() == s failed nonfinite_num_facets/basic_test.cpp(182): error in "basic_test": check (signbit) (b2) failed nonfinite_num_facets/basic_test.cpp(184): error in "basic_test": check (signbit) (b4) failed nonfinite_num_facets/basic_test.cpp(167): error in "basic_test": check ss.str() == s failed nonfinite_num_facets/basic_test.cpp(182): error in "basic_test": check (signbit) (b2) failed nonfinite_num_facets/basic_test.cpp(184): error in "basic_test": check (signbit) (b4) failed nonfinite_num_facets/basic_test.cpp(167): error in "basic_test": check ss.str() == s failed nonfinite_num_facets/basic_test.cpp(182): error in "basic_test": check (signbit) (b2) failed nonfinite_num_facets/basic_test.cpp(184): error in "basic_test": check (signbit) (b4) failed nonfinite_num_facets/lexical_cast_test.cpp(86): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a9) == s9 failed nonfinite_num_facets/lexical_cast_test.cpp(87): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a10) == s10 failed nonfinite_num_facets/lexical_cast_test.cpp(86): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a9) == s9 failed nonfinite_num_facets/lexical_cast_test.cpp(87): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a10) == s10 failed nonfinite_num_facets/lexical_cast_test.cpp(86): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a9) == s9 failed nonfinite_num_facets/lexical_cast_test.cpp(87): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a10) == s10 failed nonfinite_num_facets/lexical_cast_test.cpp(86): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a9) == s9 failed nonfinite_num_facets/lexical_cast_test.cpp(87): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a10) == s10 failed nonfinite_num_facets/lexical_cast_test.cpp(86): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a9) == s9 failed nonfinite_num_facets/lexical_cast_test.cpp(87): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a10) == s10 failed nonfinite_num_facets/lexical_cast_test.cpp(86): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a9) == s9 failed nonfinite_num_facets/lexical_cast_test.cpp(87): error in "lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a10) == s10 failed *** 30 failures detected in test suite "Master Test Suite" Perhaps perversely, VC8 in release mode, but without the /arch:SSE2 option passes all the tests. Intel-10.1 has similar failures (except in SSE2 mode!), so this may be iostream's related. Full review to follow.... John.
John Maddock wrote:
Perhaps perversely, VC8 in release mode, but without the /arch:SSE2 option passes all the tests.
And that is the only configuration that I have tested in the past. Intel-10.1 has similar failures (except in SSE2 mode!), so this may be iostream's related. I don't have either VC8 or Intel 10.1. I will download the free 30-day evaluation version of Intel 10.1 and take a look. --Johan
John Maddock wrote:
Intel-10.1 has similar failures (except in SSE2 mode!), so this may be iostream's related.
I have reproduced the failures on Intel 10.1. The only thing that was wrong was the tests. After I replaced -std::numeric_limits<ValType>::quiet_NaN() -std::numeric_limits<ValType>::signaling_NaN() by changesign(std::numeric_limits<ValType>::signaling_NaN()) changesign(std::numeric_limits<ValType>::quiet_NaN()) everywhere in the tests, then all tests passed. Could you check if that does the trick on VC8 as well? --Johan
John Maddock wrote: --------------------------------------------------------------------------------------------
MSVC-8 (debug)
Running 8 test cases... nonfinite_num_facets/legacy_test.cpp(120): error in "legacy_test": check (isnan) (b11) failed
[snip]
nonfinite_num_facets/legacy_test.cpp(138): error in "legacy_test": check ss.rdst ate() == std::ios_base::eofbit failed
*** 12 failures detected in test suite "Master Test Suite"
Could you check the value of ss.str() after line 105 in legacy_test.cpp? This test tests that the facet boost::math::nonfinite_num_get, with the boost::math::legacy flag set, can handle 1) a list of known non-standard text representations of infinity and NaN (see the library docs) 2) the native text representations of infinity and NaN on the platform being tested. So one possible explanation for the failure is that the creative people at Microsoft have come up with yet another way of formatting NaN in a text stream. The test is templated and is run for all combinations of float, double, long double and char, wchar_t. So the 12 failures are really just 2 failures. The second failure is probably a consequence of the first one. So there is probably just one failure. --------------------------------------------------------------------------------------------
MSVC-8 (release + SSE2)
Running 8 test cases... nonfinite_num_facets/basic_test.cpp(167): error in "basic_test": check ss.str() == s failed
[snip]
"lexical_cast_test": ch eck lexical_cast<std::basic_string<CharType> >(a10) == s10 failed
*** 30 failures detected in test suite "Master Test Suite"
Fix: Replace -std::numeric_limits<ValType>::quiet_NaN() -std::numeric_limits<ValType>::signaling_NaN() by changesign(std::numeric_limits<ValType>::quiet_NaN()) changesign(std::numeric_limits<ValType>::signaling_NaN()) everywhere in the tests. ------------------------------------------------------------------------------------------------ --Johan
Johan Råde wrote:
Could you check the value of ss.str() after line 105 in legacy_test.cpp?
1.#QNAN -1.#IND 1.#QNAN -1.#QNAN With MSVC's debug checks enabled the attempt to read from the stream at line 108 results in a debug assertion being triggered and the code aborting: it tries to increment the istream_iterator past the end :-( BTW both VC8 and VC9 express editions are free downloads from MS's web pages. Changing from -std::numeric_limits<>::whatever() to changesign(whatever) fixes the SSE2 problem with VC8 and VC9 BTW, however this is probably best considered either a compiler bug, or a loophole in the std if this is permitted behaviour. HTH, John.
John Maddock wrote:
Johan Råde wrote:
Could you check the value of ss.str() after line 105 in legacy_test.cpp?
1.#QNAN -1.#IND 1.#QNAN -1.#QNAN
With MSVC's debug checks enabled the attempt to read from the stream at line 108 results in a debug assertion being triggered and the code aborting: it tries to increment the istream_iterator past the end :-(
Can you check if it is reading b11 that causes problems in line 108: ss >> b1 >> b2 >> b3 >> b4 >> b5 >> b6 >> b7 >> b8 >> b9 >> b10 >> b11; What happens if you change line 105 from ss << " qnan snan nanq nans 1.#IND 1.#QNAN 1.#SNAN"; to (note the space at the end of the string) ss << " qnan snan nanq nans 1.#IND 1.#QNAN 1.#SNAN ";
BTW both VC8 and VC9 express editions are free downloads from MS's web pages.
Changing from -std::numeric_limits<>::whatever() to changesign(whatever) fixes the SSE2 problem with VC8 and VC9 BTW, however this is probably best considered either a compiler bug, or a loophole in the std if this is permitted behaviour.
If I drop the support for signed NaN, then whis will become a non-issue anyway. --Johan
Johan Råde wrote:
John Maddock wrote:
Johan Råde wrote:
Could you check the value of ss.str() after line 105 in legacy_test.cpp?
1.#QNAN -1.#IND 1.#QNAN -1.#QNAN
With MSVC's debug checks enabled the attempt to read from the stream at line 108 results in a debug assertion being triggered and the code aborting: it tries to increment the istream_iterator past the end :-(
Can you check if it is reading b11 that causes problems in line 108:
ss >> b1 >> b2 >> b3 >> b4 >> b5 >> b6 >> b7 >> b8 >> b9 >> b10
b11;
What happens if you change line 105 from
ss << " qnan snan nanq nans 1.#IND 1.#QNAN 1.#SNAN";
to (note the space at the end of the string)
ss << " qnan snan nanq nans 1.#IND 1.#QNAN 1.#SNAN ";
Yep, that fixes it, but shouldn't be needed? HTH John.
John Maddock wrote:
Johan Råde wrote:
What happens if you change line 105 from
ss << " qnan snan nanq nans 1.#IND 1.#QNAN 1.#SNAN";
to (note the space at the end of the string)
ss << " qnan snan nanq nans 1.#IND 1.#QNAN 1.#SNAN ";
Yep, that fixes it, but shouldn't be needed?
It doesn't fix it. It just diagnoses it. There must be a missing eof check somewhere. (Strange that this shows up now. The library has been exhaustively tested.) --Johan
John Maddock wrote:
There are quite a few test failures from these, I'm hoping these are related to these facets rather than the underlying utility code:
MSVC-8 (debug)
Running 8 test cases... nonfinite_num_facets/legacy_test.cpp(120): error in "legacy_test": check (isnan) (b11) failed
[snip]
nonfinite_num_facets/legacy_test.cpp(138): error in "legacy_test": check ss.rdst ate() == std::ios_base::eofbit failed
I think I have a fix for this too. Just remove line 393 (++it;) in nonfinite_num_facets.h. --Johan
John Maddock wrote:
Johan Råde wrote:
I think I have a fix for this too. Just remove line 393 (++it;) in nonfinite_num_facets.h.
Confirmed, cheers, John.
I think there is a lesson to be learned here about how difficult it is to write good tests. What happened was that when parsing 1.#INF the stream pointer was moved one step to far. So if the input had been say 1.#INF\t then the tab would have been lost. This could cause serious errors when reading a tab separated text file. None of the tests detected this problem. --Johan
Today is the last day of the Floating Point Utilities review. So far there there have been four reviews: Paul Bristow, Hartmut Kaiser, Zach Laine and John Phillips. It is clear from the discussion so far that there are many more Boosters who are interested in this problem domain. --Johan John Maddock wrote:
The review of Johan Rade's floating point utilities starts today.
Code and docs can be downloaded from : http://www.boost-consulting.com/vault/index.php?action=downloadfile&filename=floating_point_utilities_v3.zip&directory=Math%20-%20Numerics&
The library consists of three parts:
1) Floating point classification routines: these are optimised implementations of the C99 and C++ TR1 functions fpclassify, isinf, isnan, isnormal and isfinite. From Boost-1.35 onwards these are already a part of Boost.Math (see http://svn.boost.org/svn/boost/trunk/libs/math/doc/sf_and_dist/html/math_too...) so if accepted the two implementations will get merged.
The review here should focus on the implementation used, and testing on whatever platforms you have available - in particular are there any circumstances (compiler optimisation settings etc) where this implementation breaks?
2) Sign manipulation functions: implementations of the C99 and C++ TR1 functions copysign and signbit, plus the changesign function. Two of these (signbit and copysign) are currently undocumented members of Boost.Math, and again the two implementations will get merged if this library is accepted.
Again the main focus of the review here is the implementation, and testing thereof especially in the presence of compiler optimisations.
3) C++ locale facets: these will read and write non-finite numbers in a portable and round-trippable way: that is not otherwise possible with current C++ std library implementations. These are particularly useful for number-serialisation for example.
Since the design is already specified by the C++ standard for these facets, your review here should focus on implementation, testing, documentation, and perhaps where in Boost these should best be placed if accepted.
These look to be a useful collection of utilities, so I'll look forward to your reviews,
Regards,
John Maddock,
Floating Point Utilities Review Manager.
This has been a very valuable review. I have received a lot of valuable feedback, many suggestions for how to improve the library, both interface, implementation and docs. I will soon post a revised version, that takes your feedback into account. And then, if John decides to accept the library, he and I can merge the overlapping parts of this library and the Math Toolkit. Many thanks to all of you, Johan Råde
Johan Råde wrote:
This has been a very valuable review. I have received a lot of valuable feedback, many suggestions for how to improve the library, both interface, implementation and docs.
I'd just add a short postscript to this - although the review period is officially over - if there are any late reviews still to come please do still submit them! Regards, John Maddock Review Manager for floating point utilities.
participants (9)
-
Hermann Rodrigues
-
Joel FALCOU
-
Johan Råde
-
John Maddock
-
Matt Gruenke
-
Neal Becker
-
Pfligersdorffer, Christian
-
Robert Kindred
-
Robert Ramey