max@george.lbl.gov (Max Rible) (01/14/89)
I'm trying to do deal with floating point numbers as if they're ints. Things like "if(((3.1 - 3.14) & 0x7FFFFFF) <= 0.1)"--- lousy programming style, I know, but I'm interested in speed, not portability for this application. (On a Sun, if C blithely masked out the low bits, that would strip the sign bit.) Also tests like if((3.1 - 3.14) & 0x80000000) might be faster than if((3.1 - 3.14) < 0.0) ; I'd like to know if there's any dirty trick that would permit this sort of action. (I agree that it shouldn't be an easy dirty trick, but I'd certainly like for it to be possible without adding any extra instructions for conversion!) Reply to max@csam.lbl.gov and I'll summarise. Thank you. Max -- /----------------------------------v------------------------------------------\ | Max Rible, Computer Graphics Lab | "I have a very firm grasp on reality! I | | Lawrence Berkeley Laboratories | can reach out and strangle it any time!" | | ARPA: max@csam.lbl.gov |UUCP: {ames!ucbcad,ucbvax}!cartan!csam!max| \----------------------------------^------------------------------------------/
bright@Data-IO.COM (Walter Bright) (01/17/89)
In article <MAX.89Jan13163256@george.lbl.gov> max@george.lbl.gov (Max Rible) writes: >I'm trying to do deal with floating point numbers as if they're ints. >Things like "if(((3.1 - 3.14) & 0x7FFFFFF) <= 0.1)"--- lousy >programming style, I know, but I'm interested in speed, not >portability for this application. Two ways to do it: 1. Define a union such as: typedef union { double d; unsigned short u[4]; } dblunion; Assign values into d, and do the bit testing with u. 2. Try this: double d; d = expression; if (*(unsigned short *)&d & 0x1234) ... I've generally used method 2. I know it violates all notions of portability, but it was for very specific hardware! Using method 1 sometimes implies passing/returning unions to functions, which is inefficiently implemented in a lot of compilers. Unless your compiler supports something like (dblunion)(1.2) as a 'type paint', I see no way to do this without going through a memory location.
cik@l.cc.purdue.edu (Herman Rubin) (01/17/89)
In article <1825@dataio.Data-IO.COM>, bright@Data-IO.COM (Walter Bright) writes: > In article <MAX.89Jan13163256@george.lbl.gov> max@george.lbl.gov (Max Rible) writes: > >I'm trying to do deal with floating point numbers as if they're ints. < <Things like "if(((3.1 - 3.14) & 0x7FFFFFF) <= 0.1)"--- lousy < <programming style, I know, but I'm interested in speed, not < <portability for this application. > > Two ways to do it: > 1. Define a union such as: > typedef union > { double d; > unsigned short u[4]; > } dblunion; > Assign values into d, and do the bit testing with u. > 2. Try this: > double d; > d = expression; > if (*(unsigned short *)&d & 0x1234) > ... > I've generally used method 2. I know it violates all notions of > portability, but it was for very specific hardware! Using method > 1 sometimes implies passing/returning unions to functions, which > is inefficiently implemented in a lot of compilers. > > Unless your compiler supports something like (dblunion)(1.2) as > a 'type paint', I see no way to do this without going through a > memory location. This is the sort of lack on the part of languages and compilers which should not exist. If the combination (language + compiler) allows register unions (there are some) and register arrays (I do not know of any), the following 1. Define a union such as: typedef union { double d; unsigned long u[2]; } dblunion; would work. The alternative is to use the clumsy assembly language and even clumsier asm pseudo-function in C. Even this can give problems if the register variables in asm lines must be explicitly given, rather than assigned by the compiler; in that case (which is what I have to contend with), produce the assembler code with -S and edit it. I agree that every language should make it easy for the knowledgeable programmer to do these things, but I am afraid the movement is in the opposite direction. -- Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907 Phone: (317)494-6054 hrubin@l.cc.purdue.edu (Internet, bitnet, UUCP)
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/18/89)
In article <1096@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: >> In article <MAX.89Jan13163256@george.lbl.gov> max@george.lbl.gov (Max Rible) writes: >> >I'm trying to do deal with floating point numbers as if they're ints. >< <Things like "if(((3.1 - 3.14) & 0x7FFFFFF) <= 0.1)"--- lousy >< <programming style, I know, but I'm interested in speed, not >< <portability for this application. >I agree that every language should make it easy for the knowledgeable >programmer to do these things, but I am afraid the movement is in the >opposite direction. I utterly disagree. Generating efficient code for routine floating-point operations is the job of the compiler, not the high-level programmer. There is no reason why, if the suggested replacement test represents the most efficient code for the test, that the compiler should not generate it in the first place. There are a few cases, such as dealing with IEEE-754 NaNs, where bit patterns are necessary. C vendors on such systems have, quite properly, provided the necessary support as macros or functions, so the programmer still need not concern himself with bit-twiddling.
mrm%puffin@Sun.COM (Marianne Mueller) (01/18/89)
Various people have been recommending things like > Define a union such as: > typedef union > { double d; > unsigned long u[2]; > } dblunion; > to let a programmer access/manipulate bits directly. You might want to make sure that your machine doesn't penalize you on caching. Some machines cache only floating point values, and opt not to cache things that have a union type. (I think it was the compiler that forced main memory loads/stores, not the hardware.) I once thought I was speeding up my program by using union types, but it turned out I slowed it down significantly!
cik@l.cc.purdue.edu (Herman Rubin) (01/18/89)
In article <9404@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes: > In article <1096@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: > >> In article <MAX.89Jan13163256@george.lbl.gov> max@george.lbl.gov (Max Rible) writes: > >> >I'm trying to do deal with floating point numbers as if they're ints. > >< <Things like "if(((3.1 - 3.14) & 0x7FFFFFF) <= 0.1)"--- lousy > >< <programming style, I know, but I'm interested in speed, not > >< <portability for this application. > >I agree that every language should make it easy for the knowledgeable > >programmer to do these things, but I am afraid the movement is in the > >opposite direction. > > I utterly disagree. Generating efficient code for routine floating-point > operations is the job of the compiler, not the high-level programmer. > There is no reason why, if the suggested replacement test represents the > most efficient code for the test, that the compiler should not generate > it in the first place. Clearly the compiler writers and language designers did not think that the operations Max wants to use are routine. I am not even sure that Max thinks they are routine, but he wants to use them. I find myself in this position often, and I have so stated. There are routine operations on both bit patterns and floating-point numbers which are not in many languages; remember the discussion in this group about the power OPERATOR. Also, the particular situation may be highly non-portable. Note that Max has stated that he wants speed, and not necessarily portability. > There are a few cases, such as dealing with IEEE-754 NaNs, where bit > patterns are necessary. C vendors on such systems have, quite properly, > provided the necessary support as macros or functions, so the programmer > still need not concern himself with bit-twiddling. Macros can be so clumsy as to be almost useless. I do not see how to treat a double float in registers as a pair of integers by anything provided in the C language. Function calls can be quite slow, and usually are, and can even take more space than inlining. As I see the application cited, the cost of the procedure inlined is less than the cost of moving the arguments for processing by the function and moving the result back. Max wants to do in one or two instructions what the has not been provided for in the language. As I read Doug's remarks, he feels that this is inappropriate. -- Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907 Phone: (317)494-6054 hrubin@l.cc.purdue.edu (Internet, bitnet, UUCP)
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/19/89)
In article <1100@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: >Max wants to do in one or two instructions what the has not been provided >for in the language. As I read Doug's remarks, he feels that this is >inappropriate. I sure do. The actual test desired is merely some sort of tolerance test. When written in the usual way, a compiler should produce very good code for the test. Resorting to bit-twiddling not only should not produce a noticeable increase in overall program speed, but it will certainly degrade the reliability, portability, and maintainability of the program. As usual, Mr. Rubin maintains that high-level languages like C should allow him to do everything he can do in assembler, and as usual most software engineers I know of would disagree. I don't know how long it would take to port his, or other detailed bit-twiddling code, to a new environment, but I do know how long it takes to port mine (close to zero time). This frees up my time for other things such as working on new applications. I have trouble imagining why that is not an equally important criterion for others. Do they really LIKE to bit twiddle instead of work on new projects?
rjchen@phoenix.Princeton.EDU (Raymond Juimong Chen) (01/19/89)
[as is my wont, I put quoted material at the END.] Harumph. To emphasize that the code is inherently non-portable, why not just code the test in question in assembly language? This would certainly point out to anyone trying to (heaven forbid!) port the code that something amiss is up. (I mean, the code is so blatantly non-portable, one wonders how one could possibly code it in a language which was designed with portability in mind.) There seems to be this great movement to make C the One True Programming Language That Lets You Do Anything You Want. I don't think it is. If you want to get ``under the hood'' and play dirty tricks, then use assembly language. And for those of you who missed last week's episode... Max Rible wants to treat a float as an int-like bit pattern. ``I'm interested in speed, not portability.'' Herman Rubin agrees that ``every language should make it easy for the knowledgeable programmer to do these things.'' Doug Gwyn disagress, maintaining that ``Generating efficient code for routine floating-point operations of the job of the compiler, not the high-level programmer.'' Herman Rubin concedes that ``the particular situation may be highly non- portable. Note that Max has stated that he wants speed, and not necessarily portability.'' -- Raymond Chen UUCP: ...allegra!princeton!{phoenix|pucc}!rjchen BITNET: rjchen@phoenix.UUCP, rjchen@pucc ARPA: rjchen@phoenix.PRINCETON.EDU, rjchen@pucc.PRINCETON.EDU "Say something, please! ('Yes' would be best.)" - The Doctor
bga@bgalli.UUCP (Billy G. Allie) (01/21/89)
In article <5586@phoenix.Princeton.EDU>, rjchen@phoenix.Princeton.EDU (Raymond Juimong Chen) writes: > Harumph. To emphasize that the code is inherently non-portable, why > not just code the test in question in assembly language? This would > certainly point out to anyone trying to (heaven forbid!) port the code > that something amiss is up. I DO NOT LIKE coding in assembly language and will only do so if there is no other way to code it. As for pointing out to anyone that the code is non-portable, what's wrong with: <non-portable construct> /* NON-PORTABLE */ Useful comments are meant to be included in your programs, and a comment stating that a particular construct is non-portable is definately useful. > (I mean, the code is so blatantly non-portable, > one wonders how one could possibly code it in a language which was designed > with portability in mind.) I don't think C was designed for portablility. It was designed to allow a reasonably high level language provide adequate access to the underlining hardware so that WRITING CODE IN ASSEMBLER WOULD NOT BE NECESSARY. The fact that UNIX is written mostly in C says to me that it acheived that goal. I also get the impression that you perceive `portability' as the One True Goal. Portability is a useful goal for programs such as emacs and pcomm, but not for an imbedded real-time control system that needs to have good response times to external events. For such a project, portability can take a flying leap off a high cliff. > There seems to be this great movement to make C the One True Programming > Language That Lets You Do Anything You Want. I don't think it is. > If you want to get ``under the hood'' and play dirty tricks, then > use assembly language. You are right, C is not the 'One True Programming ...'. BUT - it does let me get ``under the hood'' and play `dirty' (I question the use of the word "dirty") tricks. This is the reason I started using C and it is the reason I will continue to use C. ___________________________________________________________________________ ____ Billy G. Allie Internet..: bga@bgalli.eds.com | /| 7436 Hartwell UUCP......: {mcf|edsews}!bgalli!bga |-/-|----- Dearborn, MI 48126 Compuserve: 76337,2061 |/ |LLIE (313) 582-1540 Genie.....: BGALLIE
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/22/89)
In article <284@bgalli.UUCP> bga@bgalli.UUCP (Billy G. Allie) writes: >You are right, C is not the 'One True Programming ...'. BUT - it does let >me get ``under the hood'' and play `dirty' (I question the use of the word >"dirty") tricks. This is the reason I started using C and it is the reason >I will continue to use C. C is good for that, but experience has shown that the vast majority of the time, portable C coding practice suffices, and it has the benefit of reducing the amount of work over the long run. Necessary non-portabilities can virtually always be isolated in a small section of code, with the rest system-independent. Unnecessary non-portabilities are best avoided altogether.