lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re[2]: [lmi] Unit test for C99 round()


From: Vadim Zeitlin
Subject: Re[2]: [lmi] Unit test for C99 round()
Date: Thu, 5 Jun 2008 14:28:45 +0200

On Thu, 05 Jun 2008 03:35:57 +0000 Greg Chicares <address@hidden> wrote:

GC> | AIUI (but you shouldn't rely completely on my recollection),
GC> | rint() or equivalent is called when the floating-point style
GC> | is already set to the style desired: then it should just do
GC> | the right thing, without incurring the overhead of changing
GC> | the floating-point control word. It's hard to say more from
GC> | here about what's happening on your machine, but we could
GC> | instrument it more elaborately--for instance, to print out
GC> | the actual and hoped-for control words.
GC> 
GC> Can you try that? Here's some copied (and trivially modified)
GC> code to show the whole control word, if you want to use print
GC> statements as your "debugger":
GC> 
GC>     std::ostringstream oss;
GC>     oss
GC>         << "The floating-point control word was '"
GC>         << std::hex << std::internal << std::showbase << std::setfill('0')
GC> #if defined LMI_X86
GC>         << std::setw(6) << x87_control_word()
GC> #else  // Unknown compiler or platform.
GC> #   error Unknown compiler or platform.
GC> #endif // Unknown compiler or platform.
GC>         << "'."
GC>         << "\n"
GC>         ;
GC> Or, with gdb, it's 'info float' IIRC.

 Thanks, this did help to narrow down the problem: it is due to the fact
that set_hardware_rounding_mode() in round_to_test.cpp() also tests for
__STDC_IEC_559__ before LMI_X86 and so uses the standard fesetround()
instead of LMI fenv_rounding(). So far so good, but fesetround() must be
passed FE_TONEAREST (whose value is the same as fe_tonearest in enum
e_ieee754_rounding defined in fenv_lmi_x86.hpp) or one of FE_DOWNWARD,
FE_UPWARD or FE_TOWARDZEO whose values are not at all the same. So setting
hardware rounding mode to anything but "to nearest" fails. And the code
doesn't even notice it because it doesn't check the return value of
fesetround().

 So the simplest way to fix the test is:

--- round_to_test.cpp 2008-06-03 18:25:34 +0000
+++ round_to_test.cpp 2008-06-05 12:22:33 +0000
@@ -107,10 +107,10 @@

 void set_hardware_rounding_mode(e_ieee754_rounding mode, bool synchronize)
 {
-#ifdef __STDC_IEC_559__
+#if defined LMI_X86
+    fenv_rounding(mode);
+#elif defined(__STDC_IEC_559__)
     fesetround(mode);
-#elif defined LMI_X86
-    fenv_rounding(mode);
 #else // No known way to set hardware rounding mode.
     std::cerr
         << "\nCannot set floating-point hardware rounding mode.\n"

To be complete I'd also add a test of fesetround() return value but then I
can't really test it as long as I'm only testing LMI under x86. Maybe we
should have a separate define LMI_X86_FP which would be defined by default
if LMI_X86 is but could be manually undefined to force the use of standard
FP functions even under x86 at least in order to test them, what do you
think?

 In any case, for now it probably would make sense to do the above change
as it's consistent with all the other such checks.

 Thanks,
VZ





reply via email to

[Prev in Thread] Current Thread [Next in Thread]