Re: svn commit: r253215 - head/lib/msun/src

2013-07-30 Thread Steve Kargl
On Tue, Jul 30, 2013 at 12:02:23AM -0700, David Schultz wrote:
> Fortran has its own problems and isn't very well supported.

I take issue with the later assertion.   Fortran is well 
support in GCC >4.6.  See GCC list of front-end maintainers. :-)

> But for what it's worth, C++ is actually a good choice for
> high-performance numerics, IMO, mainly because of operator
> overloading and generics.  I can write a function that looks like
> actual math, and call it with a float, a double, or even an
> arbitrary-precision mpfr_t, and it just works.

I almost spit my morning coffee on my keyboard.  One can 
do the same thing in Fortran.  Of course, I'm talking about
a modern version of Fortran: namely, Fortran 2003 or Fortran 2008.   

-- 
Steve
___
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"


Re: svn commit: r253215 - head/lib/msun/src

2013-07-30 Thread David Schultz
On Mon, Jul 29, 2013, David Chisnall wrote:
> On 29 Jul 2013, at 08:05, David Schultz  wrote:
> 
> > On Thu, Jul 11, 2013, David Chisnall wrote:
> >> +static __inline int
> >> +__inline_isnan(double __x)
> >> +{
> >> +
> >> +  return (__x != __x);
> >> +}
> >> +
> >> +static __inline int
> >> +__inline_isnanf(float __x)
> >> +{
> >> +
> >> +  return (__x != __x);
> >> +}
> >> +
> >> +static __inline int
> >> +__inline_isnanl(long double __x)
> >> +{
> >> +
> >> +  return (__x != __x);
> >> +}
> > 
> > This has already been covered at greater length, but I believe
> > this part is incorrect.  Relational operators can raise an invalid
> > exception when one of the arguments is a NaN -- even a quiet NaN.
> > Raising an exception is optional in C99 (7.12.14) and required in
> > IEEE-754... in practice, it tends to be platform- and compiler-
> > specific.
> > 
> > That is the whole reason the is* macros are defined by the
> > standard in the first place, and also why we didn't use the
> > trivial implementation above.  The is* macros are required to not
> > raise an exception.
> 
> What would you suggest replacing them with?  Note that currently LLVM iR 
> doesn't provide any way of distinguishing the != comparison from something 
> that is guaranteed not to raise an exception.  I don't know how this works in 
> GIMPLE, althouhg I'd imagine that, since gcc has a working Fortran front end, 
> there is some better support for it.

I'm not sure what the inlines here were supposed to achieve, but I
think the ideal implementation would be a compiler intrinsic, with
a fallback of the libm functions if there's no working compiler
support.  As I recall, gcc has a __builtin_isnan() and macros to
test whether __builtin_nan() exists.  Presumably it wouldn't be too
hard to do the same thing in clang.

> > P.S. It would be great if clang implemented the FENV_ACCESS pragma
> > and provided an intrinsic that produced a fast inline isnan() when
> > the pragma is off, and the full, correct one when the pragma is on.
> 
> 
> I almost agree, but C is a really terrible language for mathematical work and 
> I'd prefer that people just used Fortran instead of trying to force C to be 
> Fortran.

Fortran has its own problems and isn't very well supported.  But
for what it's worth, C++ is actually a good choice for
high-performance numerics, IMO, mainly because of operator
overloading and generics.  I can write a function that looks like
actual math, and call it with a float, a double, or even an
arbitrary-precision mpfr_t, and it just works.  In C, on the other
hand, they added all this "type-generic arithmetic" and complex
number nonsense that's of very limited interest. In a better
language, that functionality could have been implemented as a
third-party library instead of as a built-in part of the language.
So in that sense, I agree with you that C went too far with
trying to compete with Fortran...

FENV_ACCESS is more reasonable, though.  It basically says that
sophisticated users ought to be able to take advantage of the IEEE
floating-point features that nearly all hardware FPUs support,
without having the compiler mess things up.  Meanwhile, there's a
second mode for users who don't care, where the optimizer is
allowed to make a lot more assumptions.  Before C99, compilers
tended to have some muddled combination of the two extremes, which
is bad for everyone.  Unfortunately, only the commercial compilers
actually implement FENV_ACCESS these days...

> In particular, take a look in the C11 spec for the semantics of this:
> 
> _Atomic(double) x = ...;
> x += 1;
> 
> It's quite astonishingly horrible.  We don't implement it correctly in clang, 
> and I hope never to have to.  

I hope it does something horrible to the programmer who thought
of the idea of atomic double-precision arithmetic.
___
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"


Re: svn commit: r253215 - head/lib/msun/src

