Adr*_*rox 5 c math gcc discrete-mathematics
晚安。我是一名数学学士,我正在学习 log() 和系列。而且我确实想看看 GCC 如何计算所有这些东西,它对我有很大帮助,math.h 里面什么都没有,我已经读过了。我疯狂地试图找到 GCC 如何使用有史以来最快的方法计算对数和平方根。我下载了源代码,但找不到数学例程在哪里。
https://github.com/gcc-mirror/gcc
我只是想看看,我根本不是一个好的程序员,我的东西是数学。
数学函数是 C 标准库的一部分,GCC 只使用这些函数。如果要查看源代码,可以从glibc官方网站下载源代码(用于 GNU C 库版本,这是最常用的版本之一),也可以使用在线代码浏览器。例如,这是代码log()。
既然你说你不是一个程序员,我怀疑你会发现 GNU C 标准库是可理解的。它是几十年优化和兼容性调整的结果,代码非常复杂。我建议采取看看MUSL C库代替。源代码更简洁,注释也更多。这是log()函数,这是关于数学函数的所有文件。
最后,GCC 或 C 库也没有“有史以来最快的方法”来计算此类函数。C 库的目标不是为每个数学函数提供尽可能最快的实现,而是提供足够好的实现,同时仍然具有足够的可移植性以用于多种体系结构,因此它们仍然非常快,但很可能不是“有史以来最快的”。在最好的情况下,如果 CPU 支持快速的内置硬件数学运算(例如 Intel x86 with fsqrtfor the square root),则某些数学函数甚至可以简化为单个 CPU 指令。
小智 2
看看这个日志的实现。
这是来自fdlibm ,它为人类提供了许多 C 数学函数的实现(遵循IEEE-754 )。
从实施来看:
k并f使得 x = 2^k * (1+f),
where sqrt(2)/2 < 1+f < sqrt(2) .
Run Code Online (Sandbox Code Playgroud)
Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
= 2s + 2/3 s**3 + 2/5 s**5 + .....,
= 2s + s*R
Run Code Online (Sandbox Code Playgroud)
[0,0.1716]生成 14 次多项式来近似。R该多项式近似的最大误差以 为界2**-58.45。换句话说, 2 4 6 8 10 12 14
R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
(the values of Lg1 to Lg7 are listed in the program)
Run Code Online (Sandbox Code Playgroud)
和
| 2 14 | -58.45
| Lg1*s +...+Lg7*s - R(z) | <= 2
| |
Run Code Online (Sandbox Code Playgroud)
注意2s = f - s*f = f - hfsq + s*hfsq,哪里hfsq = f*f/2。为了保证下面日志中的错误1ulp,我们通过以下方式计算日志
log(1+f) = f - s*(f - R) (if f is not too large)
log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
Run Code Online (Sandbox Code Playgroud)
log(x) = k*ln2 + log(1+f).
= k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
Run Code Online (Sandbox Code Playgroud)
ln2分为两个浮点数: ln2_hi + ln2_lo,
Run Code Online (Sandbox Code Playgroud)
其中n*ln2_hi总是精确的|n| < 2000。
真实的实现和特殊情况的解释你可以在这个链接中查看。