我正在使用 MPFR 多精度库,特别是这里的实现。
有什么方法可以编译代码以使所有操作都使用标准类型(例如double
)执行?例如,将所有“软件操作”转换为通常以标准类型实现的“硬件操作”的编译标志?
在实践中,即使我使用 64 位,代码也很慢,我分析说罪魁祸首是 mpfr/gmp,我想通过更改为来衡量我获得了多少double
(无需重新编写所有代码)。
由于多种原因,这在 MPFR 库中是不可能的。首先格式不同。特别是,MPFR 具有不同的指数范围,没有次正规,单个 NaN……此外,它在 5 种舍入模式下提供正确的舍入,而处理器只有 4 种舍入模式,并且对于本机类型,大多数操作都没有正确舍入。
您可能想要编写包装器、C++ 类或任何您想做的事情,但这并不一定很有趣,因为您可能会在两种格式之间进行许多转换。
编辑:如果您不关心确切的行为,也许您想要的是基于 C++ 模板的东西。您可能需要查看另一个 C++ MPFR 接口,例如MPFRCPP或mpfr::real class。
据我了解,您提到的实现(来自 Pavel Holoborodko 的MPFR C++)使用运算符重载使 MPFR 调用看起来像标准的 C 浮点操作,来自站点:
//MPFR C - version
void mpfr_schwefel(mpfr_t y, mpfr_t x)
{
mpfr_t t;
mpfr_init(t);
mpfr_abs(t,x,GMP_RNDN);
mpfr_sqrt(t,t,GMP_RNDN);
mpfr_sin(t,t,GMP_RNDN);
mpfr_mul(t,t,x,GMP_RNDN);
mpfr_set_str(y,“418.9829“,10,GMP_RNDN);
mpfr_sub(y,y,t,GMP_RNDN);
mpfr_clear(t);
}
可以这样写:
// MPFR C++ - version
mpreal mpfr_schwefel(mpreal& x)
{
return "418.9829"-x*sin(sqrt(abs(x)));
}
顺便说一句,这很酷,因此您只需稍作更改,例如替换"418.9829"
为418.9829
,并注释掉您的代码中包含的 MPFR。
如果您的代码仍有剩余的mpfr_...
调用,您可以通过在变量初始化中将 MPFR 精度设置为 53 位或使用特定函数mpfr_set_prec
(如完全相同:_ _ _
特别是,在 53 位精度和四种标准舍入模式中的任何一种情况下,MPFR 能够准确地再现所有使用双精度机器浮点数的计算(例如,C 中的 double 类型,使用严格的 C 实现)在四个算术运算和平方根上遵循 ISO C99 标准的附件 F 和 FP_CONTRACT pragma 设置为 OFF),除了默认指数范围更宽并且不实现次正规数(但可以模拟)。
这可能足以让您大致了解 MPFR 性能与原生浮点数的差异。
如果这还不够精确,您可以在包含 MPFR 之后将临时包含放入主文件中,其中define
s 会覆盖您使用的 MPFR 函数,或多或少像这样:
typedef double mpfr_t;
#define mpfr_add(a,b,c,r) {a=b+c;}