2013-07-29 Thread Bruce Evans

On Mon, 29 Jul 2013, David Schultz wrote:


On Thu, Jul 11, 2013, David Chisnall wrote:

+static __inline int
+__inline_isnan(double __x)
+{
+
+   return (__x != __x);
+}
+
+static __inline int
+__inline_isnanf(float __x)
+{
+
+   return (__x != __x);
+}
+
+static __inline int
+__inline_isnanl(long double __x)
+{
+
+   return (__x != __x);
+}


This has already been covered at greater length, but I believe
this part is incorrect.


The correctness of this part has always been covered at greater
length :-).  We use simple "!=" tests because there is no way to
get correct behaviour and the simple test is more correct than
most, including the extern function implementation, and faster
than all.  Even greater length follows :-).


Relational operators can raise an invalid
exception when one of the arguments is a NaN -- even a quiet NaN.
Raising an exception is optional in C99 (7.12.14) and required in
IEEE-754... in practice, it tends to be platform- and compiler-
specific.


IEEE-754-2008 actually requires the '=' and '!=' comparisions (with
that spelling (or with the alternative spellins '?<>', or 'NOT=' for
'!=')) to _not_ generate an exception for quiet NaNs.  It has an
unordered-signaling and and unordered-quiet variant for all
comparisions.  The equality and inequality signaling comparisions are
so unusual that IEEE-754-2008 doesn't even give normal spellings for
their abbreviations in its tables. The tables in IEEE-854-1987 seem
to be better, and give these as '<>' and 'NOT<>'.  Howver, for
inequality predicates like '<', it is the unordered-signaling variants
that have the normal spelling, with unordered-quiet '<' having the
special spelling '?<'.

I first thought that the 2 types of comparisons were new in 2008, but
now see that they were in the IEEE-854-1987 with only a small difference
in emphasis.

The unordered-quiet variants are intended to be used in code that
takes into account the possibility of NaNs.  That is almost no code.
I had misremembered this (signaling for the usual case) as being a
design error, because real hardware like i387 and SSE has limited
support for signaling.  Actually, i387 and SSE have full support
for both cases (FCOM and COM give the signaling behaviour, and FUCOM
and UCOM give the quiet behaviour).  The only documentation that I
can find now that says that FCOM should never be used is where I
probably learned it from in _The 8086/386 Architecture_ by Morse
et al.  This says:
Since the 8087 was introduced, the floating-point standard
specified that comparisons involving quiet NaNs should return a
result of \"unordered,\" with no exception raised.  Since the FUCOM
instruction raises the invalid exception, in this case it fails
to meet the standard.  So the _unordered comparison_ instructuctions
FUCOM, FUCOMP, and FUCOMPP were added to the 387.  [...]
[Recommendation to use FCOM in simple programs and let the exception
handler deal with NaN results.  Use FUCOM if we want to handle NaNs
and the unordered condtion ourselves.]
But the standard actually requires both, at least in 1987 when Morse's
book was published.

C99 requires the signaling variants, except possiblly for the equality
predicates.  For inequality, islessgreater() gives IEEE quiet inequality
'?<>' or !'=' except it is underspecified for NaNs.  You can't get
IEEE quiet equality by inverting this since it must not be inverted for
NaNs.  You can build quiet IEEE equality and using this and
isunordered(), but the logic for this is complicated and it would be
hard for compilers to turn it back into direct IEEE quiet unordered 
equality comparisons.


C99 clarifies the intended behaviour in footnote 194, but footnotes
are not part of the standard:

%%%
   194IEC 60559 requires that the built-in relational operators
  raise the  invalid  exception  if  the  operands  compare
  unordered,  as  an  error  indicator for programs written
  without consideration of NaNs; the result in these  cases
  is false.
%%%

So '=' and '!=' should always give 'false' for NaNs, and the macros
should have the same behaviour.

x86 C compilers understand none of this.  They seem to have started
avoiding using FCOM since before Morse's book came out, and now always
generate FUCOM/UCOM.  So they always give unordered comparisons.  So
the support for "simple" programs is broken by default, and there is
no way to get it (no flag for stricter IEEE conformance?), and the C
comparison macros are useless in unportable x86 code since they generate
the same unordered comparison instructions as direct comparisons.
More usefully, the implemenation can be unportable, so it can depend
on these bugs in .  Using the x != x comparision without an
ifdef is perhaps too x86-specific, but the other arches are likely to
be even more broken no one cares about them.  I just tested the following
program on amd64, ia64 and sparc64.  It fails to raise invalid for the
comparisio

Re: svn commit: r253215 - head/lib/msun/src

