libm cleanup (fixed old incorrect info)
[www] / libm / index.html
index dce0a91..67c148e 100644 (file)
@@ -77,8 +77,7 @@ precision)
 attention to the internal representation of a NaN
 (eg. the sign of NaN may not be preserved).
 <li>Most gcc bug workarounds should be removed from the code
 attention to the internal representation of a NaN
 (eg. the sign of NaN may not be preserved).
 <li>Most gcc bug workarounds should be removed from the code
-(STRICT_ASSIGN macro is used when excessive precision is harmful and
-FORCE_EVAL when expressions must be evaluated for their side-effect, other
+(FORCE_EVAL is used when expressions must be evaluated for their side-effect, other
 usage of volatile is not justified, hacks around long double constants are
 not justified eventhough gcc can miscompile those with non-default FPU setting)
 <li>When excessive precision is not harmful, temporary variables
 usage of volatile is not justified, hacks around long double constants are
 not justified eventhough gcc can miscompile those with non-default FPU setting)
 <li>When excessive precision is not harmful, temporary variables
@@ -158,7 +157,7 @@ The m68k (and m88k) architecture uses the same format, but different endianness:
 </ul>
 where m is the significand and se is the sign and exponent.
 <p>
 </ul>
 where m is the significand and se is the sign and exponent.
 <p>
-ld128 is rare (eg. sparc64 with software emulation), it means
+hardware ld128 is rare (eg. sparc64 and aarch64 with software emulation), it means
 113bit significand with implicit msb, 15bit exp, 1 sign bit:
 <ul>
 <li>union {long double f; struct{uint16_t se; uint16_t hi; uint32_t mid; uint64_t lo;} i;};
 113bit significand with implicit msb, 15bit exp, 1 sign bit:
 <ul>
 <li>union {long double f; struct{uint16_t se; uint16_t hi; uint32_t mid; uint64_t lo;} i;};
@@ -203,13 +202,10 @@ results in extended precision, this only affects x87 instructions, not sse2 etc)
 So x = a+b may give different results depending on
 the x87 fpu precision setting.
 (only happens in round to nearest rounding mode,
 So x = a+b may give different results depending on
 the x87 fpu precision setting.
 (only happens in round to nearest rounding mode,
-but that's the most common one)
+but that's the default)
 <p>
 (double rounding can happen with float vs double as well)
 <p>
 <p>
 (double rounding can happen with float vs double as well)
 <p>
-<a href="http://repo.or.cz/w/c-standard.git/blob_plain/HEAD:/n1256.html#F.7.3">C99 annex F</a>
-prohibits double rounding, but that's non-normative.
-<p>
 Note that the value of the result can only be ruined by
 double rounding in nearest rounding mode, but the double
 rounding issue haunts directed rounding modes as well:
 Note that the value of the result can only be ruined by
 double rounding in nearest rounding mode, but the double
 rounding issue haunts directed rounding modes as well:
@@ -237,24 +233,21 @@ standard, but it can cause problems (see
 
 <li>Evaluation precision:
 <p>
 
 <li>Evaluation precision:
 <p>
-C does not require consistent evaluation
-precision: the compiler may store intermediate
-results and round them to double while keep
-other parts in higher precision.
-(And the precision the compiler choses can
-be inconsistent: adding a printf to the code
-may change the result of a nearby calculation).
+C with FLT_EVAL_METHOD>=0 requires consistent evaluation
+precision, but gcc does not follow this on i386 and may
+store intermediate results and round them to double while keep
+other parts in extended precision.
+(And the precision gcc uses can be inconsistent:
+adding a printf to the code may spill 80bit float registers
+into memory changing the result of a nearby calculation).
 So
 <pre>
 (a+b)==(a+b)
 </pre>
 So
 <pre>
 (a+b)==(a+b)
 </pre>
-may be false when the two sides
+may be false with gcc and FLT_EVAL_METHOD!=0, when the two sides
 are kept in different precision.
 are kept in different precision.
-(This is not an x87 specific problem, it matters whenever there
-is a higher precision fp type than the currently used one and
-FLT_EVAL_METHOD!=0.
-It goes away if the highest precision (long double) is used
-everywhere, but that can have a huge penalty).
+If the highest precision (long double) is used
+everywhere then there is no such issue, but that can have a huge penalty.
 (clang uses sse by default on i386 with FLT_EVAL_METHOD==0,
 while gcc uses the 80bit x87 fp registers and FLT_EVAL_METHOD==2)
 <p>
 (clang uses sse by default on i386 with FLT_EVAL_METHOD==0,
 while gcc uses the 80bit x87 fp registers and FLT_EVAL_METHOD==2)
 <p>
@@ -272,11 +265,6 @@ So in
 both sides are guaranteed to be in double precision
 when the comparision is done.
 <p>
 both sides are guaranteed to be in double precision
 when the comparision is done.
 <p>
-(This still does not solve the x87 double rounding
-issue though: eg if the left side is evaluated with
-sse2 and the right side with x87 extended precision setting
-and double rounding then the result may still be false)
-<p>
 Unfortunately gcc does not respect the standard
 and even if assingment or cast is used the result
 may be kept in higher precision
 Unfortunately gcc does not respect the standard
 and even if assingment or cast is used the result
 may be kept in higher precision
@@ -289,7 +277,7 @@ gcc 4.5 fixed it with '-fexcess-precision=standard'
 registers with temporary results without rounding,
 storing the 80 bit registers entirely in memory
 which would make the behaviour under FLT_EVAL_METHOD==2
 registers with temporary results without rounding,
 storing the 80 bit registers entirely in memory
 which would make the behaviour under FLT_EVAL_METHOD==2
-mode more predictable)
+predictable)
 <p>
 The workaround for older gcc is to force the
 compiler to store the intermediate results:
 <p>
 The workaround for older gcc is to force the
 compiler to store the intermediate results:
@@ -299,14 +287,7 @@ intermediate results, but is not guaranteed
 by the gcc docs to always work).
 <p>
 (Sometimes the excess precision is good
 by the gcc docs to always work).
 <p>
 (Sometimes the excess precision is good
-but it's hard to rely on it as it is optional
-<p>
-There is a way to check for it though using
-FLT_EVAL_METHOD, float_t and double_t.
-But it's probably easier to unconditionally
-use higher precision variables when that's
-what we want and don't depend on the implicit
-excess precision).
+then float_t and double_t may be used explicitly)
 
 <li>Float literals
 <p>
 
 <li>Float literals
 <p>
