diff liboctave/util/oct-inttypes.cc @ 17993:ac9fd5010620

avoid including gnulib header in installed Octave header file (bug #40607) * oct-conf-post.in.h (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED): New macro. * oct-inttypes.h, oct-inttypes.cc: Don't include fpucw.h from gnulib or the macros it defines. In functions that need to ensure that long double operations are not truncated to double precision, use external functions.
author John W. Eaton <jwe@octave.org>
date Sat, 23 Nov 2013 20:28:46 -0500
parents 573f865aa8c8
children 79653c5b6147
line wrap: on
line diff
--- a/liboctave/util/oct-inttypes.cc
+++ b/liboctave/util/oct-inttypes.cc
@@ -25,6 +25,8 @@
 #include <config.h>
 #endif
 
+#include <fpucw.h>
+
 #include "lo-error.h"
 
 #include "oct-inttypes.h"
@@ -50,7 +52,88 @@
 DECLARE_OCTAVE_INT_TYPENAME (uint32_t, "uint32")
 DECLARE_OCTAVE_INT_TYPENAME (uint64_t, "uint64")
 
-#ifndef OCTAVE_INT_USE_LONG_DOUBLE
+#ifdef OCTAVE_INT_USE_LONG_DOUBLE
+
+#ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
+
+template <class xop>
+bool
+octave_int_cmp_op::external_mop (long double x, long double y)
+{
+   DECL_LONG_DOUBLE_ROUNDING
+
+   BEGIN_LONG_DOUBLE_ROUNDING ();
+
+   bool retval = xop::op (x, y);
+
+   END_LONG_DOUBLE_ROUNDING ();
+
+   return retval;
+}
+
+#define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(OP) \
+  template OCTAVE_API bool \
+  octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (long double, \
+                                                          long double)
+
+INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(lt);
+INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(le);
+INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(gt);
+INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(ge);
+INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(eq);
+INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(ne);
+
+uint64_t
+octave_external_uint64_uint64_mul (uint64_t x, uint64_t y)
+{
+  DECL_LONG_DOUBLE_ROUNDING
+
+  BEGIN_LONG_DOUBLE_ROUNDING ();
+
+  uint64_t retval = octave_int_arith_base<uint64_t, false>::mul_internal (x, y);
+
+  END_LONG_DOUBLE_ROUNDING ();
+
+  return retval;
+}
+
+int64_t
+octave_external_int64_int64_mul (int64_t x, int64_t y)
+{
+  DECL_LONG_DOUBLE_ROUNDING
+
+  BEGIN_LONG_DOUBLE_ROUNDING ();
+
+  int64_t retval = octave_int_arith_base<int64_t, true>::mul_internal (x, y);
+
+  END_LONG_DOUBLE_ROUNDING ();
+
+  return retval;
+}
+
+#define OCTAVE_LONG_DOUBLE_OP(OP, NAME) \
+  long double \
+  octave_external_long_double_ ## NAME (long double x, long double y) \
+  { \
+    DECL_LONG_DOUBLE_ROUNDING \
+ \
+    BEGIN_LONG_DOUBLE_ROUNDING (); \
+ \
+    long double retval = x OP y; \
+ \
+    END_LONG_DOUBLE_ROUNDING (); \
+ \
+    return retval; \
+  }
+
+OCTAVE_LONG_DOUBLE_OP (+, add)
+OCTAVE_LONG_DOUBLE_OP (-, sub)
+OCTAVE_LONG_DOUBLE_OP (*, mul)
+OCTAVE_LONG_DOUBLE_OP (/, div)
+
+#endif
+
+#else
 
 // Define comparison operators
 
@@ -142,7 +225,7 @@
 
 template <>
 uint64_t
-octave_int_arith_base<uint64_t, false>::mul (uint64_t x, uint64_t y)
+octave_int_arith_base<uint64_t, false>::mul_internal (uint64_t x, uint64_t y)
 {
   // Get upper words
   uint64_t ux = x >> 32, uy = y >> 32;
@@ -185,7 +268,7 @@
 
 template <>
 int64_t
-octave_int_arith_base<int64_t, true>::mul (int64_t x, int64_t y)
+octave_int_arith_base<int64_t, true>::mul_internal (int64_t x, int64_t y)
 {
   // The signed case is far worse. The problem is that
   // even if neither integer fits into signed 32-bit range, the result may