473,395 Members | 1,869 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

The floating point environment

Hi people

I continue to work in the tutorial for lcc-win32, and started to try to
explain the floating point flags.

Here is the relevant part of the tutorial. Since it is a difficult part,
I would like your expert advise before I publish any serious nonsense.

Any comments are welcome, style, organization, hard errors, etc.

Thanks in advance

jacob
-------------------------------------------------------------------
Using the floating point environment
------------------------------------

The C standard specifies a type fenv_t that “refers collectively to any
floating-point status flags and control modes supported by the
implementation.”

This environment has two special parts, the “floating point status
flags” that are set by the operations the program performs, and the
“control flags” that changes how the hardware does the operations, for
instance the rounding mode, etc.

The status flags
----------------
The standard requires at least the following flags:
FE_DIVBYZERO A division by zero has occurred
FE_INEXACT The last operation had to be rounded
FE_INVALID An invalid operation was attempted
FE_OVERFLOW The result of an operation was too big to be represented
FE_UNDERFLOW The result of an operation was too small to be represented

In addition to this standard flags, lcc-win32 provides:
FE_DENORMAL The result of the last operation was a denormal number
FE_STACKFAULT The floating point stack has overflowed.

The denormal flag means that a loss of precision is certain, the number
is too small to be represented. The stack fault flag means that
lcc-win32 generated bad code, since all floating point operations should
balance the floating point stack. If you ever test positive for this
flag, do not hesitate to send me a bug report!

In general, the floating point flags can be queried by the program to
know if the last operation did complete without problems. Here is a
small example to show you how this works:

/* This program tests a division by zero */
#include <fenv.h>
#include <stdio.h>
int main(void)
{
double a=1,b=0;
feclearexcept(FE_DIVBYZERO);
a=a/b;
if (fetestexcept(FE_DIVBYZERO)) {
printf("You have divided by zero!\n");
}
return 0;
}

First we clear the flag that we are going to use using feclearexcept.
Then, we perform our operation and query if the flag is set using
fetestexcept.

Since we know that the flags are set but not cleared, the expression
could be very well be a much more complicated sequence of operations.
The above code would work the same, but we would loose the possibility
of knowing exactly which operation failed. This is in many cases not
very important, we could very well be interested that somewhere there
was a serious error, without bothering to investigate which operation
was that it failed.

Reinitializing the floating point environment
---------------------------------------------

Things can become messy, and you would like to reset everything to a
known state. The standard provides the macro FE_DFL_ENV, that represents
the address of the default environment, the one you started with. In
lcc-win32 this environment is stored in the __default_fe_env global
variable, so this macro is just:

#define FE_DFL_ENV (&__default_fe_env)

You can reset everything to its default state with:

fesetenv(FE_DFL_ENV);

The default environment in lcc-win32 has the following characteristics:
1) The rounding mode is set to round to nearest.
2) The precision of the FPU is set to full precision (80 bits)
3) All exceptions are masked, i.e. the result of invalid operations is a
NAN, not a trap.

---------------------------------------------------------------------------
Jan 17 '06 #1
4 2807
In article <43***********************@news.wanadoo.fr>,
jacob navia <ja***@jacob.remcomp.fr> wrote:
Hi people

I continue to work in the tutorial for lcc-win32, and started to try to
explain the floating point flags.

Here is the relevant part of the tutorial. Since it is a difficult part,
I would like your expert advise before I publish any serious nonsense.

Any comments are welcome, style, organization, hard errors, etc.

Thanks in advance

jacob
-------------------------------------------------------------------
Using the floating point environment
------------------------------------

The C standard specifies a type fenv_t that ³refers collectively to any
floating-point status flags and control modes supported by the
implementation.²

This environment has two special parts, the ³floating point status
flags² that are set by the operations the program performs, and the
³control flags² that changes how the hardware does the operations, for
instance the rounding mode, etc.