2013-07-29 Thread David Chisnall
On 29 Jul 2013, at 08:05, David Schultz  wrote:

> On Thu, Jul 11, 2013, David Chisnall wrote:
>> +static __inline int
>> +__inline_isnan(double __x)
>> +{
>> +
>> +return (__x != __x);
>> +}
>> +
>> +static __inline int
>> +__inline_isnanf(float __x)
>> +{
>> +
>> +return (__x != __x);
>> +}
>> +
>> +static __inline int
>> +__inline_isnanl(long double __x)
>> +{
>> +
>> +return (__x != __x);
>> +}
> 
> This has already been covered at greater length, but I believe
> this part is incorrect.  Relational operators can raise an invalid
> exception when one of the arguments is a NaN -- even a quiet NaN.
> Raising an exception is optional in C99 (7.12.14) and required in
> IEEE-754... in practice, it tends to be platform- and compiler-
> specific.
> 
> That is the whole reason the is* macros are defined by the
> standard in the first place, and also why we didn't use the
> trivial implementation above.  The is* macros are required to not
> raise an exception.

What would you suggest replacing them with?  Note that currently LLVM iR 
doesn't provide any way of distinguishing the != comparison from something that 
is guaranteed not to raise an exception.  I don't know how this works in 
GIMPLE, althouhg I'd imagine that, since gcc has a working Fortran front end, 
there is some better support for it.

> P.S. It would be great if clang implemented the FENV_ACCESS pragma
> and provided an intrinsic that produced a fast inline isnan() when
> the pragma is off, and the full, correct one when the pragma is on.


I almost agree, but C is a really terrible language for mathematical work and 
I'd prefer that people just used Fortran instead of trying to force C to be 
Fortran.  In particular, take a look in the C11 spec for the semantics of this:

_Atomic(double) x = ...;
x += 1;

It's quite astonishingly horrible.  We don't implement it correctly in clang, 
and I hope never to have to.  

David



signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: svn commit: r253215 - head/lib/msun/src

2013-07-29 Thread David Schultz
On Thu, Jul 11, 2013, David Chisnall wrote:
> +static __inline int
> +__inline_isnan(double __x)
> +{
> +
> + return (__x != __x);
> +}
> +
> +static __inline int
> +__inline_isnanf(float __x)
> +{
> +
> + return (__x != __x);
> +}
> +
> +static __inline int
> +__inline_isnanl(long double __x)
> +{
> +
> + return (__x != __x);
> +}

This has already been covered at greater length, but I believe
this part is incorrect.  Relational operators can raise an invalid
exception when one of the arguments is a NaN -- even a quiet NaN.
Raising an exception is optional in C99 (7.12.14) and required in
IEEE-754... in practice, it tends to be platform- and compiler-
specific.

That is the whole reason the is* macros are defined by the
standard in the first place, and also why we didn't use the
trivial implementation above.  The is* macros are required to not
raise an exception.

P.S. It would be great if clang implemented the FENV_ACCESS pragma
and provided an intrinsic that produced a fast inline isnan() when
the pragma is off, and the full, correct one when the pragma is on.
___
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"


Re: svn commit: r253215 - head/lib/msun/src

2013-07-13 Thread Bruce Evans

On Sat, 13 Jul 2013, Tijl Coosemans wrote:


On 2013-07-12 11:14, Bruce Evans wrote:

On Thu, 11 Jul 2013, Tijl Coosemans wrote:

On 2013-07-11 22:03, Tijl Coosemans wrote:

...
isnan(double) is part of SUSv2. It should be visible when compiling with
-D_XOPEN_SOURCE=500. I think you need something like this:

#if (__BSD_VISIBLE || __XSI_VISIBLE <= 500) && __ISO_C_VISIBLE < 1999
intisinf(double) __pure2;
intisnan(double) __pure2;
#endif


Actually this:

#if (__BSD_VISIBLE || (defined(__XSI_VISIBLE) && __XSI_VISIBLE <= 500))
&& __ISO_C_VISIBLE < 1999


Remove the __ISO_C_VISIBLE part, since this is not in C90.  This also
fixes a style bug (long line).


I shouldn't have mentioned C90. What I meant to say is the
not-C99-or-higher case which is further restricted by __BSD_VISIBLE
and __XSI_VISIBLE, but where the macros aren't defined.


Maybe just put it back where it was then.  We still have isnanf() under
__BSD_VISIBLE and no other ifdef.  It is unsorted into the __BSD_VISIBLE
section for doubles.  We also have finite() and finitef().  These are
old aliases for isfinite().  At least they are sorted.  I'd like to remove
all of these.  But msun still uses all of them internally.  It still has
a compatibility hack to misuse isnanf.  This shows how hard it is to remove
zombies.


