From adcc211feb7827127b2548c791f2de0b6efda3d3 Mon Sep 17 00:00:00 2001 From: Hein-Pieter van Braam Date: Tue, 14 Feb 2017 04:10:02 +0100 Subject: [PATCH] Make nan==nan true for GDScript After discussing this with Reduz this seemed like the best way to fix #7354. This will make composite values that contain NaN in the same places as well as the same other values compare as the same. Additionally non-composite values now also compare equal if they are both NaN. This breaks IEEE specifications but this is probably what most users expect. There is a GDScript function check for NaN if the user needs this information. This fixes #7354 and probably also fixes #6947 --- core/math/math_2d.cpp | 7 ++++ core/math/math_2d.h | 3 ++ core/math/plane.cpp | 5 +++ core/math/plane.h | 1 + core/math/quat.cpp | 19 +++++++++++ core/math/quat.h | 2 +- core/math/vector3.cpp | 11 +++++++ core/math/vector3.h | 1 + core/variant_op.cpp | 76 +++++++++++++++++++++++++++++-------------- 9 files changed, 99 insertions(+), 26 deletions(-) diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp index 76eeece688b..995cb0834a6 100644 --- a/core/math/math_2d.cpp +++ b/core/math/math_2d.cpp @@ -157,6 +157,13 @@ bool Vector2::operator!=(const Vector2& p_vec2) const { return x!=p_vec2.x || y!=p_vec2.y; } +bool Vector2::nan_equals(const Vector2& p_vec2) const { + + return (x==p_vec2.x && y==p_vec2.y) || + (x==p_vec2.x && isnan(y) && isnan(p_vec2.y)) || + (isnan(x) && isnan(p_vec2.x) && y == p_vec2.y); +} + Vector2 Vector2::floor() const { return Vector2( Math::floor(x), Math::floor(y) ); diff --git a/core/math/math_2d.h b/core/math/math_2d.h index a24c4266eec..6dd8799ba2c 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -133,6 +133,7 @@ struct Vector2 { bool operator<(const Vector2& p_vec2) const { return (x==p_vec2.x)?(y(p_a._data._mem) m_op *reinterpret_cast(p_b._data._mem));\ + case m_name: _RETURN( (*reinterpret_cast(p_a._data._mem))m_op(*reinterpret_cast(p_b._data._mem)));\ default: {}\ }\ r_valid=false;\ return;} - #define DEFAULT_OP_LOCALMEM_NEG(m_name,m_type)\ case m_name: {\ _RETURN( -*reinterpret_cast(p_a._data._mem));\ @@ -177,13 +188,28 @@ r_valid=false;\ return;} #define DEFAULT_OP_ARRAY_EQ(m_name,m_type)\ -DEFAULT_OP_ARRAY_OP(m_name,m_type,!=,!=,true,false,false) +DEFAULT_OP_ARRAY_OP(m_name,m_type,!=,!=,true,false,false,true) + +#define DEFAULT_OP_ARRAY_EQ_NAN(m_name,m_type)\ + DEFAULT_ARRAY_OP_HEAD(m_name,m_type,!=,false,false)\ + if ((ra[i] != rb[i]) && (isnan(ra[i]) != isnan(rb[i])))\ + _RETURN(false);\ + DEFAULT_ARRAY_OP_FOOT(true) + +#define DEFAULT_OP_ARRAY_EQ_NAN_V(m_name,m_type)\ +DEFAULT_OP_ARRAY_OP(m_name,m_type,!=,.nan_equals,true,false,false,false) #define DEFAULT_OP_ARRAY_LT(m_name,m_type)\ -DEFAULT_OP_ARRAY_OP(m_name,m_type,<,!=,false,a_len::Read ra = array_a.read();\ PoolVector::Read rb = array_b.read();\ \ for(int i=0;i