The status flags
----------------
The standard requires at least the following flags:
FE_DIVBYZERO A division by zero has occurred
FE_INEXACT The last operation had to be rounded
Are you sure it is "the last operation", and not any operation? Does
this flag get cleared again after an operation that doesn't need
rounding?
FE_INVALID An invalid operation was attempted
FE_OVERFLOW The result of an operation was too big to be represented
FE_UNDERFLOW The result of an operation was too small to be represented

In addition to this standard flags, lcc-win32 provides:
FE_DENORMAL The result of the last operation was a denormal number
FE_STACKFAULT The floating point stack has overflowed.

The denormal flag means that a loss of precision is certain, the number
is too small to be represented.
Do you mean "too small to be represented with full precision"?
The stack fault flag means that
lcc-win32 generated bad code, since all floating point operations should
balance the floating point stack. If you ever test positive for this
flag, do not hesitate to send me a bug report!
I don't like this at all. I wouldn't want to write code that checks if
the compiler is broken. If there is any possibility at all that this
happens, could you make this throw a hardware exception, so that it
definitely will get detected?
In general, the floating point flags can be queried by the program to
know if the last operation did complete without problems. Here is a
small example to show you how this works:

/* This program tests a division by zero */
#include <fenv.h>
#include <stdio.h>
int main(void)
{
double a=1,b=0;
feclearexcept(FE_DIVBYZERO);
a=a/b;
if (fetestexcept(FE_DIVBYZERO)) {
printf("You have divided by zero!\n");
}
return 0;
}

First we clear the flag that we are going to use using feclearexcept.
Then, we perform our operation and query if the flag is set using
fetestexcept.

Since we know that the flags are set but not cleared, the expression
could be very well be a much more complicated sequence of operations.
The above code would work the same, but we would loose the possibility **** lose of knowing exactly which operation failed. This is in many cases not ******

I wouldn't say that the operaton failed. Most floating-point operations
will set the FE_INEXACT flag, that doesn't mean they failed.
very important, we could very well be interested that somewhere there
was a serious error, without bothering to investigate which operation
was that it failed.

Reinitializing the floating point environment
---------------------------------------------

Things can become messy, and you would like to reset everything to a
known state. The standard provides the macro FE_DFL_ENV, that represents
the address of the default environment, the one you started with. In
lcc-win32 this environment is stored in the __default_fe_env global
variable, so this macro is just:

#define FE_DFL_ENV (&__default_fe_env)

You can reset everything to its default state with:

fesetenv(FE_DFL_ENV);

The default environment in lcc-win32 has the following characteristics:
1) The rounding mode is set to round to nearest.
2) The precision of the FPU is set to full precision (80 bits)
3) All exceptions are masked, i.e. the result of invalid operations is a
NAN, not a trap.

---------------------------------------------------------------------------

Jan 18 '06 #2
Christian Bau a écrit :
In article <43***********************@news.wanadoo.fr>,
jacob navia <ja***@jacob.remcomp.fr> wrote:

Hi people

I continue to work in the tutorial for lcc-win32, and started to try to
explain the floating point flags.

Here is the relevant part of the tutorial. Since it is a difficult part,
I would like your expert advise before I publish any serious nonsense.

Any comments are welcome, style, organization, hard errors, etc.

Thanks in advance

jacob
-------------------------------------------------------------------
Using the floating point environment
------------------------------------

The C standard specifies a type fenv_t that ³refers collectively to any
floating-point status flags and control modes supported by the
implementation.²

This environment has two special parts, the ³floating point status
flags² that are set by the operations the program performs, and the
³control flags² that changes how the hardware does the operations, for
instance the rounding mode, etc.

The status flags
----------------
The standard requires at least the following flags:
FE_DIVBYZERO A division by zero has occurred
FE_INEXACT The last operation had to be rounded

Are you sure it is "the last operation", and not any operation? Does
this flag get cleared again after an operation that doesn't need
rounding?


The x87 instruction manual specifies that by most arithmetic
operations, i.e. FADD FSUB, etc this flag is set/unset if the
result needed rounding. The internal flags (C0 C1 C3) specify
the direction of the rounding that was performed: up or down.
FE_INVALID An invalid operation was attempted
FE_OVERFLOW The result of an operation was too big to be represented
FE_UNDERFLOW The result of an operation was too small to be represented