These two symbols are the cause for the original problem report about
clang's cmath header (in C++11 isnan/isinf are functions returning bool
not int). Their visibility had to be constrained somehow and that
cascaded into redefining the isnan and isinf macros because they were
implemented using these functions. I think completely removing these
symbols is wrong however because it breaks the API in the specific case
of the #if above.


It's safer to clean only 1 thing at a time anyway.


I noticed some more problems in the implementation of these macros
and others:
- many or all of the __pure2's in the prototypes are wrong, since even
  the classification functions can have side effects for signaling
  NaNs.  It is impossible to avoid these side effects for extern
  functions in some cases, since the ABI gives them.  I think static
  inline functions must have the same results as extern functions,
  so compilers should pessimize inline functions as necessary to
  get the same bad results, but compilers don't do that.


Apparently, in the 2008 version of IEEE 754 they are considered
non-computational and never generate exceptions, even for sNaN.

The old IEEE 754-1985 only mentions isfinite and isnan and says
implementations may consider them non-arithmetic.


IEEE 854-1987 says the same as 754-1987 in an appendix (recommended
behaviour; not part of the standard).  It says the same for copysign()
and unary negation.  It also says that isnan(x) is equivalent to x !=
x and that isfinite(x) is true precisely when -Inf < x < Inf.  Many
comparisons are specified to raise the invalid exception for invalid
operands, and signaling NaNs can certainly be considered invalid.  The
!= comparsion mentioned in the appendix is one of the ones that must
be "unordered" and thus must raise the exception.  However, comparisons
are not considered as operations, so the requirement that operations
with signaling NaNs raise the exception doesn't apply.  The standard
is unclear here.


- classification functions are specified to convert to the semantic
  type (remove any extra precision or exponent range) before classifying.


Yes, it makes the macros more function-like.


  For example, if x is a double slightly larger than sqrt(DBL_MAX), and
  if double expressions are evaluated in extra exponent range, then x*x
  is finite with the extra range but infinite in the semantic type.  So
  isinf(x*x) is true, and the implementation
  #define isinf(x) (fabs(x) == INFINITY) is invalid.  clang on x86 gets
  __builtin_isinf(x*x) this right as a side effect of its pessimization
  of fabs() to non-inline -- parameter passing to the extern fabs()
  converts to the semantic type.  Sometimes the arg is known not to have
  extra range, so no conversion is needed.


If isinf isn't supposed to generate exceptions then it cannot use a
floating point comparison either. That would only leave bit operations.


Indeed.  I thought that the i387 unordered comparison instructions doesn't
raise the exception for signaling NaNs, but it does.  Similarly for
SSE unordered comparision.

Recent changes actually broke many cases that used to work :-(.  Compilers
don't understand this, so they generate x != x.  __isnan(), __isnanf()
and __isnanl() work since they use bit operations, provided calling them
doesn't change the precision.  So the cases that used to work on x86
except ones where the arg is float or double AND the arch is i386 AND
SSE is not used AND arg passing involves copying through the i387 (the
latter depends on the compiler and compiler options).  All cases with
signaling NaNs on x86 are now broken.


I think C11 has new mistakes for extra precision.  It specifies th

Re: svn commit: r253215 - head/lib/msun/src

2013-07-13 Thread Tijl Coosemans
On 2013-07-12 11:14, Bruce Evans wrote:
> On Thu, 11 Jul 2013, Tijl Coosemans wrote:
>> On 2013-07-11 22:03, Tijl Coosemans wrote:
>>> On 2013-07-11 21:36, David Chisnall wrote:
 On 11 Jul 2013, at 19:52, Tijl Coosemans  wrote:
>> @@ -227,8 +250,6 @@ doubleexpm1(double);
>> doublefma(double, double, double);
>> doublehypot(double, double);
>> intilogb(double) __pure2;
>> -int(isinf)(double) __pure2;
>> -int(isnan)(double) __pure2;
>
> I think they should stay for the C90 case.

 That would completely defeat the point of this entire exercise and be
 redundant unless we aim to support a compiler that only supports C90
 and no GNU extensions, in which case you'll hit errors in cdefs.h,
 long before you get to this point in an include.
>>>
>>> isnan(double) is part of SUSv2. It should be visible when compiling with
>>> -D_XOPEN_SOURCE=500. I think you need something like this:
>>> 
>>> #if (__BSD_VISIBLE || __XSI_VISIBLE <= 500) && __ISO_C_VISIBLE < 1999
>>> intisinf(double) __pure2;
>>> intisnan(double) __pure2;
>>> #endif
>>
>> Actually this:
>>
>> #if (__BSD_VISIBLE || (defined(__XSI_VISIBLE) && __XSI_VISIBLE <= 500))
>> && __ISO_C_VISIBLE < 1999
> 
> Remove the __ISO_C_VISIBLE part, since this is not in C90.  This also
> fixes a style bug (long line).

I shouldn't have mentioned C90. What I meant to say is the
not-C99-or-higher case which is further restricted by __BSD_VISIBLE
and __XSI_VISIBLE, but where the macros aren't defined.

These two symbols are the cause for the original problem report about
clang's cmath header (in C++11 isnan/isinf are functions returning bool
not int). Their visibility had to be constrained somehow and that
cascaded into redefining the isnan and isinf macros because they were
implemented using these functions. I think completely removing these
symbols is wrong however because it breaks the API in the specific case
of the #if above.

