Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 9 Mar 2012 22:28:44 -0500
From: Rich Felker <>
Subject: Re: libm

On Fri, Mar 09, 2012 at 12:02:54PM -0500, Rich Felker wrote:
> On Fri, Mar 09, 2012 at 10:56:55AM -0500, Rich Felker wrote:
> > > > Then add __RETCAST((x)), __RETCAST((x)+(y)), etc. Some trick will be
> > > > needed to make integer types result in a cast to double, though.
> > > 
> > > hm the int->double and complex/real cases are tricky
> > > 
> > > i thought +1.0 or +I would solve these, but that's wrong
> > 
> > I think +0.0f might solve it. Isn't the promoted type of any integer
> > type with float double?
> Nope, it results in float. glibc has a trick involving obscure
> interactions of null pointer constants and the ?: operator that
> generates the right type using __typeof__, which is no big deal
> because this code is already only used when __typeof__ is available,
> anyway.
> There's a good blog article on it somewhere which I can't seem to find
> at the moment...

Try this:

#define __RETCAST(x) (__typeof__(*(0 \
? (__typeof__(0 ? (double *)0 : (void *)__IS_FP(x)))0 \
: (__typeof__(0 ? (__typeof__(x) *)0 : (void *)!__IS_FP(x)))0 )))

In the outer conditional operator, the second operand is a pointer to
double if (void *)__IS_FP(x) is a null pointer constant (which is true
iff __IS_FP(x)==0) and otherwise is a pointer to void.

Conversely, the third operand of the outer conditional is a pointer to
__typeof__(x) iff __IS_FP(x)!=0, and otherwise a pointer to void.

Thus the outer conditional sees either "double *" and "void *", or
else "void *" and "__typeof__(x) *", resulting it in having type
"double *" or "__typeof__(x)", reflecting whether x was an integer or
floating point type.


Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.