Error checking for atan2()?

M

matt

Hi group,

I read the description of function atan2() as given by opengroup at:
http://www.opengroup.org/onlinepubs/009695399/functions/atan2.html

In particular, I found the following sentences:

1) "An application wishing to check for error situations should set
errno to zero and call feclearexcept(FE_ALL_EXCEPT) before calling these
functions. On return, if errno is non-zero or fetestexcept(FE_INVALID |
FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) is non-zero, an error has
occurred."

2) "These functions may fail if: The result underflows."

I tried to check for underflow errors by using this code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <fenv.h>
int
main(void)
{
double x = 10e-324,
y = 10e-324;
errno = 0;
feclearexcept(FE_ALL_EXCEPT);
printf("x = %f\n", x);
printf("y = %f\n", y);
printf("atan2(x,y) = %f\n", atan2(x,y));
if ((errno != 0) ||
(fetestexcept(FE_INVALID |
FE_DIVBYZERO |
FE_OVERFLOW |
FE_UNDERFLOW) != 0)) {
perror("mah");
exit(-1);
}
return(1);
}

but without any success:
$ gcc -Wall -O0 main.c -o exe -lm
$ ./exe
x = 0.000000
y = 0.000000
atan2(x,y) = 0.785398
$

Can you throw some light on this, and/or provide me with an working example?

Thank you in advance,
 
E

Eric Sosman

matt said:
Hi group,

I read the description of function atan2() as given by opengroup at:
http://www.opengroup.org/onlinepubs/009695399/functions/atan2.html

In particular, I found the following sentences:

1) "An application wishing to check for error situations should set
errno to zero and call feclearexcept(FE_ALL_EXCEPT) before calling these
functions. On return, if errno is non-zero or fetestexcept(FE_INVALID |
FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) is non-zero, an error has
occurred."

2) "These functions may fail if: The result underflows."

I tried to check for underflow errors by using this code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <fenv.h>
int
main(void)
{
double x = 10e-324,
y = 10e-324;
errno = 0;
feclearexcept(FE_ALL_EXCEPT);
printf("x = %f\n", x);
printf("y = %f\n", y);
printf("atan2(x,y) = %f\n", atan2(x,y));

It doesn't much matter what value atan2() might have
stored in errno, since printf() may then store its own value.
See Question 12.24 in the comp.lang.c Frequently Asked
Questions (FAQ) list at <http://www.c-faq.com/>.

By the way, it is unusual to name the arguments of atan2()
as you have done here: The first argument is the "vertical"
component and the second the "horizontal," ordinarily referred
to as Y and X respectively. In this case it doesn't matter
because the two variables have equal values, but it's a point
you might want to bear in mind for future atan2() uses.
if ((errno != 0) ||
(fetestexcept(FE_INVALID |
FE_DIVBYZERO |
FE_OVERFLOW |
FE_UNDERFLOW) != 0)) {
perror("mah");
exit(-1);
}
return(1);
}

but without any success:
$ gcc -Wall -O0 main.c -o exe -lm
$ ./exe
x = 0.000000
y = 0.000000
atan2(x,y) = 0.785398
$

Can you throw some light on this, and/or provide me with an working
example?

You gave atan2() a pair of non-zero equal arguments, and
it returned forty-five degrees, the correct answer. What's
to complain about?

If you're trying to force an underflow "just to see what
happens," I'd suggest using Y and X of dissimilar magnitudes.
No guarantees, of course: The Standard does not specify any
particular computational machinery for the innards of atan2().
 
B

Ben Bacarisse

matt said:
Hi group,

I read the description of function atan2() as given by opengroup at:
http://www.opengroup.org/onlinepubs/009695399/functions/atan2.html

In particular, I found the following sentences:

1) "An application wishing to check for error situations should set
errno to zero and call feclearexcept(FE_ALL_EXCEPT) before calling
these functions. On return, if errno is non-zero or
fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW)
is non-zero, an error has occurred."

2) "These functions may fail if: The result underflows."

I tried to check for underflow errors by using this code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <fenv.h>
int
main(void)
{
double x = 10e-324,
y = 10e-324;
errno = 0;
feclearexcept(FE_ALL_EXCEPT);
printf("x = %f\n", x);
printf("y = %f\n", y);
printf("atan2(x,y) = %f\n", atan2(x,y));
if ((errno != 0) ||
(fetestexcept(FE_INVALID |
FE_DIVBYZERO |
FE_OVERFLOW |
FE_UNDERFLOW) != 0)) {
perror("mah");
exit(-1);
}
return(1);
}

