By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,193 Members | 1,734 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,193 IT Pros & Developers. It's quick & easy.

Why the zero case in fabs()?

P: n/a
In Plauger's THE STANDARD C LIBRARY (1992) there is the source code for
fabs.c (p140).

/* fabs function */
#include "xmath.h"
double (fabs)(double x)
{
switch (_Dtest(&x))
{ /* test for special codes */
case NAN:
errno = EDOM;
return (x);
case INF:
errno = ERANGE;
return (_Inf._D);
case 0:
return (0.0);
default: /* finite */
return (x < 0.0 ? -x : x);
}
}

This is not necessarily a question about fabs() in particular, but rather a
question about the *technique* Plauger has employed, and if there is a
subtlety involved.

My question is: why is there a case for 0, which simply returns 0.0? Without
it, the default case will trap it anyway, and return 0, which will be
converted to double - the return type of the function.

Also, I'm puzzled by the superfluous use of parentheses around the return
expressions.

Martin
http://martinobrien.co.uk/

Nov 14 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a
In <CD******************@fe04.usenetserver.com> "Martin" <martin.o_brien@[no-spam]which.net> writes:
In Plauger's THE STANDARD C LIBRARY (1992) there is the source code for
fabs.c (p140).

/* fabs function */
#include "xmath.h"
double (fabs)(double x)
{
switch (_Dtest(&x))
{ /* test for special codes */
case NAN:
errno = EDOM;
return (x);
case INF:
errno = ERANGE;
return (_Inf._D);
case 0:
return (0.0);
default: /* finite */
return (x < 0.0 ? -x : x);
}
}

This is not necessarily a question about fabs() in particular, but rather a
question about the *technique* Plauger has employed, and if there is a
subtlety involved.

My question is: why is there a case for 0, which simply returns 0.0? Without
it, the default case will trap it anyway, and return 0, which will be
converted to double - the return type of the function.
No conversion to double is needed or would occur in that case: the
function would return x which is already of type double.

However, I don't know why Plauger handled 0.0 as a special case.
Also, I'm puzzled by the superfluous use of parentheses around the return
expressions.


They were mandatory, back when Plauger started to use C. Old habits die
hard...

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #2

P: n/a
Martin <martin.o_brien@[no-spam]which.net> wrote:

My question is: why is there a case for 0, which simply returns 0.0? Without
it, the default case will trap it anyway, and return 0, which will be
converted to double - the return type of the function.
The subtlety you're missing is signed zeros. On implementations that
have such things, -0.0 is not < 0.0, so the default case would return it
as-is (i.e., -0.0) rather than returning the correct +0.0.
Also, I'm puzzled by the superfluous use of parentheses around the return
expressions.


Style. Or lack thereof, if we're making value judgments. :-)

-Larry Jones

I don't think that question was very hypothetical at all. -- Calvin
Nov 14 '05 #3

P: n/a
"Martin" <martin.o_brien@[no-spam]which.net> writes:
In Plauger's THE STANDARD C LIBRARY (1992) there is the source code for
fabs.c (p140).

/* fabs function */
#include "xmath.h"
double (fabs)(double x)
{
switch (_Dtest(&x))
{ /* test for special codes */
case NAN:
errno = EDOM;
return (x);
case INF:
errno = ERANGE;
return (_Inf._D);
case 0:
return (0.0);
default: /* finite */
return (x < 0.0 ? -x : x);
}
}

This is not necessarily a question about fabs() in particular, but
rather a question about the *technique* Plauger has employed, and if
there is a subtlety involved.

My question is: why is there a case for 0, which simply returns 0.0?
Without it, the default case will trap it anyway, and return 0, which
will be converted to double - the return type of the function.
I don't know what `_Dtest' does, but presumably it returns 0 if `x' is
0.0. If it is already known that `x' is 0.0, there is no reason to
compare it with 0.0 again, which would only (slightly) degrade the
performance.
Also, I'm puzzled by the superfluous use of parentheses around the
return expressions.


