[comp.unix.wizards] casting to float without converting to float?

weiser.pa@Xerox.COM (01/08/88)

I have the following problem:  I have a value which I happen to know has the
proper bits to represent a floating point number (either 32 or 64).  However, it
is of type int.  I would now like to tell the C compiler to treat this thing as
a float.  How can I do it without taking the address of the thing (which may not
have an address because it is in a register or is an expression) or using a
subroutine call (for which I do not wish to pay the cost)?

(If I could take an address, then the solution is: *(float *)foo).)

(Needless to say, the following does NOT work: (float)foo, because it actually
does a conversion of the integer foo into a float.  I don't want a conversion,
but rather I want the compiler to just trust me that I am handing it bits that
it should consider to be a float.)

Thanks for any help.  Currently I'm working around the problem by using
assembler in-lines as supported by Sun, but I'd like a less vendor independent
method. 

-mark

bzs%bu-cs.bu.edu@bu-it.BU.EDU (Barry Shein) (01/08/88)

The attached program seems to work. Whether or not it ends up in a
register seems to be compiler dependant but I had no complaints about
the syntax and it always produced the expected results.

On the Sun it ends up in a register when compiled with a -O flag but
not if not. On an Encore/Multimax (Greenhill's C) and Vax (4.3bsd) it
never ends up in a register. I couldn't really tell on the Celerity
but I think it ends up in a register both optimized and unoptimized (I
had trouble reading the machine code, not their fault, mostly I was
too lazy to try to follow it carefully.) The optimizer for PCC on the
3090 (IBM370) is not available but it ended up in a register
unoptimized.

I'll leave it to the language lawyers as to whether or not it *should*
have worked.

	-Barry Shein, Boston University

#include <stdio.h>
/*
 * Bit patterns for 23.7 on various machines
 */
#define SUN 1
#if SUN | UMAX | CELERITY
#define TWENTYTHREEPTSEVEN 0x41bd999a
#endif
#if IBM370
#define TWENTYTHREEPTSEVEN 0x4217b333
#endif
#if VAX
#define TWENTYTHREEPTSEVEN 0x999a42bd
#endif

main()
{
  register union foo {
    int a;
    float b;
  } x;
  float z;

  x.a = TWENTYTHREEPTSEVEN;	/* bit pattern for 23.7 float */
  z = x.b; 
  printf("%f\n",z);
}

weiser.pa@Xerox.COM (01/08/88)

Sigh.  I must not have made myself sufficiently clear.  Before I get any more
responses to my converting-to-float request, please note that I need to convert
an EXPRESSION.  The UNION  examples don't help.

-mark

alex@umbc3.UMD.EDU (Alex S. Crain) (01/08/88)

In article <11171@brl-adm.ARPA> weiser.pa@Xerox.COM writes:
>I have the following problem:  I have a value which I happen to know has the
>proper bits to represent a floating point number (either 32 or 64).  However, it
>is of type int.  I would now like to tell the C compiler to treat this thing as
>a float. 

union { float f; int i; } foo;

foo.i = int value
foo.f = float value

-- 
					:alex.

alex@umbc3.umd.edu

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/08/88)

In article <11171@brl-adm.ARPA> weiser.pa@Xerox.COM writes:
>I would now like to tell the C compiler to treat this thing as a float.

C questions should go to comp.lang.c (INFO-C).

Try (*(union{int i;float f;})integer).f
which should work but probably will give your compiler indigestion.

If that doesn't work, store it into such a union's integer member
then extract the float member of the union:
	union {int i; float f} u;
	u.i = integer;
	expression( u.f );

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/08/88)

In article <11175@brl-adm.ARPA> weiser.pa@Xerox.COM writes:
>Sigh.  I must not have made myself sufficiently clear.  Before I get any more
>responses to my converting-to-float request, please note that I need to convert
>an EXPRESSION.  The UNION  examples don't help.

There is no such thing as "converting an expression".  Presumably
you want to convert the integer result of evaluating some expression
to the equivalent float.  Union is just the ticket for this; in fact
there doesn't seem to be any other way to do this.

cik@l.cc.purdue.edu (Herman Rubin) (01/08/88)

In general, you cannot change the type of a quantity (unfortunately).  
It may be that the problem can be avoided by using a cast when reading
or writing the quantity, if the appropriate array is used.  The 4.3 BSD
VAX math library uses casts and #defines to set up the constants for
the elementary functions.  Otherwise your solution to use inline
assembler statements is the only thing I have found to work, and the
various gurus I have consulted have not come up with anything better.

-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet

roy@phri.UUCP (Roy Smith) (01/09/88)

[This really doesn't belong on unix.wizards; I've moved it to comp.lang.c]

In article <11171@brl-adm.ARPA> weiser.pa@Xerox.COM writes:
> I have a value which I happen to know has the proper bits to represent
> a floating point number (either 32 or 64).  However, it is of type int.
> I would now like to tell the C compiler to treat this thing as a float.

	I think what you want to do is declare a union which has both int
and float elements and use whever you prefer whenever you want.  For
example, the following program (compiled on a Sun-3, under SunOS-3.2) does
what you want.  Lint doesn't even complain (except about ignoring the value
printf returns).  Before you do this, however, be aware that this is not
exactly what I would call portable code (although, as long as sizeof(int)
>= sizeof(float), I don't see why it shouldn't work anywhere).  Better than
assembler in-lines, at any rate.