but without any success:
$ gcc -Wall -O0 main.c -o exe -lm
$ ./exe
x = 0.000000
y = 0.000000
atan2(x,y) = 0.785398
$

Can you throw some light on this, and/or provide me with an working
example?

You need to be more specific. A working example of what? atan2(x,x)
= pi/4 (for x>0) so there is no obvious error. Even if x was actually
set to zero the definition of atan2 only says that a domain error may
occur (not must).
 
G

Gustavo Rondina

Hi group,

I read the description of function atan2() as given by opengroup at:http://www.opengroup.org/onlinepubs/009695399/functions/atan2.html

In particular, I found the following sentences:

   1) "An application wishing to check for error situations should set
errno to zero and call feclearexcept(FE_ALL_EXCEPT) before calling these
functions. On return, if errno is non-zero or fetestexcept(FE_INVALID |
FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) is non-zero, an error has
occurred."

   2) "These functions may fail if: The result underflows."

I tried to check for underflow errors by using this code:
   #include <stdio.h>
   #include <stdlib.h>
   #include <errno.h>
   #include <math.h>
   #include <fenv.h>
   int
   main(void)
   {
       double x = 10e-324,
              y = 10e-324;
       errno = 0;
       feclearexcept(FE_ALL_EXCEPT);
       printf("x = %f\n", x);
       printf("y = %f\n", y);
       printf("atan2(x,y) = %f\n", atan2(x,y));
       if ((errno != 0) ||
           (fetestexcept(FE_INVALID |
                         FE_DIVBYZERO |
                         FE_OVERFLOW |
                         FE_UNDERFLOW) != 0)) {
           perror("mah");
           exit(-1);
       }
       return(1);
   }

You should set errno to 0 right before calling atan2 and checking for
the error right after calling it, with no other calls in between.
but without any success:
   $ gcc -Wall -O0 main.c -o exe -lm
   $ ./exe
   x = 0.000000
   y = 0.000000
   atan2(x,y) = 0.785398
   $

Can you throw some light on this, and/or provide me with an working example?

I think you should check for the documentation of your specific
implementation of atan2. The man page for my implementation (glibc
2.9) says that no error occur for atan2, but it also says the
following:

If y is positive infinity (negative infinity) and x is
positive infin-
ity, +pi/4 (-pi/4) is returned.

Which is the value being returned (pi/4 = 0.785398).
 
M

matt

matt wrote:
If you're trying to force an underflow "just to see what
happens," I'd suggest using Y and X of dissimilar magnitudes.
No guarantees, of course: The Standard does not specify any
particular computational machinery for the innards of atan2().

Ok, but I read that:
"On error, the expressions (math_errhandling & MATH_ERRNO) and
(math_errhandling & MATH_ERREXCEPT) are independent of each other, but
at least one of them *must* be non-zero."

So atan2() *must* understand when an underflow occurs and an error
condition raises.

I tried by using x,y with different magnitudes, without success.

Roughly, can you provide me with a code example where an error due to
underflow occur?

Thank you
 
M

matt

You need to be more specific. A working example of what?

Basically, I just want to force an error condition due to underflow,
"just to see what happens", as Eric said.

I'd like to understand how such an error condition should be handled,
but I wasn't be able to force it to occur. I used very small numbers,
but without success. Can you provide an example where an error condition
due to underflow makes atan2() to fail?

Thank you.
 
U

user923005

So atan2() is implementation dependent? I didn't see such a statement at
opengroup description:http://www.opengroup.org/onlinepubs/009695399/functions/atan2.html

From §7.12.2 Library p 215:
5 The result underflows if the magnitude of the mathematical result is
so small that the mathematical result cannot be represented, without
extraordinary roundoff error, in an object of the specified type.204)
If the result underflows, the function returns an implementation-
defined value whose magnitude is no greater than the smallest
normalized positive number in the specified type; if the integer
expression math_errhandling & MATH_ERRNO is nonzero, whether errno
acquires the value ERANGE is implementation-defined; if the integer
expression math_errhandling & MATH_ERREXCEPT is nonzero, whether the
‘‘underflow’’ floating-point exception is raised is implementation-
defined.

Footnote 204) The term underflow here is intended to encompass both
‘‘gradual underflow’’ as in IEC 60559 and also ‘‘flush-to-zero’’
underflow.
 
M

matt