So am I.

Martin
Nov 14 '05 #4

P: n/a
>This is not necessarily a question about fabs() in particular, but rather a
question about the *technique* Plauger has employed, and if there is a
subtlety involved.

My question is: why is there a case for 0, which simply returns 0.0? Without
it, the default case will trap it anyway, and return 0, which will be
converted to double - the return type of the function.


Is negative zero an issue here? Are there some implementations
(possibly buggy by current floating point standards) where negative
zero tests as less than 0? Perhaps it was desired that fabs() never
return anything that tests less than zero, not even negative zero,
even for implementations of what later became IEEE floating point
that didn't quite handle all the corner cases involving negative
zero according to the current floating point standard.

Gordon L. Burditt
Nov 14 '05 #5

P: n/a
In article <CD******************@fe04.usenetserver.com>,
"Martin" <martin.o_brien@[no-spam]which.net> wrote:
In Plauger's THE STANDARD C LIBRARY (1992) there is the source code for
fabs.c (p140).

/* fabs function */
#include "xmath.h"
double (fabs)(double x)
{
switch (_Dtest(&x))
{ /* test for special codes */
case NAN:
errno = EDOM;
return (x);
case INF:
errno = ERANGE;
return (_Inf._D);
case 0:
return (0.0);
default: /* finite */
return (x < 0.0 ? -x : x);
}
}

This is not necessarily a question about fabs() in particular, but rather a
question about the *technique* Plauger has employed, and if there is a
subtlety involved.

My question is: why is there a case for 0, which simply returns 0.0? Without
it, the default case will trap it anyway, and return 0, which will be
converted to double - the return type of the function.
One possibility is that he wanted floating point numbers in IEEE 754
format to be handled correctly: In that format, there are two different
representations for +0.0 and -0.0; both produce values that compare
equal to x, but you would want fabs (-0.0) to be +0.0.
Also, I'm puzzled by the superfluous use of parentheses around the return
expressions.

Martin
http://martinobrien.co.uk/

Nov 14 '05 #6

P: n/a
"Christian Bau" <ch***********@cbau.freeserve.co.uk> wrote in message
news:ch*********************************@slb-newsm1.svr.pol.co.uk...
In article <CD******************@fe04.usenetserver.com>,
"Martin" <martin.o_brien@[no-spam]which.net> wrote:
In Plauger's THE STANDARD C LIBRARY (1992) there is the source code for
fabs.c (p140).

/* fabs function */
#include "xmath.h"
double (fabs)(double x)
{
switch (_Dtest(&x))
{ /* test for special codes */
case NAN:
errno = EDOM;
return (x);
case INF:
errno = ERANGE;
return (_Inf._D);
case 0:
return (0.0);
default: /* finite */
return (x < 0.0 ? -x : x);
}
}

This is not necessarily a question about fabs() in particular, but rather a question about the *technique* Plauger has employed, and if there is a
subtlety involved.

My question is: why is there a case for 0, which simply returns 0.0? Without it, the default case will trap it anyway, and return 0, which will be
converted to double - the return type of the function.


One possibility is that he wanted floating point numbers in IEEE 754
format to be handled correctly: In that format, there are two different
representations for +0.0 and -0.0; both produce values that compare
equal to x, but you would want fabs (-0.0) to be +0.0.


Correct.
Also, I'm puzzled by the superfluous use of parentheses around the return expressions.


It's a style I settled on many years ago. (FWIW and IIRC, there was a
brief period when the parentheses were required by an early Ritchie
compiler.) We made it part of the shop standard at Whitesmiths and
I've stuck with it over the years.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Nov 14 '05 #7

P: n/a
Christian Bau wrote:
One possibility is that he wanted floating point numbers in IEEE 754
format to be handled correctly: In that format, there are two different
representations for +0.0 and -0.0; both produce values that compare
equal to x, but you would want fabs (-0.0) to be +0.0.
"P.J. Plauger" commented:
Correct.
I wrote:
Also, I'm puzzled by the superfluous use of parentheses around the
return expressions.