main ()
{
	union {int i; float f;} x1, x2;
	int i;
	float f1, f2;

	f1 = 3.0;
	x1.f = f1;
	i = x1.i;	/* i now has bit pattern for 3.0e0 */
	printf ("%d\n", i);

	x2.i = i;
	f2 = x2.f;
	printf ("%f\n", f2);
}

alanine% cc test.c
alanine% a.out
1077936128
3.000000
-- 
Roy Smith, {allegra,cmcl2,philabs}!phri!roy
System Administrator, Public Health Research Institute
455 First Avenue, New York, NY 10016

jbuck@epimass.EPI.COM (Joe Buck) (01/09/88)

In article <11171@brl-adm.ARPA> weiser.pa@Xerox.COM writes:
>I have the following problem:  I have a value which I happen to know
>has the proper bits to represent a floating point number (either 32
>or 64).  However, it is of type int.  I would now like to tell the C
>compiler to treat this thing as a float.  How can I do it without
>taking the address of the thing (which may not have an address
>because it is in a register or is an expression) or using a
>subroutine call (for which I do not wish to pay the cost)?  

Casts are conversions.  Because of the way they work with pointers
on byte-addressible machines, many beginners seem to think that
	(type)x
means to treat the bit pattern in x as if it were of type "type",
but it most emphatically doesn't.  But, we have unions to deal with
this problem.  If you have a machine in which both ints and floats
have the same length, the following will work.

union {
    int i_format;
    float f_format;
} fubar;

#define CONVERT(x) (fubar.i_format = (x), fubar.f_format)

This is absolutely horrible and nonportable (it's not predictable if
the lengths of ints and floats isn't the same), but it will work for
your specific problem.
-- 
- Joe Buck  {uunet,ucbvax,sun,decwrl,<smart-site>}!epimass.epi.com!jbuck
	    Old internet mailers: jbuck%epimass.epi.com@uunet.uu.net

Argue for your limitations and you get to keep them.   -- Richard Bach

anamaria@lll-lcc.llnl.GOV (Ana Maria De Alvare) (01/09/88)

I will consider using the UNION construction.
Make a structure that 
has a union of an int and a float on the same space.
That way you can name the same space with two different type.

This is also machine dependent in the sense that you need to have the same bit length
for both float and int types.
Consult Kernigham and Ritchie's C Programming Language book.  I have used it for 
bit and int unions and it makes it easier to manipulate the information.

Example:

union header {
   char byt_hdr[2];
   struct {
	unsigned	:2,
		f_dri	:1,
		f_dpi	:1,
		f_dp	:1,
		f_dsn	:3,
			:1,
		f_revw	:3,
		f_rp	:1,
		f_rsn	:3;
	}flags;
};

This will give you the chance of requesting the information on an array of characters
or as the bits values itself of that array of character.  
Really is the word-size I am using on the array of character to retrieve all the bit information
and in other parts of the program to manipulate the bits individually.

Might sound cumbersome right now, but it does may life easy.

See page 139 opn kernigham and Ritchie for more details.

Ana Maria

wcs@ho95e.ATT.COM (Bill.Stewart) (01/09/88)

In article <11175@brl-adm.ARPA> weiser.pa@Xerox.COM writes:
:Sigh.  I must not have made myself sufficiently clear.  Before I get any more
:responses to my converting-to-float request, please note that I need to convert
:an EXPRESSION.  The UNION  examples don't help.

Declare the union somewhere within the scope you need (global if you
must), and use a comma operator if there's no cleaner way to express things.

	union { int i; float f; } intfloat;
	target = ( intfloat.i = messy()->expr , intfloat.f ) ;

Remember the parentheses around the comma expression.
I tried this, and lint didn't even mind.
-- 
#				Thanks;
# Bill Stewart, AT&T Bell Labs 2G218, Holmdel NJ 1-201-949-0705 ihnp4!ho95c!wcs

mjh@uunet.uu.NET (Mark J. Hewitt) (01/12/88)

Mark,
	Methinks  you are looking for   an equivalent to Mesa's  untyped
LOOPHOLE conversion.  I don't believe there is one in `C', no matter how
you bend the  rules, and I've been  `C' programming for many years  now.
Originally  Modula-2  only  had casts   (called type  transfer functions
there)  of the `C'  type, but the BSI/ISO  standarisation group has been
looking at `unsafe' conversions where only the bits  are transferred.  I
can't see how  this can be vendor independent  as the representations of
REAL types (both bit length and mantissa & exponent representations) are
still (despite IEEE) quite variable.

	Sorry to be so negative, but hope to be proved wrong.

Mark J. Hewitt

	usenet:	...!{mcvax,uunet,ukc}!kernel!mjh
	other:	mjh%kernel.uucp@ukc.ac.uk
	voice:	(+44) 532 465311
        fax:	(+44) 532 420183
	paper:	Kernel Technology Ltd, 21 Queen Street,
		Leeds, LS1 2TW,	West Yorkshire, UK

-------------------------------------------------------------------------------
What's the point of having opinions if they get ascribed to someone else?
-------------------------------------------------------------------------------