You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
62 lines
1.9 KiB
62 lines
1.9 KiB
/**********
|
|
Copyright 1991 Regents of the University of California. All rights reserved.
|
|
**********/
|
|
|
|
#include <assert.h>
|
|
#include "ngspice.h"
|
|
|
|
#ifdef _MSC_VER
|
|
typedef __int64 long64;
|
|
#else
|
|
typedef long long long64;
|
|
#endif
|
|
|
|
#define Abs(x) ((x) < 0 ? -(x) : (x))
|
|
|
|
/* From Bruce Dawson, Comparing floating point numbers,
|
|
http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm
|
|
Original this function is named AlmostEqual2sComplement but we leave it to AlmostEqualUlps
|
|
and can leave the code (measure.c, dctran.c) unchanged. The transformation to the 2's complement
|
|
prevent problems around 0.0.
|
|
One Ulp is equivalent to a maxRelativeError of between 1/4,000,000,000,000,000 and 1/8,000,000,000,000,000.
|
|
Practical: 3 < maxUlps < some hundred's (or thousand's) - depending on numerical requirements.
|
|
*/
|
|
bool AlmostEqualUlps(double A, double B, int maxUlps)
|
|
{
|
|
long64 aInt, bInt, intDiff;
|
|
|
|
if (A == B)
|
|
return TRUE;
|
|
|
|
/* If not - the entire method can not work */
|
|
assert(sizeof(double) == sizeof(long64));
|
|
|
|
/* Make sure maxUlps is non-negative and small enough that the */
|
|
/* default NAN won't compare as equal to anything. */
|
|
assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
|
|
aInt = *(long64*)&A;
|
|
/* Make aInt lexicographically ordered as a twos-complement int */
|
|
if (aInt < 0)
|
|
#ifdef _MSC_VER
|
|
aInt = 0x8000000000000000 - aInt;
|
|
#else
|
|
aInt = 0x8000000000000000LL - aInt;
|
|
#endif
|
|
bInt = *(long64*)&B;
|
|
/* Make bInt lexicographically ordered as a twos-complement int */
|
|
if (bInt < 0)
|
|
#ifdef _MSC_VER
|
|
bInt = 0x8000000000000000 - bInt;
|
|
#else
|
|
bInt = 0x8000000000000000LL - bInt;
|
|
#endif
|
|
#ifdef _MSC_VER
|
|
intDiff = Abs(aInt - bInt);
|
|
#else
|
|
intDiff = llabs(aInt - bInt);
|
|
#endif
|
|
/* printf("A:%e B:%e aInt:%d bInt:%d diff:%d\n", A, B, aInt, bInt, intDiff); */
|
|
if (intDiff <= maxUlps)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|