gmaranca@cipc1.Dayton.NCR.COM (Gabriel Maranca) (10/05/89)
I am posting a few answers to my question on why isn't the abs function type independent. I wish to thank everybody. Based on the answers, my ABS macro now has become: #define ABS(x) (((x) < 0) ? (-(x)) : (x)) If anybody decides to use it, the macro is faster and more generic than the standard abs and labs functions, but invocations like ABS(k++) won't work properly. A complex expression may be passed as a parameter, as long as evaluating it three times doesn't cause problems. If the expression is very complex, or if it is a function call, the ABS macro may wind up being slower than the abs and labs functions. These are the answers I got: chris@mimsy.UUCP (Chris Torek) writes: > >#define ABS(x) (((long)(x) < 0L)? -(x) : (x)) > The cast to long and the 0L are both unnecessary. If left out, this > ABS will do its comparison in whatever type x has. Thanks for illuminating me. I didn't know context type promotion was a standard feature of C (I knew my compiler did it). This will greatly simplify my code (I was doing these silly casts everywhere, thinking I was creating more portable code). > Note that ABS(k++) and the like will do `mysterious' things, and Thanks again. This explains why abs is not a macro. > that on most machines, ABS(largest_negative_integer) is either > a (compile or run)-time trap or simply largest_negative_integer. If you have time, could you explain how is this problem resolved by the standard library function? flaps@dgp.toronto.edu (Alan J Rosenthal) writes: > It is portable but will only work for ints and longs. But the following > is portable and will work for all types, including unsigned long, double, > and long long if it exists: > #define ABS(x) (((x) < 0) ? -(x) : (x)) > The zero will get promoted to the correct type. Thanks. This is the same answer I got from Chris. gwyn@brl.arpa (Doug Gwyn) writes: > That's just the way it's always been. English is not my native language, so I may have misinterpreted your statement. If you mean the abs function has always been type independent, my K&R book (second edition - pg. 253) makes reference to two functions: int abs(int n) and long labs(long n) But maybe you meant the abs function has always been type dependent, which doesn't seem a very good reason for keeping it the same way. > Note that if its argument has side effects, funny behavior may occur. Thanks. I will avoid passing such arguments. This IS a good reason for keeping the abs and labs functions the same. bill davidsen (davidsen@crdos1.crd.GE.COM) writes: > 1. instead of -(x) use (-(x)). Good point. I had overlooked this potential trap in my original macro. > 2. you might want to use (double) to work with more types Per Chris and Alan, a better approach is to remove the cast altogether. This should work with any current or future data type. Please let me know if this is not true for some C compiler. > 3. you still have to be careful about what you use for an > argument to avoid things like ABS(x[m++]) which are only > evaluated once if ABS is a procedure. OK. I wonder how many standard library "functions" are implemented as macros that could behave similarly? Or have such macros consistently been avoided because of this side effect? By the way, Bill, I am not a "she" (do not confuse Gabriel and Gabrielle) ;-) --- #Gabriel Maranca #Gabriel.Maranca@cipc1.Dayton.NCR.COM #...!uunet!ncrlnk!cipc1!gmaranca -- #Gabriel Maranca #Gabriel.Maranca@cipc1.Dayton.NCR.COM #...!uunet!ncrlnk!cipc1!gmaranca
chris@mimsy.UUCP (Chris Torek) (10/07/89)
[#define ABS(x) ((x) < 0 ? -(x) : (x))] In an article whose referent was deleted by deficient news software, I wrote: >>on most machines, ABS(largest_negative_integer) is either a (compile >>or run)-time trap or simply largest_negative_integer. In article <1392@cipc1.Dayton.NCR.COM> gmaranca@cipc1.Dayton.NCR.COM (Gabriel Maranca) writes: >... A complex expression may be passed as a parameter, as long >as evaluating it three times doesn't cause problems. Actually, x is evaluated exactly twice. >If you have time, could you explain how is this problem resolved by >the standard library function? The short answer is `not'. It is hard to give a single `best' answer for -(-2147483647 - 1) on a 32-bit two's complement machine. The library routines I have seen simply negate it and do whatever the machine's instruction set does on `impossible negation'. >... I wonder how many standard library "functions" are implemented as >macros that could behave similarly? Or have such macros consistently >been avoided because of this side effect? In general, the latter is true. The proposed ANSI C standard requires that side effects take place exactly once, which effectively prohibits a straightforward macro version of abs() and labs(). One can still write, e.g., int abs(int); #define abs(x) __abs(x) static __inline int __abs(int x) { return x < 0 ? -x : x; } in GCC. I have used this in <stdio.h> to make putc() readable (`#ifdef'ed on __GNUC__, of course). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
meissner@tiktok.dg.com (Michael Meissner) (10/10/89)
In article <20042@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: | In general, the latter is true. The proposed ANSI C standard requires | that side effects take place exactly once, which effectively prohibits | a straightforward macro version of abs() and labs(). One can still | write, e.g., | | int abs(int); | #define abs(x) __abs(x) | static __inline int __abs(int x) { return x < 0 ? -x : x; } | | in GCC. I have used this in <stdio.h> to make putc() readable (`#ifdef'ed | on __GNUC__, of course). I know the above example is to demostrate the use of __inline, but with GNU C, it does support a builtin abs function (though for some reason it's not documented). You can simplify the above to: #ifdef __GNUC__ extern int abs(int); #define abs(x) __builtin_abs(x) #endif Some machines have fast ways of doing abs (as compared to the branch method above). Gnu C also has the following builtin functions related to abs: __builtin_labs(long) __builtin_fabs(double) -- Michael Meissner, Data General. Uucp: ...!mcnc!rti!xyzzy!meissner If compiles were much Internet: meissner@dg-rtp.DG.COM faster, when would we Old Internet: meissner%dg-rtp.DG.COM@relay.cs.net have time for netnews?
keesan@bbn.com (Morris M. Keesan) (10/14/89)
In article <1392@cipc1.Dayton.NCR.COM> gmaranca@cipc1.Dayton.NCR.COM (Gabriel Maranca) writes: >#define ABS(x) (((x) < 0) ? (-(x)) : (x)) . . . >bill davidsen (davidsen@crdos1.crd.GE.COM) writes: >> 1. instead of -(x) use (-(x)). >Good point. I had overlooked this potential trap in my original macro. I don't see why the extra parentheses are necessary, or their absence a trap. #define ABS(x) ((x) < 0 ? -(x) : (x)) should work fine, because both < and - have higher precedence than ?:, and the whole expansion is protected by the outermost parentheses. It's not as if -(x) were the full expansion of the macro. ------------------------------------------------------------------------------ Morris M. Keesan | Internet: keesan@bbn.com | UUCP: Figure it out from the path |