CPU/编程语言使用哪些求幂算法?

CPU/编程语言使用哪些求幂算法?,c,algorithm,math,compiler-construction,cryptography,C,Algorithm,Math,Compiler Construction,Cryptography,我一直在学习更快的求幂算法(k元、滑动门等),想知道哪些算法在CPU/编程语言中使用?(我不清楚这是在CPU中还是通过编译器发生的) 就为了踢球,哪一个最快 关于宽泛性的编辑:它是故意宽泛的,因为我知道有很多不同的技术可以做到这一点。选中的答案正是我想要的。我想您感兴趣的是HLL标准数学库中的求幂函数的实现,特别是C/C++。这些函数包括函数exp(),exp2(),exp10(),和pow(),以及单精度对应的expf(),exp2f(),exp10f(),和powf() 您提到的求幂方法(如

我一直在学习更快的求幂算法(k元、滑动门等),想知道哪些算法在CPU/编程语言中使用?(我不清楚这是在CPU中还是通过编译器发生的)

就为了踢球,哪一个最快


关于宽泛性的编辑:它是故意宽泛的,因为我知道有很多不同的技术可以做到这一点。选中的答案正是我想要的。

我想您感兴趣的是HLL标准数学库中的求幂函数的实现,特别是C/C++。这些函数包括函数
exp()
exp2()
exp10()
,和
pow()
,以及单精度对应的
expf()
exp2f()
exp10f()
,和
powf()

您提到的求幂方法(如k进制、滑动窗口)通常用于加密算法,如基于求幂的RSA。它们通常不用于通过
math.h
cmath
提供的求幂函数。标准数学函数(如
exp()
的实现细节有所不同,但通用方案遵循三步流程:

  • 将函数参数化简为一次近似 间歇
  • 主近似区间上合适基函数的逼近
  • 将主间隔的结果映射回函数的整个范围
  • 辅助步骤通常是处理特殊情况。这些可以适用于特殊的数学情况,如
    log(0.0)
    ,或特殊的浮点操作数,如NaN(不是数字)

    下面的
    expf(float)
    的C99代码以示例性的方式显示了具体示例的这些步骤。参数
    a
    首先被拆分,使得
    exp(a)
    =er*2i,其中
    i
    是一个整数,
    r
    位于[log(sqrt(0.5)、log(sqrt(2.0)],主要近似区间。在第二步中,我们现在用多项式近似er。这种近似可以根据各种设计标准设计,如最小化绝对或相对误差。多项式可以用各种方法评估,包括Horner方案和Estrin方案

    下面的代码使用了一种非常常见的方法,即使用极小极大近似,该近似可将整个近似区间内的最大误差降至最低。计算此类近似的标准算法是Remez算法。通过Horner方案进行评估;使用
    fma可提高此评估的数值精度f()

    此标准数学函数实现了所谓的融合乘法加法或FMA。它在加法过程中使用完整的乘积
    a*b
    计算
    a*b+c
    ,并在末尾应用一个舍入。在大多数现代硬件上,如GPU、IBM Power CPU、最新的x86处理器(如Haswell)、最新的ARM处理器(作为可选扩展),它直接映射到硬件指令。在缺少此类指令的平台上,
    fmaf()
    将映射到相当慢的仿真代码,在这种情况下,如果我们对性能感兴趣,我们就不想使用它

    <最后的计算是2i的乘法运算,其中C和C++提供函数<代码> LDEXP()<代码>。库代码one在这里通常使用特定于机器的习惯用法,它利用IEEE-754二进制算法进行
    float
    。最后,代码清除溢出和下溢的情况

    x86处理器内部的x87 FPU有一条指令
    F2XM1
    ,在[-1,1]上计算2x-1。这可用于
    exp()
    exp2()计算的第二步
    。有一条指令
    FSCALE
    ,用于在第三步中乘以2i。实现
    F2XM1
    本身的一种常见方法是使用有理或多项式近似值的微码。请注意,现在维护的x87 FPU主要用于传统支持。在现代x86平台上,库通常使用基于SSE的纯软件实现和如下所示的算法类似。一些结合了小表格和多项式近似

    pow(x,y)
    在概念上可以实现为
    exp(y*log(x))
    ,但当
    x
    接近单位且
    y
    的幅度较大时,这会导致严重的精度损失,并且C/C++标准中规定的许多特殊情况处理不当。解决精度问题的一种方法是计算
    log(x)
    和产品
    y*log(x))
    以某种形式的扩展精度。详细信息将填充一个完整、冗长的单独答案,我手头没有代码来演示。在各种C/C++数学库中,
    pow(double,int)
    powf(float,int)
    由一个应用“平方和乘法”的单独代码路径计算对整数指数的二进制表示进行逐位扫描的方法

    #include/*导入fmaf()、ldexpf()、无穷大*/
    /*与rintf()类似,但-0.0f->+0.0f和| a |必须小于2**22*/
    快速浮动和脏浮动(浮动a)
    {
    常量浮动cvt_magic=0x1.800000p+23f;
    返回(a+cvt_魔法)-cvt_魔法;
    }
    /*间隔[log(sqrt(0.5)),log(sqrt(2.0))]上的近似exp(a)*/
    浮点表达式多边形(浮点a)
    { 
    浮子r;
    r=0x1.694000p-10f;//1.37805939e-3
    r=fmaf(r,a,0x1.125edcp-07f);/8.37312452e-3
    r=fmaf(r,a,0x1.555b5ap-05f);/4.16695364e-2
    r=fmaf(r,a,0x1.555450p-03f);//1.66664720e-1
    r=fmaf(r,a,0x1.fffff6p-02f);/4.99999851e-1
    r=fmaf(r,a,0x1.000000p+00f);//1.00000000e+0
    r=