dd option of doing fuzzy equality tests.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@27958 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2009-02-23 08:57:49 +00:00
parent 1db6e01877
commit 1be05b5cd7
3 changed files with 123 additions and 29 deletions

View file

@ -1,3 +1,13 @@
2009-02-23 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSGeometry.h:
* Source/NSGeometry.m:
Inspired by Matt Rice's comments on NSEqualRects(), moved the
equality testing functions from the header to the implementation
file and added conditionally compiled code to allow us to do a
fuzzy equality test. Still need to decide whether this is actually
the correct thing to do though.
2009-02-22 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSUnarchiver.m:

View file

@ -423,41 +423,18 @@ NSIntersectionRect (NSRect aRect, NSRect bRect)
/** Test geometric relationships... **/
GS_GEOM_SCOPE BOOL
/** Returns 'YES' iff aRect's and bRect's origin and size are the same. */
GS_EXPORT BOOL
NSEqualRects(NSRect aRect, NSRect bRect) GS_GEOM_ATTR;
/** Returns 'YES' iff aRect's and bRect's origin and size are the same. */
GS_GEOM_SCOPE BOOL
NSEqualRects(NSRect aRect, NSRect bRect)
{
return ((NSMinX(aRect) == NSMinX(bRect))
&& (NSMinY(aRect) == NSMinY(bRect))
&& (NSWidth(aRect) == NSWidth(bRect))
&& (NSHeight(aRect) == NSHeight(bRect))) ? YES : NO;
}
GS_GEOM_SCOPE BOOL
NSEqualSizes(NSSize aSize, NSSize bSize) GS_GEOM_ATTR;
/** Returns 'YES' iff aSize's and bSize's width and height are the same. */
GS_GEOM_SCOPE BOOL
NSEqualSizes(NSSize aSize, NSSize bSize)
{
return ((aSize.width == bSize.width)
&& (aSize.height == bSize.height)) ? YES : NO;
}
GS_GEOM_SCOPE BOOL
NSEqualPoints(NSPoint aPoint, NSPoint bPoint) GS_GEOM_ATTR;
GS_EXPORT BOOL
NSEqualSizes(NSSize aSize, NSSize bSize) GS_GEOM_ATTR;
/** Returns 'YES' iff aPoint's and bPoint's x- and y-coordinates
* are the same. */
GS_GEOM_SCOPE BOOL
NSEqualPoints(NSPoint aPoint, NSPoint bPoint)
{
return ((aPoint.x == bPoint.x)
&& (aPoint.y == bPoint.y)) ? YES : NO;
}
GS_EXPORT BOOL
NSEqualPoints(NSPoint aPoint, NSPoint bPoint) GS_GEOM_ATTR;
GS_GEOM_SCOPE BOOL
NSMouseInRect(NSPoint aPoint, NSRect aRect, BOOL flipped) GS_GEOM_ATTR;

View file

@ -36,6 +36,7 @@
#include "config.h"
#include <math.h>
#include <stdlib.h>
#include "GNUstepBase/preface.h"
#include "Foundation/NSString.h"
#include "Foundation/NSGeometry.h"
@ -388,3 +389,109 @@ NSRectFromString(NSString* string)
}
}
/* Tests for equality of floats/doubles.
* WARNING assumes the values are in the standard IEEE format ...
* this may not be true on all systems, though afaik it is the case
* on all systems we target.
*
* We use integer arithmetic for speed, assigning the float/double
* to an integer of the same size and then converting any negative
* values to twos-complement integer values so that a simple integer
* comparison can be done.
*
* MAX_ULP specified the number of Units in the Last Place by which
* the two values may differ and still be considered equal. A value
* of zero means that the two numbers must be identical.
*
* The way that infinity is represented means that it will be considered
* equal to MAX_FLT (or MAX_DBL) unless we are doing an exact comparison
* with MAX_ULP set to zero.
*
* The implementation will also treat two NaN values as being equal, which
* is technically wrong ... but is it worth adding a check for that?
*/
#define MAX_ULP 0
static inline BOOL
almostEqual(CGFloat A, CGFloat B)
{
#if MAX_ULP == 0
return (A == B) ? YES : NO;
#else /* MAX_UPL == 0 */
#if defined(CGFLOAT_IS_DBL)
union {int64_t i; double d;} valA, valB;
valA.d = A;
valB.d = B;
#if GS_SIZEOF_LONG == 8
if (valA.i < 0)
{
valA.i = 0x8000000000000000L - valA.i;
}
if (valB.i < 0)
{
valB.i = 0x8000000000000000L - valB.i;
}
if (labs(valA.i - valB.i) <= MAX_ULP)
{
return YES;
}
#else /* GS_SIZEOF_LONG == 8 */
if (valA.i < 0)
{
valA.i = 0x8000000000000000LL - valA.i;
}
if (valB.i < 0)
{
valB.i = 0x8000000000000000LL - valB.i;
}
if (llabs(valA.i - valB.i) <= MAX_ULP)
{
return YES;
}
#endif /* GS_SIZEOF_LONG == 8 */
return NO;
#else /* DEFINED(CGFLOAT_IS_DBL) */
union {int32_t i; float f;} valA, valB;
valA.f = A;
if (valA.i < 0)
{
valA.i = 0x80000000 - valA.i;
}
valB.f = B;
if (valB.i < 0)
{
valB.i = 0x80000000 - valB.i;
}
if (abs(valA.i - valB.i) <= MAX_ULP)
{
return YES;
}
return NO;
#endif /* DEFINED(CGFLOAT_IS_DBL) */
#endif /* MAX_UPL == 0 */
}
BOOL
NSEqualRects(NSRect aRect, NSRect bRect)
{
return (almostEqual(NSMinX(aRect), NSMinX(bRect))
&& almostEqual(NSMinY(aRect), NSMinY(bRect))
&& almostEqual(NSWidth(aRect), NSWidth(bRect))
&& almostEqual(NSHeight(aRect), NSHeight(bRect))) ? YES : NO;
}
BOOL
NSEqualSizes(NSSize aSize, NSSize bSize)
{
return (almostEqual(aSize.width, bSize.width)
&& almostEqual(aSize.height, bSize.height)) ? YES : NO;
}
BOOL
NSEqualPoints(NSPoint aPoint, NSPoint bPoint)
{
return (almostEqual(aPoint.x, bPoint.x)
&& almostEqual(aPoint.y, bPoint.y)) ? YES : NO;
}