14 changed files with 203 additions and 245 deletions
-
6ChangeLog
-
8configure.in
-
4src/Makefile.am
-
1src/include/ngspice.h
-
2src/maths/Makefile.am
-
4src/maths/misc/Makefile.am
-
4src/maths/misc/accuracy.c
-
62src/maths/misc/equality.c
-
53src/maths/misc/isnan.c
-
36src/maths/misc/logb.c
-
34src/maths/misc/scalb.c
-
2src/misc/Makefile.am
-
203src/misc/missing_math.c
-
29src/misc/missing_math.h
@ -1,6 +1,6 @@ |
|||||
## Process this file with automake
|
## Process this file with automake
|
||||
|
|
||||
SUBDIRS = cmaths ni sparse poly deriv @CIDERMATH@ |
|
||||
|
SUBDIRS = cmaths ni sparse poly deriv misc |
||||
DIST_SUBDIRS = cmaths ni sparse poly deriv misc |
DIST_SUBDIRS = cmaths ni sparse poly deriv misc |
||||
|
|
||||
MAINTAINERCLEANFILES = Makefile.in |
MAINTAINERCLEANFILES = Makefile.in |
||||
@ -0,0 +1,62 @@ |
|||||
|
/********** |
||||
|
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; |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
/********** |
||||
|
Copyright 1991 Regents of the University of California. All rights reserved. |
||||
|
**********/ |
||||
|
|
||||
|
#include "ngspice.h" |
||||
|
|
||||
|
#ifndef HAVE_ISNAN |
||||
|
|
||||
|
/* isnan (originally) for SOI devices in MINGW32 hvogt (dev.c) */ |
||||
|
union ieee754_double |
||||
|
{ |
||||
|
double d; |
||||
|
|
||||
|
/* This is the IEEE 754 double-precision format. */ |
||||
|
struct |
||||
|
{ |
||||
|
/* Together these comprise the mantissa. */ |
||||
|
unsigned int mantissa1:32; |
||||
|
unsigned int mantissa0:20; |
||||
|
unsigned int exponent:11; |
||||
|
unsigned int negative:1; |
||||
|
} ieee; |
||||
|
struct |
||||
|
{ |
||||
|
/* Together these comprise the mantissa. */ |
||||
|
unsigned int mantissa1:32; |
||||
|
unsigned int mantissa0:19; |
||||
|
unsigned int quiet_nan:1; |
||||
|
unsigned int exponent:11; |
||||
|
unsigned int negative:1; |
||||
|
} ieee_nan; |
||||
|
}; |
||||
|
|
||||
|
int |
||||
|
isnan(double value) |
||||
|
{ |
||||
|
union ieee754_double u; |
||||
|
|
||||
|
u.d = value; |
||||
|
|
||||
|
/* IEEE 754 NaN's have the maximum possible |
||||
|
exponent and a nonzero mantissa. */ |
||||
|
return ((u.ieee.exponent & 0x7ff) == 0x7ff && |
||||
|
(u.ieee.mantissa0 != 0 || u.ieee.mantissa1 != 0)); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* end isnan.c |
||||
|
*/ |
||||
|
#else /* HAVE_ISNAN */ |
||||
|
int Dummy_Symbol_4; |
||||
|
#endif /* HAVE_ISNAN */ |
||||
@ -0,0 +1,36 @@ |
|||||
|
/********** |
||||
|
Copyright 1991 Regents of the University of California. All rights reserved. |
||||
|
**********/ |
||||
|
|
||||
|
#include "ngspice.h" |
||||
|
|
||||
|
#ifndef HAVE_LOGB |
||||
|
|
||||
|
double |
||||
|
logb(double x) |
||||
|
{ |
||||
|
double y = 0.0; |
||||
|
|
||||
|
if (x != 0.0) |
||||
|
{ |
||||
|
if (x < 0.0) |
||||
|
x = - x; |
||||
|
while (x > 2.0) |
||||
|
{ |
||||
|
y += 1.0; |
||||
|
x /= 2.0; |
||||
|
} |
||||
|
while (x < 1.0) |
||||
|
{ |
||||
|
y -= 1.0; |
||||
|
x *= 2.0; |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
y = 0.0; |
||||
|
|
||||
|
return y; |
||||
|
} |
||||
|
#else |
||||
|
int Dummy_Symbol_3; |
||||
|
#endif |
||||
@ -0,0 +1,34 @@ |
|||||
|
/********** |
||||
|
Copyright 1991 Regents of the University of California. All rights reserved. |
||||
|
**********/ |
||||
|
|
||||
|
#include "ngspice.h" |
||||
|
|
||||
|
#ifndef HAVE_SCALB |
||||
|
# ifdef HAVE_SCALBN |
||||
|
# define scalb scalbn |
||||
|
#else /* Chris Inbody */ |
||||
|
|
||||
|
double |
||||
|
scalb(double x, int n) |
||||
|
{ |
||||
|
double y, z = 1.0, k = 2.0; |
||||
|
|
||||
|
if (n < 0) { |
||||
|
n = -n; |
||||
|
k = 0.5; |
||||
|
} |
||||
|
|
||||
|
if (x != 0.0) |
||||
|
for (y = 1.0; n; n >>= 1) { |
||||
|
y *= k; |
||||
|
if (n & 1) |
||||
|
z *= y; |
||||
|
} |
||||
|
|
||||
|
return x * z; |
||||
|
} |
||||
|
# endif /* HAVE_SCALBN */ |
||||
|
#else /* HAVE_SCALB */ |
||||
|
int Dummy_Symbol_1; |
||||
|
#endif /* HAVE_SCALB */ |
||||
@ -1,203 +0,0 @@ |
|||||
/********** |
|
||||
Copyright 1991 Regents of the University of California. All rights reserved. |
|
||||
$Id$ |
|
||||
**********/ |
|
||||
|
|
||||
/* |
|
||||
* Missing math functions |
|
||||
*/ |
|
||||
#include <assert.h> |
|
||||
#include "config.h" |
|
||||
#include "ngspice.h" |
|
||||
#include "missing_math.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; |
|
||||
} |
|
||||
|
|
||||
#ifndef HAVE_LOGB |
|
||||
|
|
||||
double |
|
||||
logb(double x) |
|
||||
{ |
|
||||
double y = 0.0; |
|
||||
|
|
||||
if (x != 0.0) |
|
||||
{ |
|
||||
if (x < 0.0) |
|
||||
x = - x; |
|
||||
while (x > 2.0) |
|
||||
{ |
|
||||
y += 1.0; |
|
||||
x /= 2.0; |
|
||||
} |
|
||||
while (x < 1.0) |
|
||||
{ |
|
||||
y -= 1.0; |
|
||||
x *= 2.0; |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
y = 0.0; |
|
||||
|
|
||||
return y; |
|
||||
} |
|
||||
#endif |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
#ifndef HAVE_SCALB |
|
||||
# ifdef HAVE_SCALBN |
|
||||
# define scalb scalbn |
|
||||
#else /* Chris Inbody */ |
|
||||
|
|
||||
double |
|
||||
scalb(double x, int n) |
|
||||
{ |
|
||||
double y, z = 1.0, k = 2.0; |
|
||||
|
|
||||
if (n < 0) { |
|
||||
n = -n; |
|
||||
k = 0.5; |
|
||||
} |
|
||||
|
|
||||
if (x != 0.0) |
|
||||
for (y = 1.0; n; n >>= 1) { |
|
||||
y *= k; |
|
||||
if (n & 1) |
|
||||
z *= y; |
|
||||
} |
|
||||
|
|
||||
return x * z; |
|
||||
} |
|
||||
# endif /* HAVE_SCALBN */ |
|
||||
#endif /* HAVE_SCALB */ |
|
||||
|
|
||||
|
|
||||
#ifndef HAVE_ERFC |
|
||||
/* From C. Hastings, Jr., Approximations for digital computers, |
|
||||
Princeton Univ. Press, 1955. |
|
||||
Approximation accurate to within 1.5E-7 |
|
||||
(making some assumptions about your machine's floating point mechanism) |
|
||||
*/ |
|
||||
|
|
||||
double |
|
||||
erfc(double x) |
|
||||
|
|
||||
{ |
|
||||
double t, z; |
|
||||
|
|
||||
t = 1/(1 + 0.3275911*x); |
|
||||
z = 1.061405429; |
|
||||
z = -1.453152027 + t * z; |
|
||||
z = 1.421413741 + t * z; |
|
||||
z = -0.284496736 + t * z; |
|
||||
z = 0.254829592 + t * z; |
|
||||
z = exp(-x*x) * t * z; |
|
||||
|
|
||||
return(z); |
|
||||
} |
|
||||
#endif |
|
||||
|
|
||||
|
|
||||
|
|
||||
#ifndef HAVE_ISNAN |
|
||||
/* isnan (originally) for SOI devices in MINGW32 hvogt (dev.c) */ |
|
||||
|
|
||||
union ieee754_double |
|
||||
{ |
|
||||
double d; |
|
||||
|
|
||||
/* This is the IEEE 754 double-precision format. */ |
|
||||
struct |
|
||||
{ |
|
||||
/* Together these comprise the mantissa. */ |
|
||||
unsigned int mantissa1:32; |
|
||||
unsigned int mantissa0:20; |
|
||||
unsigned int exponent:11; |
|
||||
unsigned int negative:1; |
|
||||
} ieee; |
|
||||
struct |
|
||||
{ |
|
||||
/* Together these comprise the mantissa. */ |
|
||||
unsigned int mantissa1:32; |
|
||||
unsigned int mantissa0:19; |
|
||||
unsigned int quiet_nan:1; |
|
||||
unsigned int exponent:11; |
|
||||
unsigned int negative:1; |
|
||||
} ieee_nan; |
|
||||
}; |
|
||||
|
|
||||
int |
|
||||
isnan(double value) |
|
||||
|
|
||||
{ |
|
||||
union ieee754_double u; |
|
||||
|
|
||||
u.d = value; |
|
||||
|
|
||||
/* IEEE 754 NaN's have the maximum possible |
|
||||
exponent and a nonzero mantissa. */ |
|
||||
return ((u.ieee.exponent & 0x7ff) == 0x7ff && |
|
||||
(u.ieee.mantissa0 != 0 || u.ieee.mantissa1 != 0)); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
/* |
|
||||
* end isnan.c |
|
||||
*/ |
|
||||
#endif /* HAVE_ISNAN */ |
|
||||
|
|
||||
@ -1,29 +0,0 @@ |
|||||
/************* |
|
||||
* Header file for missing_math.c |
|
||||
* 1999 E. Rouat |
|
||||
************/ |
|
||||
|
|
||||
#ifndef MISSING_MATH_H_INCLUDED |
|
||||
#define MISSING_MATH_H_INCLUDED |
|
||||
|
|
||||
bool AlmostEqualUlps(double, double, int); |
|
||||
|
|
||||
#ifndef HAVE_ERFC |
|
||||
double erfc(double); |
|
||||
#endif |
|
||||
|
|
||||
#ifndef HAVE_LOGB |
|
||||
double logb(double); |
|
||||
#endif |
|
||||
|
|
||||
#ifndef HAVE_SCALB |
|
||||
# ifndef HAVE_SCALBN |
|
||||
double scalb(double, int); |
|
||||
# endif |
|
||||
#endif |
|
||||
|
|
||||
#ifndef HAVE_ISNAN |
|
||||
int isnan(double); |
|
||||
#endif |
|
||||
|
|
||||
#endif /* MISSING_MATH_H_INCLUDED */ |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue