[m-rev.] diff: speed up is_finite/1 and is_nan/1 in C grades

Julien Fischer jfischer at opturion.com
Wed Sep 17 12:01:14 AEST 2014


Speed up is_finite/1 and is_nan/1 in C grades.

The Mercury runtime procedures MR_is_{inf,nan} are defined as functions, even
on systems (e.g. all those that support the relevant bits of C99), where the
underlying C stdlib uses macros to implement those operations.  Define the
above runtime procedures as macros speeds up an artificial test case (counting
infinities in a list of floats) by ~3.5%.

Change the name of MR_is_inf to MR_is_infinite.

runtime/mercury_float.h:
 	Rename MR_is_inf to MR_is_infinite.

 	Define MR_is_{infinite,nan} as macros on systems that support C99.
 	This avoids some unnecessary function call overhead.

 	Rename the function versions of MR_is_infinite and MR_is_nan to
 	MR_is_infinite_func and MR_is_nan_func.

runtime/mercury_float.c:
library/float.m:
 	Conform to the above changes.

diff --git a/library/float.m b/library/float.m
index 4b7b0c2..bc263e3 100644
--- a/library/float.m
+++ b/library/float.m
@@ -692,7 +692,7 @@ is_infinite(F) :-
  	[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
          does_not_affect_liveness],
  "
-	SUCCESS_INDICATOR = MR_is_inf(Flt);
+	SUCCESS_INDICATOR = MR_is_infinite(Flt);
  ").
  :- pragma foreign_proc("IL",
  	is_inf(Flt::in),
diff --git a/runtime/mercury_float.c b/runtime/mercury_float.c
index 90ecfc4..dee4ab0 100644
--- a/runtime/mercury_float.c
+++ b/runtime/mercury_float.c
@@ -76,7 +76,7 @@ MR_sprintf_float(char *buf, MR_Float f)
          return;
      }

-    if (MR_is_inf(f)) {
+    if (MR_is_infinite(f)) {
          if (f < 0) {
              strcpy(buf, "-infinity");
          } else {
@@ -122,7 +122,7 @@ MR_sprintf_float(char *buf, MR_Float f)
  }

  MR_bool
-MR_is_nan(MR_Float Flt)
+MR_is_nan_func(MR_Float Flt)
  {
  #if defined(MR_USE_SINGLE_PREC_FLOAT) && defined(MR_HAVE_ISNANF)
      return isnanf(Flt);
@@ -136,7 +136,7 @@ MR_is_nan(MR_Float Flt)
  }

  MR_bool
-MR_is_inf(MR_Float Flt)
+MR_is_inf_func(MR_Float Flt)
  {
      /*
      ** On Solaris, isinf() is detected by configure but we pass -fno-builtin
diff --git a/runtime/mercury_float.h b/runtime/mercury_float.h
index 7c40298..4e4a6fa 100644
--- a/runtime/mercury_float.h
+++ b/runtime/mercury_float.h
@@ -210,7 +210,31 @@ void MR_sprintf_float(char *buf, MR_Float f);

  MR_Integer MR_hash_float(MR_Float);

-MR_bool MR_is_nan(MR_Float);
-MR_bool MR_is_inf(MR_Float);
+/*
+** We define MR_is_{nan,infinite} as macros if we support the relevant bits
+** of C99 since the resulting code is faster.
+*/
+#if defined(MR_USE_SINGLE_PREC_FLOAT) && defined(MR_HAVE_ISNANF)
+    #define MR_is_nan(f) isnanf((f))
+#elif defined(MR_HAVE_ISNAN)
+    #define MR_is_nan(f) isnan((f))
+#else
+    #define MR_is_nan(f) MS_is_nan_func((f))
+#endif
+
+/*
+** See comments for function MR_is_infinite_func in mercury_float.c for the
+** handling of Solaris here.
+*/
+#if defined(MR_USE_SINGLE_PREC_FLOAT) && defined(MR_HAVE_ISINFF) && !defined(MR_SOLARIS)
+    #define MR_is_infinite(f) isinff((f))
+#elif defined(MR_HAVE_ISINF) && !defined(MR_SOLARIS)
+    #define MR_is_infinite(f) isinf((f))
+#else
+    #define MR_is_infinite(f) MR_is_infinite_func((f))
+#endif
+
+MR_bool MR_is_nan_func(MR_Float);
+MR_bool MR_is_infinite_func(MR_Float);

  #endif /* not MERCURY_FLOAT_H */



More information about the reviews mailing list