Permalink
Browse files

Infinity is now by default an acceptable value for type 'float'.

This fix makes the handling of type 'float' and 'double' the same. The implementation requires the
C99 isfinite() macro, or otherwise some platform dependent equivalents, to be available.
  • Loading branch information...
1 parent f47075e commit a91cd0bc5c1550bfa2c922c7434323c30ca1fb87 @wsfulton wsfulton committed Sep 12, 2013
View
@@ -5,6 +5,22 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 2.0.11 (in progress)
============================
+2013-09-12: wsfulton
+ [UTL] Infinity is now by default an acceptable value for type 'float'. This fix makes
+ the handling of type 'float' and 'double' the same. The implementation requires the
+ C99 isfinite() macro, or otherwise some platform dependent equivalents, to be available.
+
+ Users requiring the old behaviour of not accepting infinity, can define a 'check' typemap
+ wherever a float is used, such as:
+
+ %typemap(check,fragment="<float.h>") float, const float & %{
+ if ($1 < -FLT_MAX || $1 > FLT_MAX) {
+ SWIG_exception_fail(SWIG_TypeError, "Overflow in type float");
+ }
+ %}
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
2013-08-30: wsfulton
[Lua] Pull Git patch #81: Include Lua error locus in SWIG error messages.
This is standard information in Lua error messages, and makes it much
@@ -285,8 +285,9 @@ CPP_TEST_CASES += \
operbool \
ordering \
overload_copy \
- overload_method \
overload_extend \
+ overload_method \
+ overload_numeric \
overload_rename \
overload_return_type \
overload_simple \
@@ -0,0 +1,51 @@
+%module overload_numeric
+
+// Tests overloading of integral and floating point types to verify the range checking required
+// for dispatch to the correct overloaded method
+
+#ifdef SWIGLUA
+// lua only has one numeric type, so most of the overloads shadow each other creating warnings
+%warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) Nums::over;
+#endif
+
+%{
+#include <iostream>
+%}
+
+%inline %{
+#include <limits.h>
+#include <float.h>
+struct Limits {
+ signed char schar_min() { return SCHAR_MIN; }
+ signed char schar_max() { return SCHAR_MAX; }
+ short shrt_min() { return SHRT_MIN; }
+ short shrt_max() { return SHRT_MAX; }
+ int int_min() { return INT_MIN; }
+ int int_max() { return INT_MAX; }
+ float flt_min() { return FLT_MIN; }
+ float flt_max() { return FLT_MAX; }
+ double dbl_max() { return DBL_MAX; }
+};
+
+struct Nums {
+ const char * over(signed char v) {
+ return "signed char";
+ }
+ const char * over(short v) {
+ return "short";
+ }
+ const char * over(int v) {
+ return "int";
+ }
+ const char * over(float v) {
+ return "float";
+ }
+ const char * over(double v) {
+ return "double";
+ }
+ double doublebounce(double v) {
+ return v;
+ }
+};
+%}
+
@@ -0,0 +1,43 @@
+
+from overload_numeric import *
+import math
+
+nums = Nums()
+limits = Limits()
+
+def check(got, expected):
+ if got != expected:
+ raise RuntimeError("got: " + got + " expected: " + expected)
+
+check(nums.over(0), "signed char")
+check(nums.over(0.0), "float")
+
+check(nums.over(limits.schar_min()), "signed char")
+check(nums.over(limits.schar_max()), "signed char")
+
+check(nums.over(limits.schar_min()-1), "short")
+check(nums.over(limits.schar_max()+1), "short")
+check(nums.over(limits.shrt_min()), "short")
+check(nums.over(limits.shrt_max()), "short")
+
+check(nums.over(limits.shrt_min()-1), "int")
+check(nums.over(limits.shrt_max()+1), "int")
+check(nums.over(limits.int_min()), "int")
+check(nums.over(limits.int_max()), "int")
+
+check(nums.over(limits.flt_min()), "float")
+check(nums.over(limits.flt_max()), "float")
+
+check(nums.over(limits.flt_max()*10), "double")
+check(nums.over(-limits.flt_max()*10), "double")
+check(nums.over(limits.dbl_max()), "double")
+check(nums.over(-limits.dbl_max()), "double")
+
+check(nums.over(float("inf")), "float")
+check(nums.over(float("-inf")), "float")
+check(nums.over(float("nan")), "float")
+
+# Just check if the following are accepted without exceptions being thrown
+nums.doublebounce(float("inf"))
+nums.doublebounce(float("-inf"))
+nums.doublebounce(float("nan"))
@@ -153,6 +153,29 @@
#include <stddef.h>
%}
+%fragment("SWIG_isfinite","header",fragment="<math.h>,<float.h>") %{
+/* Getting isfinite working pre C99 across multiple platforms is non-trivial. Users can provide SWIG_isfinite on older platforms. */
+#ifndef SWIG_isfinite
+# if defined(isfinite)
+# define SWIG_isfinite(X) (isfinite(X))
+# elif defined(_MSC_VER)
+# define SWIG_isfinite(X) (_finite(X))
+# elif defined(__sun) && defined(__SVR4)
+# include <ieeefp.h>
+# define SWIG_isfinite(X) (finite(X))
+# endif
+#endif
+%}
+
+%fragment("SWIG_Float_Overflow_Check","header",fragment="<float.h>,SWIG_isfinite") %{
+/* Accept infinite as a valid float value unless we are unable to check if a value is finite */
+#ifdef SWIG_isfinite
+# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX) && SWIG_isfinite(X))
+#else
+# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX))
+#endif
+%}
+
/* -----------------------------------------------------------------------------
* special macros for fragments
* ----------------------------------------------------------------------------- */
@@ -213,13 +236,20 @@ SWIG_AsVal_dec(Type)(SWIG_Object obj, Type *val)
%enddef
-/* Macro for 'double' derived types */
+/* Macro for floating point derived types (original macro) */
%define %numeric_double(Type, Frag, Min, Max)
%numeric_type_from(Type, double)
%numeric_signed_type_asval(Type, double, Frag , Min, Max)
%enddef
+/* Macro for floating point derived types */
+
+%define %numeric_float(Type, Frag, OverflowCond)
+%numeric_type_from(Type, double)
+%numeric_type_asval(Type, double, Frag, OverflowCond)
+%enddef
+
/* Macros for missing fragments */
@@ -139,7 +139,7 @@ SWIG_AsVal_dec(bool)(SWIG_Object obj, bool *val)
/* float */
-%numeric_double(float, "<float.h>", -FLT_MAX, FLT_MAX)
+%numeric_float(float, "SWIG_Float_Overflow_Check", SWIG_Float_Overflow_Check(v))
/* long/unsigned long */

0 comments on commit a91cd0b

Please sign in to comment.