是否可以计算C中的逆误差函数?
我能找到erf(x)的<math.h>,其计算误差函数,但我找不到任何做反.
hypot在1999年的语言修订版中引入C 的函数,在另一方作为参数的情况下,计算了直角三角形的斜边,但要注意避免因天真实现而导致的上下溢.
double hypot(double a, double b)
{
return sqrt(a*a + b*b);
}
Run Code Online (Sandbox Code Playgroud)
我发现自己需要伴侣功能:给定一个边和三角形的斜边,找到第三面(避免在/溢出下).我可以想到几种方法来做到这一点,但想知道是否存在现有的"最佳实践"?
我的目标是Python,但实际上我正在寻找算法指针.
我编写的代码中有大量的浮点运算。我们有测试用例来记录给定输入的输出,并验证我们不会对结果进行太多更改。我建议我启用 -march native 以提高性能。然而,启用该功能后,我们会遇到测试失败的情况,因为结果发生了变化。由于访问由 -march native 启用的更现代的硬件而将使用的指令是否会减少浮点错误量?增加浮点误差量?或者两者兼而有之?融合乘法加法应该可以减少浮点错误量,但这是否是随时间添加的指令的典型情况?或者是否添加了一些说明,虽然效率更高,但准确性较低?
我的目标平台是 x86_64 Linux。处理器信息根据/proc/cpuinfo是:
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 85
model name : Intel(R) Xeon(R) Gold 6152 CPU @ 2.10GHz
stepping : 4
microcode : 0x2006a0a
cpu MHz : 2799.999
cache size : 30976 KB
physical id : 0
siblings : 44
core id : 0
cpu cores : 22
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level …Run Code Online (Sandbox Code Playgroud) 根据文档,有一个fma()功能math.h.这非常好,我知道FMA如何工作以及如何使用它.但是,我不太确定这在实践中如何实施?我最感兴趣的是x86和x86_64架构.
是否存在FMA的浮点(非向量)指令,可能是IEEE-754 2008定义的?
是使用FMA3还是FMA4指令?
在依赖精度的情况下,是否存在确保使用真实FMA的内在因素?
在一些应用中,需要多个角度的正弦和余弦,其中角度是通过将相同大小的增量incr重复添加到起始值基数来导出的。出于性能原因,无需为每个生成的角度调用sin()标准cos()数学库函数(或可能是非标准sincos()函数),只计算一次sin(base)和cos(base),然后导出所有其他角度是非常有利的通过应用角和公式计算正弦和余弦:
\n\n\nsin(基数+增量) = cos(增量) \xc2\xb7 sin(基数) + sin(增量) \xc2\xb7 cos(基数) \
\n
n cos(基数+增量) = cos(增量) \xc2\xb7 cos (基数) - sin(增量) \xc2\xb7 sin(基数)
这只需要一次性预计算比例因子sin(incr)和cos(incr),而不管执行多少次迭代。
\n\n这种方法有几个问题。如果增量很小,cos(incr)将是一个接近单位的数字,在以有限精度浮点格式计算时,会因隐式减法取消而导致精度损失。此外,由于计算没有以数值有利形式sin(base+incr) = sin(base) + adjustment排列,因此会产生比必要的更多的舍入误差,其中计算的数量adjustment 的幅度明显小于sin(base) (类似于余弦)。
\n\n由于通常会应用数十到数百个迭代步骤,因此这些误差将会累积。如何以最有利于保持高精度的方式构建迭代计算?如果融合乘加运算 (FMA) 可用(通过标准数学函数fma()和公开),则应对算法进行哪些更改fmaf()?
我目前正在研究余弦的近似值。由于最终目标设备是使用 32 位浮点 ALU / LU 的自行开发,并且有专门的 C 编译器,因此我无法使用 C 库数学函数(cosf,...)。我的目标是编写在准确性和指令/周期数量方面不同的各种方法。
我已经尝试了很多不同的近似算法,从 fdlibm、泰勒展开、pade 近似、使用枫树的 remez 算法等开始......
但是,一旦我仅使用浮点精度来实现它们,就会显着降低精度。并且可以肯定:我知道双精度,更高的精度完全没有问题......
现在,我有一些近似值,在 pi/2(出现最大误差的范围)附近精确到几千 ulp,我觉得我受到单精度转换的限制。
为了解决主题参数减少:输入是弧度。我认为参数减少会由于除法/乘法而导致更多的精度损失......因为我的整体输入范围只有 0..pi,我决定将参数减少到 0..pi/2。
因此,我的问题是:有没有人知道高精度(并且在最好的情况下效率高)余弦函数的单精度近似值?是否有任何算法可以优化单精度的近似值?你知道内置的 cosf 函数是否在内部计算单精度双精度的值吗?~
float ua_cos_v2(float x)
{
float output;
float myPi = 3.1415927410125732421875f;
if (x < 0) x = -x;
int quad = (int32_t)(x*0.63661977236f);//quad = x/(pi/2) = x*2/pi
if (x<1.58f && x> 1.57f) //exclude approximation around pi/2
{
output = -(x - 1.57079637050628662109375f) - 2.0e-12f*(x - 1.57079637050628662109375f)*(x - 1.57079637050628662109375f) + 0.16666667163372039794921875f*(x - 1.57079637050628662109375f)*(x - 1.57079637050628662109375f)*(x - 1.57079637050628662109375f) …Run Code Online (Sandbox Code Playgroud) c floating-point trigonometry approximation single-precision
我尝试使用以下方法计算 clog(a + i*b) 的实部
将“x”视为复数。x = a + i*b 令 z 为 x 的复数对数。
实数(x) = 0.5 * log(a^2 + b^2)
这种方法在 ULP 方面会产生巨大的误差,特别是对于 0.5 和 1.0 之间的值。
我尝试了其他方法来避免实部和虚部的平方,例如
设 t = b / a;实数(x) = log(a) + 0.5 * log1p(t*t)
使用此方法时错误仍然存在。我知道错误可能来自 a 和 b 的平方,因此我尝试使用fma()操作来获取由于 'a' 和 'b' 的平方引起的错误
令 a2 = a * a b2 = b * b
err_a2 = fma(a,a, -a2)
err_b2 = fma(b,b,-b2)
然后我尝试0.5 * log(((err_a1 + err_b2) + a2) + …