> If the result underflows, the function returns an implementation-
> defined value whose magnitude is no greater than the smallest
> if the integer expression math_errhandling & MATH_ERRNO is nonzero,
> whether errno acquires the value ERANGE is implementation-defined;
> if the integer expression math_errhandling & MATH_ERREXCEPT is
> nonzero, whether the ‘‘underflow’’ floating-point exception is raised
> is implementation-defined.

So, if the result underflows, either the integer expression
(math_errhandling & MATH_ERRNO) or (math_errhandling & MATH_ERREXCEPT)
*must* be nonzero.

I modified my example code in order to try to perform a check on the
integer expression above:
if ((math_errhandling & MATH_ERREXCEPT)||
(math_errhandling & MATH_ERRNO))
perror("myprogram");

but I've not been able even to compile it:
$ gcc -Wall -O0 main.c -o exe -lm
main.c: In function 'main':
main.c:17: error: 'math_errhandling' undeclared (first use in this function)
main.c:17: error: (Each undeclared identifier is reported only once
main.c:17: error: for each function it appears in.)
main.c:17: error: 'MATH_ERREXCEPT' undeclared (first use in this function)
main.c:18: error: 'MATH_ERRNO' undeclared (first use in this function)

In math.h, I found a definition both for macro MATH_ERRNO and
MATH_ERREXCEPT but I couldn't find a definition for the macro
math_errhandling...

Any suggestion?

Thank you
 
U

user923005

On 08/03/2009 09:35 PM, user923005 wrote:
 > If the result underflows, the function returns an implementation-
 > defined value whose magnitude is no greater than the smallest
 > if the integer expression math_errhandling & MATH_ERRNO is nonzero,
 > whether errno acquires the value ERANGE is implementation-defined;
 > if the integer expression math_errhandling & MATH_ERREXCEPT is
 > nonzero, whether the ‘‘underflow’’ floating-point exception is raised
 > is implementation-defined.

So, if the result underflows, either the integer expression
(math_errhandling & MATH_ERRNO) or (math_errhandling & MATH_ERREXCEPT)
*must* be nonzero.

I modified my example code in order to try to perform a check on the
integer expression above:
   if ((math_errhandling & MATH_ERREXCEPT)||
               (math_errhandling & MATH_ERRNO))
           perror("myprogram");

but I've not been able even to compile it:
$ gcc -Wall -O0 main.c -o exe -lm
main.c: In function 'main':
main.c:17: error: 'math_errhandling' undeclared (first use in this function)
main.c:17: error: (Each undeclared identifier is reported only once
main.c:17: error: for each function it appears in.)
main.c:17: error: 'MATH_ERREXCEPT' undeclared (first use in this function)
main.c:18: error: 'MATH_ERRNO' undeclared (first use in this function)

In math.h, I found a definition both for macro MATH_ERRNO and
MATH_ERREXCEPT but I couldn't find a definition for the macro
math_errhandling...

Any suggestion?

It's a C99 requirement. What compiler are you using?
 
K

Keith Thompson

matt said:
So, if the result underflows, either the integer expression
(math_errhandling & MATH_ERRNO) or (math_errhandling & MATH_ERREXCEPT)
*must* be nonzero.

I modified my example code in order to try to perform a check on the
integer expression above:
if ((math_errhandling & MATH_ERREXCEPT)||
(math_errhandling & MATH_ERRNO))
perror("myprogram");

but I've not been able even to compile it:
$ gcc -Wall -O0 main.c -o exe -lm
main.c: In function 'main':
main.c:17: error: 'math_errhandling' undeclared (first use in this function)
main.c:17: error: (Each undeclared identifier is reported only once
main.c:17: error: for each function it appears in.)
main.c:17: error: 'MATH_ERREXCEPT' undeclared (first use in this function)
main.c:18: error: 'MATH_ERRNO' undeclared (first use in this function)

In math.h, I found a definition both for macro MATH_ERRNO and
MATH_ERREXCEPT but I couldn't find a definition for the macro
math_errhandling...

math_errhandling is a C99-specific feature. Possibly your
implementation doesn't support it. Mine doesn't (gcc 4.3.3, glibc
2.9, Ubuntu 9.04).
 
J

jameskuyper

matt said:
So, if the result underflows, either the integer expression
(math_errhandling & MATH_ERRNO) or (math_errhandling & MATH_ERREXCEPT)
*must* be nonzero.

No, those are conditions that tell you whether or not it's
implementation-defined whether certain consequences of an underflow
will occur. If either expression is 0, the corresponding consequence
cannot happen at all. However, an underflow can occur regardless of
the value of math_errhandling.
I modified my example code in order to try to perform a check on the
integer expression above:
if ((math_errhandling & MATH_ERREXCEPT)||
(math_errhandling & MATH_ERRNO))
perror("myprogram");

