c#Math.Sqrt实现

Rag*_*ghu 10 .net c# math frameworks

我最近一直在使用System.Math,有一天我想知道微软将如何在库中实现Sqrt方法.所以我弹出了我最好的伙伴Reflector并尝试反汇编库中的方法,但它显示:

[MethodImpl(MethodImplOptions.InternalCall),ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static extern double Sqrt(double d);
Run Code Online (Sandbox Code Playgroud)

那天有史以来第一次,我意识到我的孩子依赖于框架,吃饭.

开玩笑,但我想知道MS会用什么样的算法来实现这个方法,换句话说,如果你没有库支持,你将如何用C#编写自己的Math.Sqrt实现.

干杯

Han*_*ant 17

使用Reflector或Reference Source找到的具有MethodImplOptions.InternalCall属性的任何方法实际上都是在CLR内部的C++中实现的.您可以从SSCLI20发行版中获取这些源代码.相关文件是clr/src/vm/ecall.cpp,它包含一个带有函数指针的方法名称表,由JIT编译器用来直接将调用地址嵌入到生成的机器代码中.相关表格部分是

FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos)
FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt)
FCIntrinsic("Round", COMDouble::Round, CORINFO_INTRINSIC_Round)
...
Run Code Online (Sandbox Code Playgroud)

这将你带到clr/src/classlibnative/float/comfloat.cpp

FCIMPL1_V(double, COMDouble::Sqrt, double d)
    WRAPPER_CONTRACT;
    STATIC_CONTRACT_SO_TOLERANT;

    return (double) sqrt(d);
FCIMPLEND
Run Code Online (Sandbox Code Playgroud)

它只是调用CRT功能.但这不是x86抖动中发生的情况,请注意表声明中的"内在".你不会发现在SSLI20版本的抖动中,它是一个不受专利影响的简单版本.然而,运输方式确实将其变成了内在的:

        double d = 2.0;
        Console.WriteLine(Math.Sqrt(d));
Run Code Online (Sandbox Code Playgroud)

翻译成

00000008  fld         dword ptr ds:[0072156Ch] 
0000000e  fsqrt 
..etc
Run Code Online (Sandbox Code Playgroud)

换句话说,Math.Sqrt()转换为单个浮点机器代码指令.请查看此答案,详细了解如何轻松地击败本机代码.