Re: svn commit: r253215 - head/lib/msun/src
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
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
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
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
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
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
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
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
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
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
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
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
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