but I've not been able even to compile it:
$ gcc -Wall -O0 main.c -o exe -lm
main.c: In function 'main':
main.c:17: error: 'math_errhandling' undeclared (first use in this function)
main.c:17: error: (Each undeclared identifier is reported only once
main.c:17: error: for each function it appears in.)
main.c:17: error: 'MATH_ERREXCEPT' undeclared (first use in this function)
main.c:18: error: 'MATH_ERRNO' undeclared (first use in this function)

In math.h, I found a definition both for macro MATH_ERRNO and
MATH_ERREXCEPT but I couldn't find a definition for the macro
math_errhandling...

These are new C99 features - you have to use "-std=c99" to get gcc to
recognise them. Also, you need to #include <math.h>.
 
E

Eric Sosman

matt said:
[...]
I modified my example code in order to try to perform a check on the
integer expression above:
if ((math_errhandling & MATH_ERREXCEPT)||
(math_errhandling & MATH_ERRNO))
perror("myprogram");

but I've not been able even to compile it:
$ gcc -Wall -O0 main.c -o exe -lm
main.c: In function 'main':
main.c:17: error: 'math_errhandling' undeclared (first use in this
function)
main.c:17: error: (Each undeclared identifier is reported only once
main.c:17: error: for each function it appears in.)
main.c:17: error: 'MATH_ERREXCEPT' undeclared (first use in this function)
main.c:18: error: 'MATH_ERRNO' undeclared (first use in this function)

In math.h, I found a definition both for macro MATH_ERRNO and
MATH_ERREXCEPT but I couldn't find a definition for the macro
math_errhandling...

Any suggestion?

math_errhandling was introduced in C99 (or at any rate
sometime after C89), so you might try "-std=c99" in the compile
flags. You might also want to check a gcc forum to see what it
says about C99 compliance; this might be one of those areas
gcc hasn't quite caught up to yet.
 
K

Keith Thompson

jameskuyper said:
matt wrote: [...]
In math.h, I found a definition both for macro MATH_ERRNO and
MATH_ERREXCEPT but I couldn't find a definition for the macro
math_errhandling...

These are new C99 features - you have to use "-std=c99" to get gcc to
recognise them. Also, you need to #include <math.h>.

<SOMEWHAT_OT>

And even that may not work, depending on the C runtime library.
Apparently math_errhandling requires support from both the compiler
and the library. glibc, the library typically used on Linux-based
systems, apparently doesn't have this support.

See the "Further notes" section of <http://gcc.gnu.org/c99status.html>
(which refer to some libc-hacker messages from 9 years ago).

Using gcc on Cygwin, math_errhandling is declared in <math.h>; Cygwin
doesn't use glibc.

</SOMEWHAT_OT>
 
A

Alan Curry

I tried to check for underflow errors by using this code: [...]
double x = 10e-324,
y = 10e-324;
errno = 0;
feclearexcept(FE_ALL_EXCEPT);
printf("x = %f\n", x);
printf("y = %f\n", y);
printf("atan2(x,y) = %f\n", atan2(x,y));
if ((errno != 0) ||
(fetestexcept(FE_INVALID |
FE_DIVBYZERO |
FE_OVERFLOW |
FE_UNDERFLOW) != 0)) {
perror("mah");
[...]

I got an underflow to occur by changing the numbers to
x = 1e-160, y = 1e+160

Your perror didn't say anything useful (just "Success" since errno was 0) but
it did get executed, proving that fetestexcept worked.
 
D

Dik T. Winter

> So atan2() *must* understand when an underflow occurs and an error
> condition raises.

When you give atan2 two equal arguments there is no underflow within atan2.
On some systems it can happen that atan2 is defined in terms of atan, in
that case an underflow can occur within atan2 (when y is much larger than
x), but if it is a function written on its own, it can be written such
that no underflow will occur at all.
 
D

Dik T. Winter

>
> When you give atan2 two equal arguments there is no underflow within atan2.
> On some systems it can happen that atan2 is defined in terms of atan, in
> that case an underflow can occur within atan2 (when y is much larger than
> x), but if it is a function written on its own, it can be written such
> that no underflow will occur at all.

Sorry, this was wrong. There will be an underflow if y/x does underflow.
(As the derivative in the neighbourhood of the origin of atan is 1, for
very small values atan(z) ~ z.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top