@@ -335,9 +316,9 @@ to the compile-time rounded value.
 <p>
 According to the freebsd libm code gcc truncates long double
 const literals on i386.
 <p>
 According to the freebsd libm code gcc truncates long double
 const literals on i386.
-I assume this happens because freebsd uses 64bit long doubles by default
-(double precision) and gcc incorrectly uses the precision setting of the
-host platform instead of the target one, but i did not observe this on linux.
+I assume this happens because freebsd sets x87 precision to double precision by default
+where gcc is hosted and gcc cannot get the constants right for the target platform,
+but i did not observe this on linux.
 (as a workaround sometimes double-double arithmetics was used
 to initialize long doubles on i386, but most of these should be
 fixed in musl's math code now)
 (as a workaround sometimes double-double arithmetics was used
 to initialize long doubles on i386, but most of these should be
 fixed in musl's math code now)
@@ -408,9 +389,7 @@ eg. if one wants to check for -0 silently then
 <pre>
 if (x == 0.0 &amp;&amp; 1/x &lt; 0) { /* x is a -0 */ }
 </pre>
 <pre>
 if (x == 0.0 &amp;&amp; 1/x &lt; 0) { /* x is a -0 */ }
 </pre>
-is not ok: == raises invalid exception when x is nan,
-and even if we filter nans out 1/x will raise the
-divbyzero flag.
+is not ok: 1/x raises the divbyzero flag.
 <p>
 When a library wants to raise a flag deliberately
 but feraiseexcept is not available for some reason,
 <p>
 When a library wants to raise a flag deliberately
 but feraiseexcept is not available for some reason,
@@ -425,8 +404,7 @@ exception at runtime, but get optimized into x = +inf.
 see compiler optimizations above.
 <p>
 Another x87 gcc bug related to fp exceptions is that in some cases
 see compiler optimizations above.
 <p>
 Another x87 gcc bug related to fp exceptions is that in some cases
-comparision operators (==, &lt;, etc) don't raise invalid
-when an operand is nan
+relation operators (&lt;, etc) don't raise invalid when an operand is nan
 (eventhough this is required by ieee + c99 annex F).
 (see <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52451">gcc bug52451</a>).
 <p>
 (eventhough this is required by ieee + c99 annex F).
 (see <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52451">gcc bug52451</a>).
 <p>
@@ -451,9 +429,7 @@ and then set the errno variable based on that.
 So eventhough errno may be convenient, in libm it is
 not the right thing to do.
 <p>
 So eventhough errno may be convenient, in libm it is
 not the right thing to do.
 <p>
-For soft-float targets however errno seems to be the only option
-(which means annex K cannot be fully supported, as it requires
-the support of exception flags).
+For soft-float targets exceptions are problematic in c99.
 The problem is that at context switches the fpu status should
 be saved and restored which is done by the kernel on hard-fp
 architectures when the state is in an fpu status word.
 The problem is that at context switches the fpu status should
 be saved and restored which is done by the kernel on hard-fp
 architectures when the state is in an fpu status word.
@@ -465,6 +441,7 @@ Wrapping signal handlers is not possible/difficult for various
 reasons and the compiler cannot know which functions will be used
 as signal handlers, so the c runtime has no way to guarantee that
 signal handlers do not alter the fenv.
 reasons and the compiler cannot know which functions will be used
 as signal handlers, so the c runtime has no way to guarantee that
 signal handlers do not alter the fenv.
+C11 fixed this by changing signal handler semantics: fenv is in unspecified state.
 
 <li>Complex arithmetics
 <p>
 
 <li>Complex arithmetics
 <p>