In addition to this standard flags, lcc-win32 provides:
FE_DENORMAL The result of the last operation was a denormal number
FE_STACKFAULT The floating point stack has overflowed.

The denormal flag means that a loss of precision is certain, the number
is too small to be represented.

Do you mean "too small to be represented with full precision"?


Yes, you are right. Thanks.
The stack fault flag means that
lcc-win32 generated bad code, since all floating point operations should
balance the floating point stack. If you ever test positive for this
flag, do not hesitate to send me a bug report!

I don't like this at all. I wouldn't want to write code that checks if
the compiler is broken. If there is any possibility at all that this
happens, could you make this throw a hardware exception, so that it
definitely will get detected?


Yes, it would just mean unmasking the exception flag, what would
provoke a trap if a FP stack overflow happens.
In general, the floating point flags can be queried by the program to
know if the last operation did complete without problems. Here is a
small example to show you how this works:

/* This program tests a division by zero */
#include <fenv.h>
#include <stdio.h>
int main(void)
{
double a=1,b=0;
feclearexcept(FE_DIVBYZERO);
a=a/b;
if (fetestexcept(FE_DIVBYZERO)) {
printf("You have divided by zero!\n");
}
return 0;
}

First we clear the flag that we are going to use using feclearexcept.
Then, we perform our operation and query if the flag is set using
fetestexcept.

Since we know that the flags are set but not cleared, the expression
could be very well be a much more complicated sequence of operations.
The above code would work the same, but we would loose the possibility


**** lose
of knowing exactly which operation failed. This is in many cases not


******

I wouldn't say that the operaton failed. Most floating-point operations
will set the FE_INEXACT flag, that doesn't mean they failed.


True, will correct that.
Thanks for your input.

jacob
Jan 18 '06 #3
jacob navia wrote:
The status flags
----------------
The standard requires at least the following flags:
FE_DIVBYZERO A division by zero has occurred
FE_INEXACT The last operation had to be rounded
It would be much more straight forward to say that the result produced
was not the exact mathematical result of the operation. That avoids the
awkwardness of having to define "had to be rounded".
FE_INVALID An invalid operation was attempted
FE_OVERFLOW The result of an operation was too big to be represented
FE_UNDERFLOW The result of an operation was too small to be represented

Nit: The magnitude of the result was too large/small to be represented.
In addition to this standard flags, lcc-win32 provides:
FE_DENORMAL The result of the last operation was a denormal number
FE_STACKFAULT The floating point stack has overflowed.

The denormal flag means that a loss of precision is certain, the number
is too small to be represented.
The statement "loss of precision is certain" is accurate, but
misleading. It doesn't imply an erroneous value or loss of accuracy.

A denormalized number is too small to be represented with full
precision, but not too small to be represented at all.
In general, the floating point flags can be queried by the program to
know if the last operation did complete without problems. Here is a suggest: completed ^^^^^^^^^^^^ small example to show you how this works:

/* This program tests a division by zero */
#include <fenv.h>
#include <stdio.h>
int main(void)
{
double a=1,b=0;
feclearexcept(FE_DIVBYZERO);
a=a/b;
if (fetestexcept(FE_DIVBYZERO)) {
printf("You have divided by zero!\n");
}
return 0;
}

First we clear the flag that we are going to use using feclearexcept. First we clear the flag FE_DIVBYZERO using feclearexcept.
Then, we perform our operation and query if the flag is set using
fetestexcept. We next perform the divide, then test the flag using fetestexcept.
Since we know that the flags are set but not cleared, the expression xxxxxxxxxxxx could be very well be a much more complicated sequence of operations.
The above code would work the same, but we would loose the possibility
of knowing exactly which operation failed. This is in many cases not
very important, we could very well be interested that somewhere there xxxx . We might only need to know was a serious error, without bothering to investigate which operation knowing precisely where. was that it failed.


--
Thad
Jan 19 '06 #4
Thad Smith a écrit :
jacob navia wrote:
The status flags
----------------
The standard requires at least the following flags:
FE_DIVBYZERO A division by zero has occurred
FE_INEXACT The last operation had to be rounded