If __ISO_C_VISIBLE < 1999 isn't correct then maybe __cplusplus < 201103L?

> How can that work?  Even you forgot to restore the parentheses around
> the functions, so the above has syntax errors.

The macros aren't there for __ISO_C_VISIBLE < 1999.

> I noticed some more problems in the implementation of these macros
> and others:
> - many or all of the __pure2's in the prototypes are wrong, since even
>   the classification functions can have side effects for signaling
>   NaNs.  It is impossible to avoid these side effects for extern
>   functions in some cases, since the ABI gives them.  I think static
>   inline functions must have the same results as extern functions,
>   so compilers should pessimize inline functions as necessary to
>   get the same bad results, but compilers don't do that.

Apparently, in the 2008 version of IEEE 754 they are considered
non-computational and never generate exceptions, even for sNaN.

The old IEEE 754-1985 only mentions isfinite and isnan and says
implementations may consider them non-arithmetic.

> - classification functions are specified to convert to the semantic
>   type (remove any extra precision or exponent range) before classifying.

Yes, it makes the macros more function-like.

>   For example, if x is a double slightly larger than sqrt(DBL_MAX), and
>   if double expressions are evaluated in extra exponent range, then x*x
>   is finite with the extra range but infinite in the semantic type.  So
>   isinf(x*x) is true, and the implementation
>   #define isinf(x) (fabs(x) == INFINITY) is invalid.  clang on x86 gets
>   __builtin_isinf(x*x) this right as a side effect of its pessimization
>   of fabs() to non-inline -- parameter passing to the extern fabs()
>   converts to the semantic type.  Sometimes the arg is known not to have
>   extra range, so no conversion is needed.

If isinf isn't supposed to generate exceptions then it cannot use a
floating point comparison either. That would only leave bit operations.

