Writing a macro for checking close enough floating points.

P

pereges

Hi, I'm trying to write a macro for the relative difference function
which is used to check the close enough floating point values. Is
this correct way to write it ? :


#define max(x, y) ((x) > (y) ? (x) : (y))
#define eq(a, b) max(fabs(a), fabs(b)) == 0.0 ? 0.0 : fabs(a - b) /
(max(fabs(a), fabs(b)))
 
W

Walter Roberson

Hi, I'm trying to write a macro for the relative difference function
which is used to check the close enough floating point values. Is
this correct way to write it ? :
#define max(x, y) ((x) > (y) ? (x) : (y))
#define eq(a, b) max(fabs(a), fabs(b)) == 0.0 ? 0.0 : fabs(a - b) /
(max(fabs(a), fabs(b)))

The name eq() suggests a logical test. Logical tests in C return
an integral 0 or an integral 1. Your macro returns a floating 0.0
or some other floating point calculation (which might be floating 0.0
if the two values are equal but non-0.) Using a logical name for a test
but returning a floating point value suggests that you have some
confusion about how this macro is going to be used.

Also, consider that in the eq() macro that the arguments might be
expressions. Unless subtraction is the lowest precedence operator
(and it isn't), fabs(a - b) is not going to be correct if a or b
are expressions of lower precedence. Take the hint from the way that
the x and y arguments are used in max().

I have not attempted a numeric analysis to determine what
value your eq() macro returns.
 
A

August Karlstrom

pereges said:
Hi, I'm trying to write a macro for the relative difference function
which is used to check the close enough floating point values. Is
this correct way to write it ? :


#define max(x, y) ((x) > (y) ? (x) : (y))
#define eq(a, b) max(fabs(a), fabs(b)) == 0.0 ? 0.0 : fabs(a - b) /
(max(fabs(a), fabs(b)))

Are you sure you really need to define the functions as macros? If you
define them as ordinary functions they can typically be inlined by the
compiler anyway. This way you will also have type safety. I would write
something like the following:

#include <assert.h>
#include <math.h>

double max(double x, double y)
{
return (x > y)? x: y;
}


double reldiff(double x, double y)
{
assert((x != 0) || (y != 0));

return fabs(x - y) / max(fabs(x), fabs(y));
}


August
 
P

pereges

Are you sure you really need to define the functions as macros? If you
define them as ordinary functions they can typically be inlined by the
compiler anyway. This way you will also have type safety. I would write
something like the following:

#include <assert.h>
#include <math.h>

double max(double x, double y)
{
return (x > y)? x: y;

}

double reldiff(double x, double y)
{
assert((x != 0) || (y != 0));

return fabs(x - y) / max(fabs(x), fabs(y));

}

Is it always better to write functions over macros for even smaller
things, say square of a number ?
For my project, I have a file called util.h which basically contains
some math macros like this, error display macro, constants etc. all at
one place and its a few lines anyway so including it in most files
won't hurt that bad whereas if i write full fledge functions it
increases the amount of code that is included everytime. Is that
correct ?
 
B

Ben Bacarisse

... I would
write something like the following:

#include <assert.h>
#include <math.h>

double max(double x, double y)
{
return (x > y)? x: y;
}


double reldiff(double x, double y)
{
assert((x != 0) || (y != 0));

What is this assert for? What problem is caused by x == 0 && y == 0?
Did you intend to check that

assert(max(fabs(x), fabs(y)) != 0);

? If so, i would argue that this is not a good use of assert. Not
unless you know something about the use of this function that makes
calling it in that way a logic fault in the program.
 
A

August Karlstrom

Ben said:
What is this assert for? What problem is caused by x == 0 && y == 0?

Division by zero (mathematically speaking).
Did you intend to check that

assert(max(fabs(x), fabs(y)) != 0);

Yes, same thing.
? If so, i would argue that this is not a good use of assert. Not
unless you know something about the use of this function that makes
calling it in that way a logic fault in the program.

The relative difference of x and y is undefined if both x and y are
zero. The assert statement is used here to put constraints on the input
parameters (for debugging purposes and for documentation). The caller
must of course make sure that this precondition is met.


August
 
B

Ben Bacarisse

August Karlstrom said:
Division by zero (mathematically speaking).


Yes, same thing.

Duh! I forgot the fabs()s were there (despite having typed them).
 
B

Barry Schwarz

Is it always better to write functions over macros for even smaller
things, say square of a number ?

It is always better to write the code in a way that best (tm)
satisfies several possibly competing requirements.

First and foremost, it must do the job.
It should be easily maintained.
It should be easy to read and understand
It should be extendable (for example, can the "arguments" be
expressions with side effects).
It should promote re-use.
For my project, I have a file called util.h which basically contains
some math macros like this, error display macro, constants etc. all at
one place and its a few lines anyway so including it in most files
won't hurt that bad whereas if i write full fledge functions it

A lot of projects are done this way so it can't be that unreasonable.
increases the amount of code that is included everytime. Is that
correct ?

If you invoke a macro 100 times will it generate more code than if you
call the same function 100 times? As always, it depends.

If you find a problem with the macro, how many routines will need to
be recompiled? If you fix the function, how many?

You are on the verge of treating the issue as a premature
optimization. In the vast majority of cases, this places the emphasis
on the wrong syllable. Write clear working code and don't worry about
extra lines of code in the compile phase or a few extra K of memory in
the execution phase.


Remove del for email
 
F

Flash Gordon

August Karlstrom wrote, On 29/06/08 16:40:
Division by zero (mathematically speaking).

Logically it would more more sense to do
if (x==0 && y==0) return 0;
After all, if most numbers are identical (i.e. 0) there is no difference!

Alternatively, reduce the above to one test with:
if (x==y) return 0;
Yes, same thing.


The relative difference of x and y is undefined if both x and y are
zero. The assert statement is used here to put constraints on the input
parameters (for debugging purposes and for documentation). The caller
must of course make sure that this precondition is met.

Since this function is for use in determining if two numbers are
identical such a restriction would not be sensible. Return 0 which is a
sensible definition for the relative difference if both number are 0
since the absolute difference is 0!
 

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

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top