It would be much more straight forward to say that the result produced
was not the exact mathematical result of the operation. That avoids the
awkwardness of having to define "had to be rounded".


OK, it is a better formulation. Will change that.
FE_INVALID An invalid operation was attempted
FE_OVERFLOW The result of an operation was too big to be represented
> FE_UNDERFLOW The result of an operation was too small to be

represented

Nit: The magnitude of the result was too large/small to be represented.


Mmmm, if I use magnitude I would have to explain what does that mean
in this context. I do explain in a previous chapter the floating
point format, so I could go back to that and explain overflow

explicitely with normal --> denormal --> overflow
In addition to this standard flags, lcc-win32 provides:
FE_DENORMAL The result of the last operation was a denormal number
FE_STACKFAULT The floating point stack has overflowed.

The denormal flag means that a loss of precision is certain, the
number is too small to be represented.

The statement "loss of precision is certain" is accurate, but
misleading. It doesn't imply an erroneous value or loss of accuracy.

A denormalized number is too small to be represented with full
precision, but not too small to be represented at all.
In general, the floating point flags can be queried by the program to
know if the last operation did complete without problems. Here is a


suggest: completed ^^^^^^^^^^^^

Yes, typo. Thanks
small example to show you how this works:

/* This program tests a division by zero */
#include <fenv.h>
#include <stdio.h>
int main(void)
{
double a=1,b=0;
feclearexcept(FE_DIVBYZERO);
a=a/b;
if (fetestexcept(FE_DIVBYZERO)) {
printf("You have divided by zero!\n");
}
return 0;
}

First we clear the flag that we are going to use using feclearexcept.


First we clear the flag FE_DIVBYZERO using feclearexcept.
Then, we perform our operation and query if the flag is set using
fetestexcept.


We next perform the divide, then test the flag using fetestexcept.

Since we know that the flags are set but not cleared, the expression


xxxxxxxxxxxx
could be very well be a much more complicated sequence of operations.
The above code would work the same, but we would loose the possibility
of knowing exactly which operation failed. This is in many cases not
very important, we could very well be interested that somewhere there


xxxx . We might only need to know
> was a serious error, without bothering to investigate which operation

knowing precisely where.
was that it failed.


Jan 19 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Dave | last post by:
Hi folks, I am trying to develop a routine that will handle sphere-sphere and sphere-triangle collisions and interactions. My aim is to develop a quake style collision engine where a player can...
31
by: JS | last post by:
We have the same floating point intensive C++ program that runs on Windows on Intel chip and on Sun Solaris on SPARC chips. The program reads the exactly the same input files on the two platforms....
5
by: Anton Noll | last post by:
We are using Visual Studio 2003.NET (C++) for the development of our software in the fields digital signal processing and numerical acoustics. One of our programs was working correctly if we are...
687
by: cody | last post by:
no this is no trollposting and please don't get it wrong but iam very curious why people still use C instead of other languages especially C++. i heard people say C++ is slower than C but i can't...
7
by: Vinoth | last post by:
I'm working in an ARM (ARM9) system which does not have Floating point co-processor or Floating point libraries. But it does support long long int (64 bits). Can you provide some link that would...
32
by: ma740988 | last post by:
template <class T> inline bool isEqual( const T& a, const T& b, const T epsilon = std::numeric_limits<T>::epsilon() ) { const T diff = a - b; return ( diff <= epsilon ) && ( diff >= -epsilon );...
14
by: Peter Sprenger | last post by:
Hello, I want to efficient convert floating point numbers (IEEE754) into a string. I have no library routines that do the job (like sprintf etc.), because I work in an embedded environment. ...
39
by: rembremading | last post by:
Hi all! The following piece of code has (for me) completely unexpected behaviour. (I compile it with gcc-Version 4.0.3) Something goes wrong with the integer to float conversion. Maybe somebody...
9
by: ssubbarayan | last post by:
Hi all, I am trying a program to convert floating point values to a byte array and printing the same to the screen.The idea behind this is we already have an existing function which can do byte...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.