> I think C11 has new mistakes for extra precision.  It specifies that
> return reduces to the semantic type, like the classification macros
> are required to do for their arg.  clang -std=c11 doesn't implement
> this bug for at least:
> 
> #include 
> double sq(double x) { return (x*x); }
> double sq2(double x) { return (fabs(x*x); }
> 
> On i386 without SSE2 (so extra precision), this generates the same code
> as with -std=c99.  Squaring x gives extra precision and exponent range.
> This is not destroyed on return, so extra precision is not defeated by
> writing the squaring operation as a function.  fabs() is inlined in both
> cases, so it has little effect here (no effect unless x is NaN), but I
> think even C99 doesn't permit this.  If fabs() were not inline, then
> the ABI would force destruction of the extra precision and range when
> it is called, and I think C99 requires conversion to the semantic type
> for calls.

For function parameters both C99 and C11 state that they are converted

Re: svn commit: r253215 - head/lib/msun/src

2013-07-12 Thread Bruce Evans

On Thu, 11 Jul 2013, Tijl Coosemans wrote:


On 2013-07-11 22:03, Tijl Coosemans wrote:

On 2013-07-11 21:36, David Chisnall wrote:

On 11 Jul 2013, at 19:52, Tijl Coosemans  wrote:

@@ -227,8 +250,6 @@ double  expm1(double);
double  fma(double, double, double);
double  hypot(double, double);
int ilogb(double) __pure2;
-int(isinf)(double) __pure2;
-int(isnan)(double) __pure2;


I think they should stay for the C90 case.


That would completely defeat the point of this entire exercise and be
redundant unless we aim to support a compiler that only supports C90
and no GNU extensions, in which case you'll hit errors in cdefs.h,
long before you get to this point in an include.


isnan(double) is part of SUSv2. It should be visible when compiling with
-D_XOPEN_SOURCE=500. I think you need something like this:



#if (__BSD_VISIBLE || __XSI_VISIBLE <= 500) && __ISO_C_VISIBLE < 1999
int isinf(double) __pure2;
int isnan(double) __pure2;
#endif


Actually this:

#if (__BSD_VISIBLE || (defined(__XSI_VISIBLE) && __XSI_VISIBLE <= 500)) && 
__ISO_C_VISIBLE < 1999


Remove the __ISO_C_VISIBLE part, since this is not in C90.  This also fixes
a style bug (long line).

How can that work?  Even you forgot to restore the parentheses around
the functions, so the above has syntax errors.  Applications would
have to use parentheses to get the functions (or not include ,
but then it doesn't matther if it doesn't declare the functions).
Applications that forget to do this will get the macros instead of the
functions.  If the arg type is double, then the macro will work the
same as the functions.  Otherwise, it has different semantics, but
usually the same result except for signaling NaNs.  But does old XSI
really specify that parentheses must be used to get isnan() (or can
be used to get an isnan() function that is specified to exist)?  Old
BSD has almost no specification for isnan(), and there probably isn't
much old BSD code that carefully prevents use of the macro using
parentheses.  isnan()'s man page actually says that 3BSD introduced
isinf() and isnan() functions, but these have been superseded by the
macros.

I noticed some more problems in the implementation of these macros
and others:
- many or all of the __pure2's in the prototypes are wrong, since even
  the classification functions can have side effects for signaling
  NaNs.  It is impossible to avoid these side effects for extern
  functions in some cases, since the ABI gives them.  I think static
  inline functions must have the same results as extern functions,
  so compilers should pessimize inline functions as necessary to
  get the same bad results, but compilers don't do that.
- classification functions are specified to convert to the semantic
  type (remove any extra precision or exponent range) before classifying.

  For example, if x is a double slightly larger than sqrt(DBL_MAX), and
  if double expressions are evaluated in extra exponent range, then x*x
  is finite with the extra range but infinite in the semantic type.  So
  isinf(x*x) is true, and the implementation
  #define isinf(x) (fabs(x) == INFINITY) is invalid.  clang on x86 gets
  __builtin_isinf(x*x) this right as a side effect of its pessimization
  of fabs() to non-inline -- parameter passing to the extern fabs()
  converts to the semantic type.  Sometimes the arg is known not to have
  extra range, so no conversion is needed.

  isnan(x) can safely skip the conversion, at least on x86, since conversion
  doesn't change the classification of NaNs.  __builtin_isnan(x*x) for
  clang on x86 skips the conversion.

  __builtin_isinfinite(x*x) for clang on x86 is a combination of the above --
  isnan() with no conversion and !isinf() with pessimal conversion via
  non-inline fabs().

I couldn't find any case where a necessary conversion is not done.  Our
implementation using functions gives the necessary conversions including
ones that are broken for signaling NaNs.  But there is no problem for
with signaling NaNs for expressions like x*x, since the result of an
expression with almost any operator in it can't be a signaling NaN.

I think C11 has new mistakes for extra precision.  It specifies that
return reduces to the semantic type, like the classification macros
are required to do for their arg.  clang -std=c11 doesn't implement
this bug for at least:

#include 
double sq(double x) { return (x*x); }
double sq2(double x) { return (fabs(x*x); }

On i386 without SSE2 (so extra precision), this generates the same code
as with -std=c99.  Squaring x gives extra precision and exponent range.
This is not destroyed on return, so extra precision is not defeated by
writing the squaring operation as a function.  fabs() is inlined in both
cases, so it has little effect here (no effect unless x is NaN), but I
think even C99 doesn't permit this.  If fabs() were not inline, then
the ABI would force destruction of the extra precision and range when
it is called, and 

Re: svn commit: r253215 - head/lib/msun/src

2013-07-12 Thread Bruce Evans

On Thu, 11 Jul 2013, David Chisnall wrote:


On 11 Jul 2013, at 19:52, Tijl Coosemans  wrote:


GCC doesn't support _Generic yet for -std=c11.


Ugh.  Given that they also lack a fine-grained feature check mechanism, they 
really should not advertise support for a language dialect if they don't 
support it.



+#elif __GNUC_PREREQ__(5, 1)


GCC 3.1?


Ooops, I changed this to 5.1 to test the other code path and forgot to revert 
it.


Last __fpclassifyd should be __fpclassifyl.


Fixed.


There are still many style bugs to fix:
- indentation of continuation lines.  It was changed from the normal 4
  spaces to 1 tab in macro definitions.  The style rule for continuation
  lines for #define's is not as clear as for statements, but math.h used
  to use 4 spaces consistently.
- whitespace before backslashes.  It is neither minimal, maximal, lines
  up the backslashes to tab boundaries, lines up the backslashes across
  macros, nor uses tabs.  It repaces formatting that uses tabs to line
  up all backslashes to the 7th tab stop.
- whitespace before macro bodies.  It was changed from the normal 1 tab
  to 1 space.  The next block of macros (for __MATH_BUILTIN_RELOPS)
  provides examples of normal formatting, and the block beginning with
  isfinite() looks really ugly in comparison.
- verbose names, and resulting ugly formatting to avoid long lines
- the x parameter is missing parentheses in the main macros starting at
  fpclassify().  __fp_type_select() supplies the necessary parentheses,
  but this is fragile.

BTW, is it really permitted for the comparison macros to evaluate their
args more than once?  This is done for the !__MATH_BUILTIN_RELOPS case.
I hoped that you replace all the inlines for isnan() by macros, but
now I can't see how to do this without using either multiple evaluation
of the arg or an unportable statement-expression.  However, the relops
already use macros that are sloppy about multiple evaluation in the
!_MATH_BUILTIN_RELOPS case, so math.h would be no more broken if it did
the same for isnan().  isnan() is just a special relop that is even
simpler than the others, but its implementation is more complicated and
10-20 times larger in math.h alone (100 times larger counting all the
compatibility cruft for it in other files).


@@ -227,8 +250,6 @@ double  expm1(double);
double  fma(double, double, double);
double  hypot(double, double);
int ilogb(double) __pure2;
-int(isinf)(double) __pure2;
-int(isnan)(double) __pure2;


I think they should stay for the C90 case.


That would completely defeat the point of this entire exercise and be redundant 
unless we aim to support a compiler that only supports C90 and no GNU 
extensions, in which case you'll hit errors in cdefs.h, long before you get to 
this point in an include.


They aren't in C90.  More in another reply.

Bruce
___
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"


Re: svn commit: r253215 - head/lib/msun/src

2013-07-11 Thread Tijl Coosemans
On 2013-07-11 22:03, Tijl Coosemans wrote:
> On 2013-07-11 21:36, David Chisnall wrote:
>> On 11 Jul 2013, at 19:52, Tijl Coosemans  wrote:
 @@ -227,8 +250,6 @@ double expm1(double);
 double fma(double, double, double);
 double hypot(double, double);
 intilogb(double) __pure2;
 -int   (isinf)(double) __pure2;
 -int   (isnan)(double) __pure2;
>>>
>>> I think they should stay for the C90 case.
>>
>> That would completely defeat the point of this entire exercise and be
>> redundant unless we aim to support a compiler that only supports C90
>> and no GNU extensions, in which case you'll hit errors in cdefs.h,
>> long before you get to this point in an include.
> 
> isnan(double) is part of SUSv2. It should be visible when compiling with
> -D_XOPEN_SOURCE=500. I think you need something like this:
> 
> #if (__BSD_VISIBLE || __XSI_VISIBLE <= 500) && __ISO_C_VISIBLE < 1999
> int   isinf(double) __pure2;
> int   isnan(double) __pure2;
> #endif

Actually this:

#if (__BSD_VISIBLE || (defined(__XSI_VISIBLE) && __XSI_VISIBLE <= 500)) && 
__ISO_C_VISIBLE < 1999





signature.asc
Description: OpenPGP digital signature


Re: svn commit: r253215 - head/lib/msun/src

2013-07-11 Thread Tijl Coosemans
On 2013-07-11 21:36, David Chisnall wrote:
> On 11 Jul 2013, at 19:52, Tijl Coosemans  wrote:
>>> @@ -227,8 +250,6 @@ double  expm1(double);
>>> double  fma(double, double, double);
>>> double  hypot(double, double);
>>> int ilogb(double) __pure2;
>>> -int(isinf)(double) __pure2;
>>> -int(isnan)(double) __pure2;
>>
>> I think they should stay for the C90 case.
> 
> That would completely defeat the point of this entire exercise and be
> redundant unless we aim to support a compiler that only supports C90
> and no GNU extensions, in which case you'll hit errors in cdefs.h,
> long before you get to this point in an include.

isnan(double) is part of SUSv2. It should be visible when compiling with
-D_XOPEN_SOURCE=500. I think you need something like this:

#if (__BSD_VISIBLE || __XSI_VISIBLE <= 500) && __ISO_C_VISIBLE < 1999
int isinf(double) __pure2;
int isnan(double) __pure2;
#endif



signature.asc
Description: OpenPGP digital signature


Re: svn commit: r253215 - head/lib/msun/src

2013-07-11 Thread David Chisnall
On 11 Jul 2013, at 19:52, Tijl Coosemans  wrote:

> GCC doesn't support _Generic yet for -std=c11.

Ugh.  Given that they also lack a fine-grained feature check mechanism, they 
really should not advertise support for a language dialect if they don't 
support it.

> 
>> +#elif __GNUC_PREREQ__(5, 1)
> 
> GCC 3.1?

Ooops, I changed this to 5.1 to test the other code path and forgot to revert 
it.

> Last __fpclassifyd should be __fpclassifyl.

Fixed.

>> @@ -227,8 +250,6 @@ double   expm1(double);
>> double   fma(double, double, double);
>> double   hypot(double, double);
>> int  ilogb(double) __pure2;
>> -int (isinf)(double) __pure2;
>> -int (isnan)(double) __pure2;
> 
> I think they should stay for the C90 case.

That would completely defeat the point of this entire exercise and be redundant 
unless we aim to support a compiler that only supports C90 and no GNU 
extensions, in which case you'll hit errors in cdefs.h, long before you get to 
this point in an include.  

David




signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: svn commit: r253215 - head/lib/msun/src

2013-07-11 Thread Tijl Coosemans
On 2013-07-11 19:41, David Chisnall wrote:
> Author: theraven
> Date: Thu Jul 11 17:41:04 2013
> New Revision: 253215
> URL: http://svnweb.freebsd.org/changeset/base/253215
> 
> Log:
>   Cleanups to math.h that prevent namespace conflicts with C++.
>   
>   Reviewed by:bde
>   MFC after:  3 days
> 
> Modified:
>   head/lib/msun/src/math.h
> 
> Modified: head/lib/msun/src/math.h
> ==
> --- head/lib/msun/src/math.h  Thu Jul 11 16:27:11 2013(r253214)
> +++ head/lib/msun/src/math.h  Thu Jul 11 17:41:04 2013(r253215)
> @@ -80,27 +80,33 @@ extern const union __nan_un {
>  #define  FP_NORMAL   0x04
>  #define  FP_SUBNORMAL0x08
>  #define  FP_ZERO 0x10
> +
> +#if __STDC_VERSION__ >= 201112L
> +#define  __fp_type_select(x, f, d, ld) _Generic((x), \
> + float: f(x),\
> + double: d(x),   \
> + long double: ld(x))

GCC doesn't support _Generic yet for -std=c11.

> +#elif __GNUC_PREREQ__(5, 1)

GCC 3.1?

> +#define  __fp_type_select(x, f, d, ld) __builtin_choose_expr(
>   \
> + __builtin_types_compatible_p(__typeof(x), long double), ld(x),\
> + __builtin_choose_expr(\
> + __builtin_types_compatible_p(__typeof(x), double), d(x),  \
> + __builtin_choose_expr(\
> + __builtin_types_compatible_p(__typeof(x), float), f(x), (void)0)))
> +#else
> +#define   __fp_type_select(x, f, d, ld) \
> + ((sizeof(x) == sizeof(float)) ? f(x)   \
> + : (sizeof(x) == sizeof(double)) ? d(x) \
> + : ld(x))
> +#endif
> +
>  #define  fpclassify(x) \
> -((sizeof (x) == sizeof (float)) ? __fpclassifyf(x) \
> -: (sizeof (x) == sizeof (double)) ? __fpclassifyd(x) \
> -: __fpclassifyl(x))
> -
> -#define  isfinite(x) \
> -((sizeof (x) == sizeof (float)) ? __isfinitef(x) \
> -: (sizeof (x) == sizeof (double)) ? __isfinite(x)\
> -: __isfinitel(x))
> -#define  isinf(x)\
> -((sizeof (x) == sizeof (float)) ? __isinff(x)\
> -: (sizeof (x) == sizeof (double)) ? isinf(x) \
> -: __isinfl(x))
> -#define  isnan(x)\
> -((sizeof (x) == sizeof (float)) ? __isnanf(x)\
> -: (sizeof (x) == sizeof (double)) ? isnan(x) \
> -: __isnanl(x))
> -#define  isnormal(x) \
> -((sizeof (x) == sizeof (float)) ? __isnormalf(x) \
> -: (sizeof (x) == sizeof (double)) ? __isnormal(x)\
> -: __isnormall(x))
> + __fp_type_select(x, __fpclassifyf, __fpclassifyd, __fpclassifyd)

Last __fpclassifyd should be __fpclassifyl.

> @@ -227,8 +250,6 @@ doubleexpm1(double);
>  double   fma(double, double, double);
>  double   hypot(double, double);
>  int  ilogb(double) __pure2;
> -int  (isinf)(double) __pure2;
> -int  (isnan)(double) __pure2;

I think they should stay for the C90 case.



signature.asc
Description: OpenPGP digital signature