Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit f58c8b7

Browse files
committed
com.livecode.math: Check function domain errors portably.
Only glibc sets EDOM for mathematical function domain errors. All platforms return NaN, however. Check for domain errors by checking for NaN result when none of the function's inputs were NaN.
1 parent d017ddf commit f58c8b7

1 file changed

Lines changed: 39 additions & 25 deletions

File tree

libscript/src/module-math.cpp

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <foundation-system.h>
2020

2121
#include <float.h>
22+
#include <fenv.h>
2223
#include <errno.h>
2324

2425
// Older versions of MSVC don't supply "trunc"
@@ -32,15 +33,32 @@ MCTypeInfoRef kMCMathDomainErrorTypeInfo;
3233

3334
////////////////////////////////////////////////////////////////
3435

36+
static inline bool
37+
__MCMathPropagateNanUnary (double p_in, double p_out)
38+
{
39+
if (isnan (p_out) && !isnan (p_in))
40+
return false;
41+
return true;
42+
}
43+
44+
static inline bool
45+
__MCMathPropagateNanBinary (double p_left, double p_right, double p_out)
46+
{
47+
if (isnan (p_out) && (!(isnan (p_left) || isnan (p_right))))
48+
return false;
49+
return true;
50+
}
51+
52+
////////////////////////////////////////////////////////////////
53+
3554
extern "C" MC_DLLEXPORT void MCMathEvalRealToPowerOfReal(double p_left, double p_right, double& r_output)
3655
{
37-
errno = 0;
3856
r_output = pow(p_left, p_right);
3957

40-
if (errno == EDOM)
41-
{
42-
MCErrorCreateAndThrow (kMCMathDomainErrorTypeInfo, nil);
43-
}
58+
if (__MCMathPropagateNanBinary (p_left, p_right, r_output))
59+
return;
60+
61+
MCErrorCreateAndThrow (kMCMathDomainErrorTypeInfo, nil);
4462
}
4563

4664
extern "C" MC_DLLEXPORT void MCMathEvalNumberToPowerOfNumber(MCNumberRef p_left, MCNumberRef p_right, MCNumberRef& r_output)
@@ -58,13 +76,12 @@ extern "C" MC_DLLEXPORT void MCMathEvalNumberToPowerOfNumber(MCNumberRef p_left,
5876

5977
extern "C" MC_DLLEXPORT void MCMathEvalBase10LogReal(double p_operand, double& r_output)
6078
{
61-
errno = 0;
6279
r_output = log10(p_operand);
6380

64-
if (errno == EDOM)
65-
{
66-
MCErrorCreateAndThrow (kMCMathDomainErrorTypeInfo, nil);
67-
}
81+
if (__MCMathPropagateNanUnary (p_operand, r_output))
82+
return;
83+
84+
MCErrorCreateAndThrow (kMCMathDomainErrorTypeInfo, nil);
6885
}
6986

7087
extern "C" MC_DLLEXPORT void MCMathEvalBase10LogNumber(MCNumberRef p_operand, MCNumberRef& r_output)
@@ -81,13 +98,12 @@ extern "C" MC_DLLEXPORT void MCMathEvalBase10LogNumber(MCNumberRef p_operand, MC
8198

8299
extern "C" MC_DLLEXPORT void MCMathEvalNaturalLogReal(double p_operand, double& r_output)
83100
{
84-
errno = 0;
85101
r_output = log(p_operand);
86102

87-
if (errno == EDOM)
88-
{
89-
MCErrorCreateAndThrow (kMCMathDomainErrorTypeInfo, nil);
90-
}
103+
if (__MCMathPropagateNanUnary (p_operand, r_output))
104+
return;
105+
106+
MCErrorCreateAndThrow (kMCMathDomainErrorTypeInfo, nil);
91107
}
92108

93109
extern "C" MC_DLLEXPORT void MCMathEvalNaturalLogNumber(MCNumberRef p_operand, MCNumberRef& r_output)
@@ -172,13 +188,12 @@ extern "C" MC_DLLEXPORT void MCMathEvalTanNumber(MCNumberRef p_operand, MCNumber
172188

173189
extern "C" MC_DLLEXPORT void MCMathEvalAsinReal(double p_operand, double& r_output)
174190
{
175-
errno = 0;
176191
r_output = asin(p_operand);
177192

178-
if (errno == EDOM)
179-
{
180-
MCErrorCreateAndThrow (kMCMathDomainErrorTypeInfo, nil);
181-
}
193+
if (__MCMathPropagateNanUnary (p_operand, r_output))
194+
return;
195+
196+
MCErrorCreateAndThrow (kMCMathDomainErrorTypeInfo, nil);
182197
}
183198

184199
extern "C" MC_DLLEXPORT void MCMathEvalAsinNumber(MCNumberRef p_operand, MCNumberRef& r_output)
@@ -195,13 +210,12 @@ extern "C" MC_DLLEXPORT void MCMathEvalAsinNumber(MCNumberRef p_operand, MCNumbe
195210

196211
extern "C" MC_DLLEXPORT void MCMathEvalAcosReal(double p_operand, double& r_output)
197212
{
198-
errno = 0;
199213
r_output = acos(p_operand);
200214

201-
if (errno == EDOM)
202-
{
203-
MCErrorCreateAndThrow (kMCMathDomainErrorTypeInfo, nil);
204-
}
215+
if (__MCMathPropagateNanUnary (p_operand, r_output))
216+
return;
217+
218+
MCErrorCreateAndThrow (kMCMathDomainErrorTypeInfo, nil);
205219
}
206220

207221
extern "C" MC_DLLEXPORT void MCMathEvalAcosNumber(MCNumberRef p_operand, MCNumberRef& r_output)

0 commit comments

Comments
 (0)