libm cleanup (fixed old incorrect info) master
authornsz <nsz@port70.net>
Thu, 12 Sep 2013 23:44:55 +0000 (23:44 +0000)
committernsz <nsz@port70.net>
Thu, 12 Sep 2013 23:44:55 +0000 (23:44 +0000)
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
-(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
@@ -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>
-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;};
@@ -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,
-but that's the most common one)
+but that's the default)
 <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:
@@ -237,24 +233,21 @@ standard, but it can cause problems (see
 
 <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>
-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.
-(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>
@@ -272,11 +265,6 @@ So in
 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
@@ -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
-mode more predictable)
+predictable)
 <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
-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>
@@ -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.
-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)
@@ -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>
-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,
@@ -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
-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>
@@ -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>
-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.
@@ -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.
+C11 fixed this by changing signal handler semantics: fenv is in unspecified state.
 
 <li>Complex arithmetics
 <p>