"P.J. Plauger" replied It's a style I settled on many years ago. (FWIW and IIRC, there was a
brief period when the parentheses were required by an early Ritchie
compiler.) We made it part of the shop standard at Whitesmiths and
I've stuck with it over the years.


My thanks to P.J. Plauger, Christian, Gordon, Martin Dicksopp, Lawrence, and
Dan for your reponses.

THE STANDARD C LIBRARY is packed with much information I know, and is a
large enough book, but perhaps that subtlety with the IEEE 754 should have
been pointed out (brief comment in the code?).

--
Martin
http://martinobrien.co.uk/

Nov 14 '05 #8

P: n/a
Martin wrote:

In Plauger's THE STANDARD C LIBRARY (1992) there is the source
code for fabs.c (p140).

/* fabs function */
#include "xmath.h"
double (fabs)(double x)
{
switch (_Dtest(&x))
{ /* test for special codes */
case NAN:
errno = EDOM;
return (x);
case INF:
errno = ERANGE;
return (_Inf._D);
case 0:
return (0.0);
default: /* finite */
return (x < 0.0 ? -x : x);
}
}

This is not necessarily a question about fabs() in particular,
but rather a question about the *technique* Plauger has employed,
and if there is a subtlety involved.

My question is: why is there a case for 0, which simply returns
0.0? Without it, the default case will trap it anyway, and return
0, which will be converted to double - the return type of the
function.
The switch is not testing x, but whatever the return value of
_Dtest(&x) happens to be. That obviously involves some magic
incantations, and is outside the users name space. It might well
have something to do with the existance of -ve 0 in that
particular arithmetic system.

Also, I'm puzzled by the superfluous use of parentheses around
the return expressions.


Superfluous is in the eye of the beholder. Plauger, and others,
feel that there is no further need to ration parentheses and that
they can be neatly used to delimit expressions.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #9

P: n/a
In <nr************@jones.homeip.net> la************@ugsplm.com writes:
Martin <martin.o_brien@[no-spam]which.net> wrote:

My question is: why is there a case for 0, which simply returns 0.0? Without
it, the default case will trap it anyway, and return 0, which will be
converted to double - the return type of the function.


The subtlety you're missing is signed zeros. On implementations that
have such things, -0.0 is not < 0.0, so the default case would return it
as-is (i.e., -0.0) rather than returning the correct +0.0.


If -0.0 is not < 0.0, why is it an error to return it as such?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #10

P: n/a
Dan Pop <Da*****@cern.ch> wrote:

If -0.0 is not < 0.0, why is it an error to return it as such?


I won't defend the vagaries of signed zeros, but although -0.0 and +0.0
compare equal (obviously), -0.0 is nonetheless negative whereas the
result of fabs() should (obviously) be non-negative. Despite comparing
equal, -0.0 and +0.0 can still be distingished (e.g., by the signbit()
or copysign() functions).

-Larry Jones

I don't need to improve! Everyone ELSE does! -- Calvin
Nov 14 '05 #11

P: n/a
In article <c0***********@sunnews.cern.ch>, Da*****@cern.ch (Dan Pop)
wrote:
In <nr************@jones.homeip.net> la************@ugsplm.com writes:
Martin <martin.o_brien@[no-spam]which.net> wrote:

My question is: why is there a case for 0, which simply returns 0.0?
Without
it, the default case will trap it anyway, and return 0, which will be
converted to double - the return type of the function.


The subtlety you're missing is signed zeros. On implementations that
have such things, -0.0 is not < 0.0, so the default case would return it
as-is (i.e., -0.0) rather than returning the correct +0.0.


If -0.0 is not < 0.0, why is it an error to return it as such?


If the implementor guarantees that the compiler implements not only the
C Standard, but also for example the IEEE 754 Standard then returning
-0.0 as the result of fabs (-0.0) is an error. It would violate the IEEE
754 Standard.
Nov 14 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.