https://github.com/somian/Path64/blob/master/pathscale/libmpath/amd/w_sincos.c

x64 msvcr100/110 uses this:

https://github.com/simonbyrne/libacml_mv/blob/master/src/gas/sin.S

The newer x64 CRTs would get updates, like the FMA path in msvcr120. ]]>

if |x| < 2^-27:

return x

else if |x| < 2^-13:

return x – x^3/6

else: …

x64 compares the whole 64-bit value so the constants have to be loaded from memory. ARM (Thumb-2) compares the top 32-bit half. 2^-27 is an immediate but 2^-13 has to be loaded from memory. I don't know how much code is shared between the x64 and ARM libraries but here are my observations:

– They all use the same 13th degree polynomial approximation

– x64 (FMA) and ARM have the x – x^3/6 part while x64 (SSE2) does not

– Range reduction is different on all three

This has been interesting so far, maybe I will study the range reduction next.

Perhaps because the constant for the comparison is simpler thus faster to load? On the ARM, this would be the case for 0x3e400000 (2^(-27)), which fits on 8 bits with an even rotate, but not for 0x3e500000. If the VS 2015 source code is the same for the ARM, this could explain the reason.

]]>In actual implementations of sin() the threshold for the “return x” case is usually lower. For example, the VS 2015 64-bit runtime (ucrtbase) uses 2^-27. For 2^27 < |x| < 2.149e-8, it will do some computations but the result should be equal to x. ]]>

http://www.wolframalpha.com/input/?i=plot+y+%3D+x-sin(x)+from+x+%3D+2.14911931e-8+to+2.14911935e-8

]]>When I wrote this I was working at Valve on Steam and their various games.

I now work at Google on Chrome. It is indeed famous enough that Microsoft has re-implemented a similar product into its portfolio. We’ll see how it goes.

Curiously enough, Google is working on improving the clang compiler and now has the option of compiling Chrome with clang instead of the VC++ compiler.

]]>Moreover, you’ll have helped MS to get there by improving their other software products which have defeated products of other companies in the given market niche…. ]]>

It also shows an extra /D CODE_ANALYSIS which it may be a good idea to use.

No sign of how the ruleset to use is communicated to the compiler… I really hope it’s not done by the compiler parsing the name from the /analyze:log argument

/analyze:log “MyFile.cpp.nativecodeanalysis.xml”

I suppose I could try changing the rulesets to use and comparing the command line (and then sniffing registry access etc)

]]>It is the gap size that results in the relative error, which is calculated as the difference between 8.589973e9 and 8.589973504e9, divided by 8.589973e9.

As Goldberg puts it,

“If the result of a calculation is the floating-point number nearest to the correct result, it still might be in error by as much as .5 ulp. Another way to measure the difference between a floating-point number and the real number it is approximating is relative error, which is simply the difference between the two numbers divided by the real number…

Since numbers of the form d.dd…dd × (Base^e) all have the same absolute error, but have values that range between (Base^e) and ((Base^e) × Base), the relative error ranges between … (1/2)*(Base)^(-precision) and ((Base)/2) * ((Base)^(-precision)).

In particular, the relative error corresponding to .5 ulp can vary by a factor of (Base). This factor is called the wobble.”

Thus, from what I understand, relative error is calculated for a single float representation within the range [2^n, 2^(n+1)) whereas wobble refers to the range of the relative errors of the floats within the range [2^n, 2^(n+1)).

Where you mention that “At 8.589930e9 a float’s relative precision is 1/16777216 but at 8.589974e9 it is just 1/8388608”, the relative error/precision at 8.589974e9 can be calculated specifically as

|(8.589973504e9-8.589974e9)| / 8.589974e9 =(approx.) 5.8e-8

which is within the wobble range for floats – 1/16777216 (at start of power of 2 range) to 1/33554432 (at end of power of 2 range).

As to whether the numerator should be 1.0 or 0.5, Goldberg defines “the relative error ranges (for the wobble as being) between ((Base/2) * (Base^(-p)) * (Base^e)/(Base^e) and ((Base/2) * Base^(-p)) * (Base^e)/Base^(e+1). So, strictly speaking the numerator, which is the 1/2 ULP term, should be

(Base/2) * (Base^(-p)) * (Base^e)

After the reduction of the relative error expressions where Base == 2, whether you would like to consider the numerator as 1 or 0.5 is purely algebraic I think.

]]>