desj@idacrd.UUCP (David desJardins) (10/02/89)
Does anyone have any ideas on how one should go about converting an integer to the floating-point number with the same bit pattern? One frequently (well, occasionally) needs to do this to implement certain bit manipulations efficiently on Cray computers and other vector machines, and possibly on other architectures with fast floating-point but no fast shift (?). The best way I have found to do this in FORTRAN is to write INTEGER I REAL X X = OR (I, 0). (The Cray FORTRAN compiler optimizes out the trivial OR instruction.) It doesn't seem that there is any equally straightforward way to accomplish this in C. I don't want to involve pointers because the whole point is efficiency, and I expect that it will be very difficult for any compiler to optimize out the dereferences in something like int i; float x; * (int *) & x = i; to produce a single register-to-register transfer (or not even that). What I think is probably necessary is to define a real function of one integer argument, returning the same bit pattern as its input. Ultimately I would need to get Cray to incorporate it into their C compiler as an intrinsic function. Does anyone have any experience with such a thing, or a good idea of how these functions should be named? -- David desJardins
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/07/89)
In article <475@idacrd.UUCP> desj@idacrd.UUCP (David desJardins) writes: > Does anyone have any ideas on how one should go about converting an >integer to the floating-point number with the same bit pattern? The simple answer is, you shouldn't need to do that! However, C does provide "union" types that can be used for such purposes. Load the bit pattern into the integer union member and extract it via the floating-point member.
henry@utzoo.uucp (Henry Spencer) (10/08/89)
In article <475@idacrd.UUCP> desj@idacrd.UUCP (David desJardins) writes: > Does anyone have any ideas on how one should go about converting an >integer to the floating-point number with the same bit pattern? ... > It doesn't seem that there is any equally straightforward way to >accomplish this in C. I don't want to involve pointers ... You might try unions. This is one of the things they're good for, albeit in a very implementation-specific way. (Not a problem here, since the operation is inherently implementation-specific.) If your compiler won't put unions into registers, complain to your supplier. -- A bit of tolerance is worth a | Henry Spencer at U of Toronto Zoology megabyte of flaming. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
ok@cs.mu.oz.au (Richard O'Keefe) (10/08/89)
In article <475@idacrd.UUCP>, desj@idacrd.UUCP (David desJardins) writes: > Does anyone have any ideas on how one should go about converting an > integer to the floating-point number with the same bit pattern? union { long i; float x; } pun; pun.i = the_integer_to_be_converted; the_single_precision_result = pun.f; > One frequently (well, occasionally) needs to do this to implement certain > bit manipulations efficiently on Cray computers and other vector machines ... Just which operations are these? If the operations are meaningful functions of floating-point numbers (e.g. things like ilogb() copysign() nextafter()) it might make more sense to ask Cray to put _those_ in their library. I really would like to know what the operations are.
tanner@cdis-1.uucp (Dr. T. Andrews) (10/09/89)
henry@utzoo.uucp (Henry Spencer) writes:
) If your compiler won't put unions into registers, complain to
) your supplier.
Done, long ago. Our internal reference shows it as our item
"pfc155.c" of 15-Jan-87, vendor's reference number 0380101.
The vendor's comment? He said that they don't have to put unions
in registers because "register" is just a hint, and they're free to
do whatever they want to.
--
Cutting half of passenger service | {bpa,uunet}!cdin-1!cdis-1!tanner
Mulroney: "cold froze our brains" | {attctc gatech!uflorida}!ki4pv!cdis-1!tanner
bright@Data-IO.COM (Walter Bright) (10/10/89)
In article <475@idacrd.UUCP> desj@idacrd.UUCP (David desJardins) writes:
< Does anyone have any ideas on how one should go about converting an
<integer to the floating-point number with the same bit pattern?
Try a union:
union blah { int i; float f; } x;
x.f = f;
/* now manipulate x.i */
< It doesn't seem that there is any equally straightforward way to
<accomplish this in C. I don't want to involve pointers because the
<whole point is efficiency, and I expect that it will be very difficult
<for any compiler to optimize out the dereferences in something like
< int i;
< float x;
< * (int *) & x = i;
<to produce a single register-to-register transfer (or not even that).
Not at all. It's a pretty much standard and trivial optimization to
convert *(int*)&x=i into MOV X,I. Feel free to use it, with the caveat
that float format is not the same from machine to machine. I've done
it many times to do special manipulations on doubles.
cik@l.cc.purdue.edu (Herman Rubin) (10/10/89)
In article <2165@dataio.Data-IO.COM>, bright@Data-IO.COM (Walter Bright) writes: > In article <475@idacrd.UUCP> desj@idacrd.UUCP (David desJardins) writes: | < Does anyone have any ideas on how one should go about converting an | <integer to the floating-point number with the same bit pattern? > > Try a union: > union blah { int i; float f; } x; > x.f = f; > /* now manipulate x.i */ ....................... | < int i; | < float x; | < * (int *) & x = i; | <to produce a single register-to-register transfer (or not even that). > > Not at all. It's a pretty much standard and trivial optimization to > convert *(int*)&x=i into MOV X,I. Feel free to use it, with the caveat > that float format is not the same from machine to machine. I've done > it many times to do special manipulations on doubles. This may or may not work. It is likely that the "&" by itself will force x to memory. But event if a #define is used to eliminate that, al least on may compilers the MOV X,I or equivalent will not work. Reluctantly, I would have to say that it might be necessary to put in a kludge and then edit the .s files, which is what I find myself forced to do in these situations. -- Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907 Phone: (317)494-6054 hrubin@l.cc.purdue.edu (Internet, bitnet, UUCP)
lhf@aries5.uucp (Luiz H de Figueiredo) (10/10/89)
In article <11242@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: > >However, C does provide "union" types that can be used for such purposes. >Load the bit pattern into the integer union member and extract it via the >floating-point member. Provided both members have the same size! Otherwise, try union { float f; unsigned char b[sizeof(float)]; }; ------------------------------------------------------------------------------- Luiz Henrique de Figueiredo internet: lhf@aries5.uwaterloo.ca Computer Systems Group bitnet: lhf@watcsg.bitnet University of Waterloo ------------------------------------------------------------------------------- eof
jerry@violet.berkeley.edu ( Jerry Berkman ) (10/11/89)
In article <475@idacrd.UUCP> desj@idacrd.UUCP (David desJardins) writes: > Does anyone have any ideas on how one should go about converting an >integer to the floating-point number with the same bit pattern? >The best way I have found to do this in FORTRAN is to write > INTEGER I > REAL X > X = OR (I, 0). >(The Cray FORTRAN compiler optimizes out the trivial OR instruction.) > -- David desJardins Why not use equivalence? INTEGER I REAL X, IX EQUIVALENCE (X,IX) IX = I The Fortran standard specifies that a REAL and INTEGER occupy the same space. The only problem is this might fool some optimizers. - Jerry Berkman jerry@violet.berkeley.edu
slimer@trsvax.UUCP (10/11/89)
In article <475@idacrd.UUCP>, desj@idacrd.UUCP (David desJardins) writes: > the_single_precision_result = pun.f; According to the pun union structure, this should actually read: the_single_precision_result = pun.x; **************************************************************************** * Thank You, texbell!letni!rwsys!slimer * * Bill "Ever felt like a dip switch?" - ComputerWorld * * George W. Pogue, 1300 Two Tandy, Fort Worth, TX. 76102 (817) 390-2871 * ****************************************************************************
diamond@csl.sony.co.jp (Norman Diamond) (10/11/89)
In article <475@idacrd.UUCP> desj@idacrd.UUCP (David desJardins) writes: > Does anyone have any ideas on how one should go about converting an >integer to the floating-point number with the same bit pattern? >The best way I have found to do this in FORTRAN is to write > INTEGER I > REAL X > X = OR (I, 0). >(The Cray FORTRAN compiler optimizes out the trivial OR instruction.) Looks like the Cray Fortran compiler has a bug. The result of OR(I,0) should be an integer, and the conversion from integer to floating (across the assignment) should usually have a different bit pattern. >I don't want to involve pointers > int i; > float x; > * (int *) & x = i; This would look a little bit better as x = * (float *) & i; although the effect is the same. In fact with an optimizing compiler this should not be an efficiency problem. The problem comes about if you DECLARE register float x; because it's illegal to apply the "&" operator to a register operand. If your variables are auto but the optimizer is USING registers, it will generally figure out register-to-register transfers. On the other hand, how many hardware architectures have instructions to transfer directly between integer registers and floating registers? Usually you have to store it to RAM and load it back anyway. Another solution is to use unions union { int i; float x; } converter; converter.i = i; x = converter.x; but most compilers will not put converter in a register for you. This time you could try it yourself, "register union ....." because you aren't applying "&" to it, but I cannot imagine a compiler obeying your "register" request. Again, how many architectures put integers and floats in the same register? -- Norman Diamond, Sony Corp. (diamond%ws.sony.junet@uunet.uu.net seems to work) The above opinions are inherited by your machine's init process (pid 1), after being disowned and orphaned. However, if you see this at Waterloo or Anterior, then their administrators must have approved of these opinions. Newsgroups: comp.lang.c,comp.sys.super Subject: Re: Type punning in C Summary: Expires: References: <475@idacrd.UUCP> Sender: Reply-To: diamond@riks. (Norman Diamond) Followup-To: Distribution: Organization: Sony Computer Science Laboratory Inc., Tokyo, Japan Keywords: In article <475@idacrd.UUCP> desj@idacrd.UUCP (David desJardins) writes: > Does anyone have any ideas on how one should go about converting an >integer to the floating-point number with the same bit pattern? >The best way I have found to do this in FORTRAN is to write > INTEGER I > REAL X > X = OR (I, 0). >(The Cray FORTRAN compiler optimizes out the trivial OR instruction.) Looks like the Cray Fortran compiler has a bug. The result of OR(I,0) should be an integer, and the conversion from integer to floating (across the assignment) should usually have a different bit pattern. >I don't want to involve pointers > int i; > float x; > * (int *) & x = i; This would look a little bit better as x = * (float *) & i; although the effect is the same. In fact with an optimizing compiler this should not be an efficiency problem. The problem comes about if you DECLARE register float x; because it's illegal to apply the "&" operator to a register operand. If your variables are auto but the optimizer is USING registers, it will generally figure out register-to-register transfers. On the other hand, how many hardware architectures have instructions to transfer directly between integer registers and floating registers? Usually you have to store it to RAM and load it back anyway. Another solution is to use unions union { int i; float x; } converter; converter.i = i; x = converter.x; but most compilers will not put converter in a register for you. This time you could try it yourself, "register union ....." because you aren't applying "&" to it, but I cannot imagine a compiler obeying your "register" request. Again, how many architectures put integers and floats in the same register? -- Norman Diamond, Sony Corp. (diamond%ws.sony.junet@uunet.uu.net seems to work) The above opinions are inherited by your machine's init process (pid 1), after being disowned and orphaned. However, if you see this at Waterloo or Anterior, then their administrators must have approved of these opinions.
ok@cs.mu.oz.au (Richard O'Keefe) (10/11/89)
In article <1989Oct10.185851.6490@agate.berkeley.edu>, jerry@violet.berkeley.edu ( Jerry Berkman ) writes: : In article <475@idacrd.UUCP> desj@idacrd.UUCP (David desJardins) writes: : > Does anyone have any ideas on how one should go about converting an : >integer to the floating-point number with the same bit pattern? : Why not use equivalence? : INTEGER I : REAL X, IX : EQUIVALENCE (X,IX) Because he was asking how to do it in C. I understand that the original problem was something that could be expressed quite clearly and simply as an ordinary C arithmetic expression operating exclusively on integers, and that straightforward C code would _work_ on the Cray, but because some operation (bitwise shifts?) didn't have a vector equivalent it wouldn't vectorise. But a hairy hack involving floats _would_ vectorise because the Cray system is good at vectorising float operations. The interesting point here is that there are a lot of things you can do IF you have the functions required and recommended in the IEEE 754 standard. For example, if there is some reason why you want to avoid p << i use (int) scalb((float)p, i) p >> j use (int) scalb((float)p, -j) This is why I think that it would be interesting for people with such problems (and this includes Herman Rubin) to give us more detail about the problem they are really trying to solve (e.g. the original poster's problem was "how do I get results equal to these in a way that will vectorise on a Cray?"). It may be that some of these problems have solutions which are less machine-specific than hand-crafted bit-twiddling, or would be if functional equivalents of the IEEE functions were provided.
exspes@gdr.bath.ac.uk (P E Smee) (10/11/89)
In article <1989Oct10.185851.6490@agate.berkeley.edu> jerry@violet.berkeley.edu ( Jerry Berkman ) writes: > >Why not use equivalence? > INTEGER I > REAL X, IX > EQUIVALENCE (X,IX) > > IX = I >The Fortran standard specifies that a REAL and INTEGER occupy the same space. >The only problem is this might fool some optimizers. > Problem is, the Fortran standard *also* says that if your program tries to take the value of the variable using a different type than the type you used when you last stored into it, your program is invalid. This is a polite way of saying (to the user) 'this trick may not work', and (to the compiler writer) 'your optimizer does not have to worry about aliasing between variables of different types'. If the compiler can tell that you are going to (e.g.) store an integer into that storage, and then read a real, it is under no obligation to make sure that the integer value gets stored. Fortran equivalence was designed toallow reuse of storage on the early small memory machines -- not to allow type punning. Usually you can get away with punning, but it doesn't always work and so is a bad habit. -- Paul Smee | JANET: Smee@uk.ac.bristol Computer Centre | BITNET: Smee%uk.ac.bristol@ukacrl.bitnet University of Bristol | Internet: Smee%uk.ac.bristol@nsfnet-relay.ac.uk (Phone: +44 272 303132) | UUCP: ...!mcvax!ukc!gdr.bath.ac.uk!exspes
cik@l.cc.purdue.edu (Herman Rubin) (10/12/89)
In article <1989Oct11.091619.18336@gdt.bath.ac.uk>, exspes@gdr.bath.ac.uk (P E Smee) writes: > In article <1989Oct10.185851.6490@agate.berkeley.edu> jerry@violet.berkeley.edu ( Jerry Berkman ) writes: < > < >Why not use equivalence? < > INTEGER I < > REAL X, IX < > EQUIVALENCE (X,IX) < > < > IX = I < >The Fortran standard specifies that a REAL and INTEGER occupy the same space. < >The only problem is this might fool some optimizers. < > > Problem is, the Fortran standard *also* says that if your program tries > to take the value of the variable using a different type than the type you > used when you last stored into it, your program is invalid. This is a > polite way of saying (to the user) 'this trick may not work', and (to the > compiler writer) 'your optimizer does not have to worry about aliasing > between variables of different types'. If the compiler can tell that > you are going to (e.g.) store an integer into that storage, and then > read a real, it is under no obligation to make sure that the integer > value gets stored. > > Fortran equivalence was designed toallow reuse of storage on the early > small memory machines -- not to allow type punning. Usually you can > get away with punning, but it doesn't always work and so is a bad habit. This is another example of those "gurus" who can not envision an intelligent user using the machine in an intelligent manner, and prevent that use. I have deliberately used "type punning" on various machines, and I consider it an extremely useful tool. Now, I do not mind the compiler asking me if I really wanted to do it, but I object to anyone telling me that I CAN NOT use instructions that do what I want to do. It should not even bother an optimizer. The optimizer takes the operations given by the programmer, in some cases applies transformations known to provide the same result, and optimizes the order. Why should an integer and a floating point number in the same location bother it, unless that location is a register and the (expletives deleted) hardware has different integer and floating registers? But even that should not befuddle the optimizer. > -- > Paul Smee | JANET: Smee@uk.ac.bristol > Computer Centre | BITNET: Smee%uk.ac.bristol@ukacrl.bitnet > University of Bristol | Internet: Smee%uk.ac.bristol@nsfnet-relay.ac.uk > (Phone: +44 272 303132) | UUCP: ...!mcvax!ukc!gdr.bath.ac.uk!exspes -- Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907 Phone: (317)494-6054 hrubin@l.cc.purdue.edu (Internet, bitnet, UUCP)
mac@harris.cis.ksu.edu (Myron A. Calhoun) (10/12/89)
In article <1654@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: >In article <1989Oct11.091619.18336@gdt.bath.ac.uk>, exspes@gdr.bath.ac.uk (P E Smee) writes: >> In article <1989Oct10.185851.6490@agate.berkeley.edu> jerry@violet.berkeley.edu ( Jerry Berkman ) writes: >< >Why not use equivalence? [several lines deleted] >> Problem is, the Fortran standard *also* says that if your program tries... [several lines deleted] >This is another example of those "gurus" who can not envision an intelligent >user using the machine in an intelligent manner, and prevent that use. I >have deliberately used "type punning" on various machines, and I consider it >an extremely useful tool..... [several lines deleted] I agree wholeheartedly. FORTRAN doesn't have PL/1's UNSPEC verb, yet I have had occasion to want it. And EQUIVALENCE provided it. Calling a subroutine with "wrong" type parameters can also work: CALL NEWTYP (INTEGER,...) ::::: SUBROUTINE NEWTYP (REAL,...) --Myron -- Myron A. Calhoun, PhD EE, W0PBV, (913) 532-6350 (work), 539-4448 (home). INTERNET: mac@ksuvax1.cis.ksu.edu BITNET: mac@ksuvax1.bitnet UUCP: ...{rutgers, texbell}!ksuvax1!harry!mac
dik@cwi.nl (Dik T. Winter) (10/13/89)
(You could read the parent twice; I did not include it twice.) In article <10950@riks.csl.sony.co.jp> diamond@ws.sony.junet (Norman Diamond) writes: > In article <475@idacrd.UUCP> desj@idacrd.UUCP (David desJardins) writes: > > > X = OR (I, 0). > >(The Cray FORTRAN compiler optimizes out the trivial OR instruction.) > > Looks like the Cray Fortran compiler has a bug. The result of OR(I,0) > should be an integer, This ought to be in comp.lang.fortran; but nevertheless: no Mr Diamond. OR is not a standard (generic) function in Fortran so Cray may play all games with it (and defines it as typeless). -- dik t. winter, cwi, amsterdam, nederland INTERNET : dik@cwi.nl BITNET/EARN: dik@mcvax
khb%chiba@Sun.COM (Keith Bierman - SPD Advanced Languages) (10/13/89)
In article <1989Oct11.091619.18336@gdt.bath.ac.uk> exspes@gdr.bath.ac.uk (P E Smee) writes: >Problem is, the Fortran standard *also* says that if your program tries >to take the value of the variable using a different type than the type you >used when you last stored into it, your program is invalid. This is a >polite way of saying (to the user) 'this trick may not work', and (to >the My quick peek into the document (pages 8-3 and 17-1..4ish) doesn't make this obvious to me. Could you please quote chapter and verse ? > >Fortran equivalence was designed toallow reuse of storage on the early >small memory machines -- not to allow type punning. Usually you can >get away with punning, but it doesn't always work and so is a bad habit. > On which systems (if any) have you seen this not work ? Keith H. Bierman |*My thoughts are my own. !! kbierman@sun.com It's Not My Fault | MTS --Only my work belongs to Sun* I Voted for Bill & | Advanced Languages/Floating Point Group Opus | "When the going gets Weird .. the Weird turn PRO"
ok@cs.mu.oz.au (Richard O'Keefe) (10/13/89)
In article <4055@deimos.cis.ksu.edu>, mac@harris.cis.ksu.edu (Myron A. Calhoun) writes: : In article <1654@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: : >This is another example of those "gurus" who can not envision an intelligent : >user using the machine in an intelligent manner, and prevent that use. I : >have deliberately used "type punning" on various machines, and I consider it : >an extremely useful tool..... : I agree wholeheartedly. FORTRAN doesn't have PL/1's UNSPEC verb, yet : I have had occasion to want it. And EQUIVALENCE provided it. : Calling a subroutine with "wrong" type parameters can also work: : CALL NEWTYP (INTEGER,...) : ::::: : SUBROUTINE NEWTYP (REAL,...) I shall try to tell you what the point is in words that have but one sound in them. Those who write books that say what a tool like C means want to help you make tools that can be used on more than one box. I shall say it one more time: "that can be used on more than one box". A type pun is all but sure to work on at most one box. This means that those who write books that say what a tool like C means MUST tell you not to trust type puns. This does not mean that type puns will not work on your box. It just means that those who write books that say what a tool like C means had to tell you that it might not work. They could not rule that the same pun must work on each box, since they do not tell those who make each box what to do. Nor do they tell YOU what to do, just what you can TRUST. If a type pun works on your box, use it, but keep in mind that it may not work on aught else. [PS: UNSPEC is not a "verb" in PL/I, it is a "pseudo-function", and it is very far from being portable. It's a _major_ pain when trying to port PL/I programs. ]
exspes@gdr.bath.ac.uk (P E Smee) (10/13/89)
In article <1654@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: >In article <1989Oct11.091619.18336@gdt.bath.ac.uk>, exspes@gdr.bath.ac.uk (P E Smee) writes: >> In article <1989Oct10.185851.6490@agate.berkeley.edu> jerry@violet.berkeley.edu ( Jerry Berkman ) writes: >< > >< >Why not use equivalence? >< > INTEGER I >< > REAL X, IX >< > EQUIVALENCE (X,IX) >< > >< >The Fortran standard specifies that a REAL and INTEGER occupy the same space. >> Fortran equivalence was designed toallow reuse of storage on the early >> small memory machines -- not to allow type punning. Usually you can >> get away with punning, but it doesn't always work and so is a bad habit. > >This is another example of those "gurus" who can not envision an intelligent >user using the machine in an intelligent manner, and prevent that use. I >have deliberately used "type punning" on various machines, and I consider it >an extremely useful tool. Now, I do not mind the compiler asking me if I >really wanted to do it, but I object to anyone telling me that I CAN NOT >use instructions that do what I want to do. Trust me, 'cause I don't want to get into a long discussion of FORTRAN in a C newsgroup. There are an incredible number of things which may cause aliasing in FORTRAN, some of it invisible to the compiler at any given moment due to separate compilation of modules, and so the optimizer needs all the help it can get. '77 FORTRAN is even more restrictive on the user as regards possible punning and aliasing than '66 FORTRAN was, in order primarily to permit more reliable optimization. The need for a construct to permit type punning is clear, particularly if you're doing 'systemmy' work. People working on the Algol compiler on Multics (which does even more stringent, and cross-module, type checking) resorted to writing little PL/1 routines which simply took whatever they were given and passed it straight back, unchanged(bitwise) -- and declared them in the Algol code as 'foreign' ('other language module, suspend type checking') 'takes integer returns real'. Lies, in other words. I tend to like things which match PL/1's 'unspec' in concept. This provides an explicit instruction to the compiler, and (more importantly) a warning to future maintainers of the code, that you are about to willfully, knowledgeably, and intentionally, cheat the data typing and conversion rules. Every serious language should have such a thing. (Unfortunately, it seems that most don't, sigh...) -- Paul Smee | JANET: Smee@uk.ac.bristol Computer Centre | BITNET: Smee%uk.ac.bristol@ukacrl.bitnet University of Bristol | Internet: Smee%uk.ac.bristol@nsfnet-relay.ac.uk (Phone: +44 272 303132) | UUCP: ...!mcvax!ukc!gdr.bath.ac.uk!exspes
cik@l.cc.purdue.edu (Herman Rubin) (10/13/89)
In article <10950@riks.csl.sony.co.jp>, diamond@csl.sony.co.jp (Norman Diamond) writes: ............................ > On the other hand, how many hardware architectures have instructions > to transfer directly between integer registers and floating registers? > Usually you have to store it to RAM and load it back anyway. ............................ Most of the machines I am familiar with either have registers which can be used for integer or floating point arguments. Some of them have an index type (shorter integer) but those can convert between short integer and long.. These machines include VAX, PYRAMID, CDC 6x00 and descendents, CRAY, CYBER 205 and ETA 10, and even vector mode on the IBM 3090. -- Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907 Phone: (317)494-6054 hrubin@l.cc.purdue.edu (Internet, bitnet, UUCP)
6sigma@polari.UUCP (Brian Matthews) (10/14/89)
In article <7675@cdis-1.uucp> tanner@cdis-1.uucp (Dr. T. Andrews) writes: |henry@utzoo.uucp (Henry Spencer) writes: |) If your compiler won't put unions into registers, complain to |) your supplier. |Done, long ago. [...] The vendor's comment? He said that they don't have |to put unions in registers because "register" is just a hint, and they're |free to do whatever they want to. To which your response should be, "I'm free to do what I want also, and now I'm going to find a new vendor." -- Brian L. Matthews blm@6sigma.UUCP
exspes@gdr.bath.ac.uk (P E Smee) (10/16/89)
In article <126279@sun.Eng.Sun.COM> khb@sun.UUCP (Keith Bierman - SPD Advanced Languages) writes: >In article <1989Oct11.091619.18336@gdt.bath.ac.uk> exspes@gdr.bath.ac.uk (P E Smee) writes: > > >>Problem is, the Fortran standard *also* says that if your program tries >>to take the value of the variable using a different type than the type you >>used when you last stored into it, your program is invalid. > >My quick peek into the document (pages 8-3 and 17-1..4ish) doesn't >make this obvious to me. Could you please quote chapter and verse ? > Section 17.3(2) -- (or, page 17.4, lines 15-18) 'When an entity of a given type becomes defined, all totally associated entities of different type become undefined.' With 17.2(1) 'Execution of an arithmetic, logical, or character assignment statement causes the entity that precedes the equals to become defined. These must, of course, be taken in conjunction with the definition of what it means for something to be defined, and with the fact that if your program uses variables while they are undefined, your program is invalid. From 17.1 it is clear that EQUIVALENCE may cause total association. May also cause only partial association depending on what the equivalanced entities are. In particular, from 17.1.1 single (non-array) integer, real, and logical values equivalenced in any mix are totally associated. >> >>Fortran equivalence was designed toallow reuse of storage on the early >>small memory machines -- not to allow type punning. Usually you can >>get away with punning, but it doesn't always work and so is a bad habit. >> > >On which systems (if any) have you seen this not work ? > Honeywell Multics at certain optimisation levels. Of course, since HIS don't make them any more, that's a moot point. I believe I recall similar occasional problems under various flavours of IBM OSes, again at particular optimisation levels. Doesn't alter the fact that since the standard makes it clear that it can be invalid, it's a bad habit. -- Paul Smee | JANET: Smee@uk.ac.bristol Computer Centre | BITNET: Smee%uk.ac.bristol@ukacrl.bitnet University of Bristol | Internet: Smee%uk.ac.bristol@nsfnet-relay.ac.uk (Phone: +44 272 303132) | UUCP: ...!mcvax!ukc!gdr.bath.ac.uk!exspes
exspes@gdr.bath.ac.uk (P E Smee) (10/16/89)
In article <1989Oct16.092936.142@gdt.bath.ac.uk> exspes@gdr.bath.ac.uk (P E Smee) writes: >In article <126279@sun.Eng.Sun.COM> khb@sun.UUCP (Keith Bierman - SPD Advanced Languages) writes: >>In article <1989Oct11.091619.18336@gdt.bath.ac.uk> exspes@gdr.bath.ac.uk (P E Smee) writes: >> >> >>>Problem is, the Fortran standard *also* says that if your program tries >>>to take the value of the variable using a different type than the type you >>>used when you last stored into it, your program is invalid. >> >>My quick peek into the document (pages 8-3 and 17-1..4ish) doesn't >>make this obvious to me. Could you please quote chapter and verse ? >> In the previous posting, I quoted chapter and verse from the 77 FORTRAN standard. The 66 standard is even stricter. EQUIVALENCE causes things to become associated (full stop -- no fudging about partial or total association) and says in 10.2.3.1 (5) [Variables and array elements become undefined as follows:] When an associated entry of different type becomes defined. So, I'd say the 66 standard prohibits it completely, while the 77 standard allows it in some cases (but only when the variables are not (loosely speaking) of the same size). The one interesting case which is explicitly valid in 77 appears to be EQUIVALENCE of a REAL array of dimension 2 with an COMPLEX variable, in which case REAL(1) would be the real part of the COMPLEX and REAL(2) the imaginary part. -- Paul Smee | JANET: Smee@uk.ac.bristol Computer Centre | BITNET: Smee%uk.ac.bristol@ukacrl.bitnet University of Bristol | Internet: Smee%uk.ac.bristol@nsfnet-relay.ac.uk (Phone: +44 272 303132) | UUCP: ...!mcvax!ukc!gdr.bath.ac.uk!exspes
evil@arcturus.UUCP (Wade Guthrie) (10/19/89)
>In article <11242@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: However, C does provide "union" types that can be used for such purposes. Load the bit pattern into the integer union member and extract it via the floating-point member. lhf@aries5.uucp (Luiz H de Figueiredo) writes: Provided both members have the same size! Otherwise, try union { float f; unsigned char b[sizeof(float)]; }; I thought that the standard said (as opposed to what I remember reading in K&R I) that members of unions do NOT have to have zero offset? In this case, none of the above work (and, BTW, breaks a lot of existing code). Do I completely misunderstand what the standard said, or is the stuff above just not portable to ANSI conformant compilers (God, I didn't mean for that to sound as snotty as it did -- please take that as a neophyte asking an innocent question). Wade Guthrie evil@arcturus.UUCP Rockwell International Anaheim, CA (Rockwell doesn't necessarily believe / stand by what I'm saying; how could they when *I* don't even know what I'm talking about???)
karl@haddock.ima.isc.com (Karl Heuer) (10/21/89)
In article <6310@arcturus> evil@arcturus.UUCP (Wade Guthrie) writes: >I thought that the standard said (as opposed to what I remember reading >in K&R I) that members of unions do NOT have to have zero offset? The pANS guarantees that a pointer to a union, suitably cast, points to each of its members, and vice versa. It also says that the behavior is undefined if you use a union for punning. (What else could it say? You can't close your eyes and pretend that the behavior is predictable!) Since you already know your program isn't portable, you needn't worry about this. It may be that the undefined-behavior clause would permit an implementation where punning doesn't work and differently-typed union members don't overlap, provided that appropriate code is generated when casting to/from a union type. This may be the source of the rumor you heard. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
kremer@cs.odu.edu (Lloyd Kremer) (10/21/89)
In article <11242@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: > > However, C does provide "union" types that can be used for such > purposes. Load the bit pattern into the integer union member > and extract it via the floating-point member. Another way would be to back off one level of indirection, and transfer the bit pattern by means of pointers to the respective objects. Example: float f; int i; /* assign f */ i = *(int *)&f; /* transfer bit pattern from f to i */ -- Lloyd Kremer ...!uunet!xanth!kremer Have terminal...will hack!
bill@twwells.com (T. William Wells) (10/24/89)
In article <14939@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes:
: It may be that the undefined-behavior clause would permit an implementation
: where punning doesn't work and differently-typed union members don't overlap,
: provided that appropriate code is generated when casting to/from a union type.
: This may be the source of the rumor you heard.
Actually, the standard is quite unambiguous in asserting that the
members of a union overlap. But it doesn't say beans about by how
much.
---
Bill { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com
thorinn@skinfaxe.diku.dk (Lars Henrik Mathiesen) (10/27/89)
bill@twwells.com (T. William Wells) writes: <In article
<14939@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer)
<writes:
<: It may be that the undefined-behavior clause would permit an
<: implementation where punning doesn't work and differently-typed union
<: members don't overlap, provided that appropriate code is generated
<: when casting to/from a union type. This may be the source of the
<: rumor you heard.
<Actually, the standard is quite unambiguous in asserting that the
<members of a union overlap. But it doesn't say beans about by how
<much.
If this is meant in the sense that inverting all the bits of one union
member is guaranteed to invert at least one bit of every other member,
then I think that the committee has overconstrained the language a
bit. As discussed before in the context of capability machines,
objects of pointer type may want to live in another address space than
objects of basic type.
Another reason to make union members start at an offset would be to
allow objects (e.g., chars) which are smaller than a machine word to
be placed in the same position in a memory word as in a register; in a
big-endian architecture that position will not have the same byte
address as the containing word.
A compiler optimizing for fast-but-space-consuming code might want to
do this for all ``small'' structure members; however, the standard
forbids holes at the start of structures. This means that given
struct s { signed char c, int i} s;
union u { signed char c, int i} u;
void *p;
these are guaranteed to hold:
(1) &s.c == (signed char *)(void *)&s;
(1') &((struct s *)p)->c == (signed char *)p;
(2) &u.c == (signed char *)(union u *)&u.i;
whereas the compiler is free to put u.c at an offset so that
(3) &u.c != (signed char *)(void *)&u.i;
The difference between (2) and (3) is that the standard demands that
the compiler can cast between pointer-to-union and pointer-to-member
(even if there's an offset). The difference between (1) and (3) is
that the standard forces s.c to be at offset zero.
Note that even if the no-initial-hole constraint were lifted,
(4) &s.c == (signed char *)&s;
(4') &((struct s *)p)->c == (signed char *)(struct s *)p;
could still be guaranteed (with some work from the compiler _if_
initial holes were used). The relevant sentences (in the May 88 draft)
go: ``A pointer to a structure object, suitably cast, points to its
initial member (or if that member is a bit-field, then to the unit in
which it resides), and vice versa. There may _therefore_ be unnamed
holes within a structure, but not at its beginning, as necessary to
achieve the appropriate alignment.'' (My emphasis). It seems to me
that the no-initial-hole rule is a conclusion rather than a deliberate
decision.
Therefore I wonder which, if any, of the following it was that the
Committee intended:
a) ``Suitably cast'' does not involve changing the byte
address of a pointer, only its type; in other words, an intermediate
void pointer can validly be used. [In this case, all union members
have to start at the same byte address too, as the language used for
unions is similar in regard to the casting although the no-hole rule
is not explicit stated.]
b) There is so much code out there which does not explicitly
cast structure pointers (when used as function arguments, for example)
that this guarantee must be given; however, that is not the case for
union pointers[?!].
c) When a union type has several members with structure type,
and each of those structures have an initial member with the same
common type, it should be possible to use those initial members
interchangeably. [This would be very useful for discriminated unions,
however, the comment about unions from a) above must apply here too
for that to work.]
d) RISCs are fast enough already, let's not allow them to
optimize too much [:-)].
In my opinion, only c) above is totally acceptable, and if that was
the reason, it might have been formulated more directly. Anyway, if I
ever get my hands on a current Draft (or even Standard), Rationale,
Response and Interpretations document, and they don't cover this
better, I may cook up a Request for Interpretation (or whatever the
term is).
--
Lars Mathiesen, DIKU, U of Copenhagen, Denmark [uunet!]mcvax!diku!thorinn
Institute of Datalogy -- we're scientists, not engineers. thorinn@diku.dk