From c422b48bf43f9a1e2b29c4803c646de0617e32b4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 21 May 2015 15:06:47 +0100 Subject: [PATCH] Bugfix for hwf_manager::round_to_integral --- src/util/hwf.cpp | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/util/hwf.cpp b/src/util/hwf.cpp index 40d20b644..b159cbdb6 100644 --- a/src/util/hwf.cpp +++ b/src/util/hwf.cpp @@ -338,8 +338,39 @@ void hwf_manager::sqrt(mpf_rounding_mode rm, hwf const & x, hwf & o) { void hwf_manager::round_to_integral(mpf_rounding_mode rm, hwf const & x, hwf & o) { set_rounding_mode(rm); - modf(x.value, &o.value); - // Note: on x64, this sometimes produces an SNAN instead of a QNAN? + // CMW: modf is not the right function here. + // modf(x.value, &o.value); + + // According to the Intel Architecture manual, the x87-instrunction FRNDINT is the + // same in 32-bit and 64-bit mode. The _mm_round_* intrinsics are SSE4 extensions. + +#ifdef USE_INTRINSICS + switch (rm) { + case 0: _mm_store_sd(&o.value, _mm_round_pd(_mm_set_sd(x.value), _MM_FROUND_TO_NEAREST_INT)); break; + case 2: _mm_store_sd(&o.value, _mm_round_pd(_mm_set_sd(x.value), _MM_FROUND_TO_POS_INF)); break; + case 3: _mm_store_sd(&o.value, _mm_round_pd(_mm_set_sd(x.value), _MM_FROUND_TO_NEG_INF)); break; + case 4: _mm_store_sd(&o.value, _mm_round_pd(_mm_set_sd(x.value), _MM_FROUND_TO_ZERO)); break; + case 1: + UNREACHABLE(); // Note: MPF_ROUND_NEAREST_TAWAY is not supported by the hardware! + break; + default: + UNREACHABLE(); // Unknown rounding mode. + } +#else + NOT_IMPLEMENTED_YET(); +#endif + +#if 0 + double xv = x.value; + double & ov = o.value; + + __asm { + fld xv + frndint + fstp ov // Store result away. + } + +#endif } void hwf_manager::rem(hwf const & x, hwf const & y, hwf & o) {