Using math functions like asin, sqrt, pow, ... without getting range errors

I am writing a DLL and I am using some math functions like asin, sqrt, pow, ...

The problem is the arguments for the functions are set by users so sometimes it can cause errors. For example asin(1.5) will cause an error because the number should be in [-1,1]. Other functions like pow(1,500) cause errors too because the result is too small or too big. Most of the time the DLL function that is using this code will crash and return nothing.

This website said:
Floating point value in the interval [-1,+1].
If the argument is out of this interval, a domain error occurs, setting the global variable errno to the value EDOM.

So I tried solving this problem with this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
include "dll.h"
#include <math.h>
#include <errno.h>

short testfunction(double* result) {
double res,arg1;
errno = 0;
arg1 = 1.5;
result = asin(arg1);
if(errno==EDOM) { return 0; }
*result = res;
return 1;
}

export double mydllfunction() {
double result;
if(testfunction(&result)) {
return result;
} else {
return 0;
}
}


This doesn't seem to work, so I tried this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
include "dll.h"
#include <math.h>
#include <exception>
#include <stdexcept>

short testfunction(double* result) {
double res,arg1;
errno = 0;
arg1 = 1.5;
try {
result = asin(arg1);
}
catch(std::domain_error&) {
return 0;
}
catch(...) {
return 0;
}
*result = res;
return 1;
}

export double mydllfunction() {
double result;
if(testfunction(&result)) {
return result;
} else {
return 0;
}
}

But this doesn't work either. It just freezes my program (because it doesn't return anything, I think).

I am having the same problem with codes like:
 
a = 1e200*1e200;


How should I check if these function will fail?
I have no idea what you're talking about.
1
2
3
4
5
6
7
#include <cstdio>
#include <cmath>

int main(){
	printf("%f\n",asin(1.5));
	return 0;
}

-1.#IND00
If your program is crashing is for a different reason. Computers no longer freeze when trying to divide by zero.
Why don't you check the value to be in the range before passing it to the functions?

or use try{/*...*/}catch(...){/*...*/}
Last edited on

I have no idea what you're talking about.
1
2
3
4
5
6
7
 #include <cstdio>
#include <cmath>

int main(){
	printf("%f\n",asin(1.5));
	return 0;
} 

-1.#IND00
If your program is crashing is for a different reason. Computers no longer freeze when trying to divide by zero.

That's what I thought too, but this doesn't seem to be true for me. Maybe it's the compiler I'm using (dev-c++) or because it is a DLL. In my DLL the function just crashes and returns nothing at all (as far as I can check). When I test this in a normal (MSDOS) application I get no errors, but in a DLL it crashes.


Why don't you check the value to be in the range before passing it to the functions?

or use try{/*...*/}catch(...){/*...*/}

- I could do this for functions like sin() but trying to do this to prevent overflow errors with pow(x,n) is not possible (I think).
- I tried using this but it made no difference. The function still crashed. Also, using the exeptions system adds 30kb to my dll, even if I use it only once. If I use it 10 times it adds about 50kb, so if I used this everywhere my dll would become really big.
I'm using GCC, as well, so no, it's not the compiler. Maybe your function depends on the math function returning a valid value. By the way,
printf("%f\n",pow(2,500)); 32733906078961419000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000.000000

(Obviously the result of limited precition arithmetic.)
I have done some more testing. In a normal application, the program never crashes, but in my DLL:

- 1e200*1e200 (1.#INF) -> works
- pow(10.0,999.0) (range error) -> my program freezes
- pow(10.0,999.0) (domain error) -> my program freezes
- 2.0/0.0 (1.#INF, divide by zero error) -> my program freezes

It looks like the program that calls the dll function detects if an error has occurred, and if an error has occurred it just freezes. Is there any way to avoid this?
Is the DLL a plugin or are you writing the program, too?
In the former case, can you pass an error code to the program?
In the latter case, it seems you should check that the return value is valid before proceeding.
I am writing a DLL to use in Game Maker (http://www.yoyogames.com/gamemaker), so in fact it is a plugin.

In those cases were the functionality of GML is not enough for your wishes, you can actually extend the possibilities by using plug-ins. A plug-in comes in the form of a DLL file (a Dynamic Link Library). In such a DLL file you can define functions. Such functions can be programmed in any programming language that supports the creation of DLL's (e.g. Delphi, C, C++, etc.) You will though need to have some programming skill to do this. Plug-in functions must have a specific format. They can have between 0 and 16 arguments, each of which can either be a real number (double in C) or a null-terminated string. (For more than 4 arguments, only real arguments are supported at the moment.) They must return either a real or a null-terminated string.


I can only change the calling convention (stdcall or cdecl) and the return value type (double or char*). I have to solve the problem by changing the DLL, I can't edit the import code. I tried both stdcall and cdecl, but it didn't make any difference.
What is the interface (i.e. the signature of your function) like?
Your best bet is to check what parameters are being passed into your function, and if the parameter is invalid return a specified value, or throw an exception etc.

Just be aware, even though your complaining about the DLL size (which is really irrelevant). Exception handling increases the execution time of your code quite dramatically.
Topic archived. No new replies allowed.