Velocity Reviews > Writing a macro for checking close enough floating points.

# Writing a macro for checking close enough floating points.

pereges
Guest
Posts: n/a

 06-29-2008
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)))

Walter Roberson
Guest
Posts: n/a

 06-29-2008
In article <(E-Mail Removed)>,
pereges <(E-Mail Removed)> wrote:
>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
--
"The quirks and arbitrariness we observe force us to the
conclusion that ours is not the only universe." -- Walter Kistler

August Karlstrom
Guest
Posts: n/a

 06-29-2008
pereges wrote:
> 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

pereges
Guest
Posts: n/a

 06-29-2008
On Jun 29, 7:17 pm, August Karlstrom <(E-Mail Removed)> wrote:

> 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 ?

Ben Bacarisse
Guest
Posts: n/a

 06-29-2008
August Karlstrom <(E-Mail Removed)> writes:

> pereges wrote:
>> Hi, I'm trying to write a macro for the relative difference function

<snip>
> ... 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.

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

--
Ben.

August Karlstrom
Guest
Posts: n/a

 06-29-2008
Ben Bacarisse wrote:
> August Karlstrom <(E-Mail Removed)> writes:
>>
>> 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?

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

Ben Bacarisse
Guest
Posts: n/a

 06-29-2008
August Karlstrom <(E-Mail Removed)> writes:

> Ben Bacarisse wrote:
>> August Karlstrom <(E-Mail Removed)> writes:
>>>
>>> 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?

>
> Division by zero (mathematically speaking).
>
>> Did you intend to check that
>>
>> assert(max(fabs(x), fabs(y)) != 0);

>
> Yes, same thing.

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

--
Ben.

Barry Schwarz
Guest
Posts: n/a

 06-29-2008
On Sun, 29 Jun 2008 07:57:08 -0700 (PDT), pereges <(E-Mail Removed)>
wrote:

>On Jun 29, 7:17 pm, August Karlstrom <(E-Mail Removed)> wrote:
>
>
>> 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 ?

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

Flash Gordon
Guest
Posts: n/a

 07-22-2008
August Karlstrom wrote, On 29/06/08 16:40:
> Ben Bacarisse wrote:
>> August Karlstrom <(E-Mail Removed)> writes:
>>>
>>> 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?

>
> 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;

>> 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.

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!
--
Flash Gordon

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post IĆ±aki Baz Castillo Ruby 7 01-12-2010 01:32 PM pereges C Programming 3 07-23-2008 03:37 PM pereges C Programming 7 05-31-2008 07:24 AM ajacobs2 Digital Photography 33 10-05-2003 12:14 PM VT Digital Photography 43 09-12-2003 11:15 AM