当允许使用的唯一浮点指令是387个时,几乎不可能(*)以合理的成本提供严格的IEEE 754语义.当希望保持FPU在完整的64位有效数字上工作时,这一点特别困难,因此该long double类型可用于扩展精度.通常的"解决方案"是以唯一可用的精度进行中间计算,并在或多或少明确定义的场合转换为较低的精度.
根据Joseph S. Myers在2008年GCC邮件列表中发布的解释,GCC的最新版本处理中间计算中的过多精度.gcc -std=c99 -mno-sse2 -mfpmath=387据我所知,这个描述使程序编译完全可预测,到最后一点.如果它偶然没有,那就是一个错误而且它将被修复:约瑟夫S.迈尔斯在他的帖子中声明的意图是使其可预测.
是否记录了Clang如何处理超额精度(比如何时使用该选项-mno-sse2),以及在哪里?
(*)编辑:这是夸大其词.当允许将x87 FPU配置为使用53位有效数字时,这有点令人讨厌,但并不难以模拟binary64.
在下面的R ..评论之后,这里是我与Clang的最新版本之间的短暂互动的日志:
Hexa:~ $ clang -v
Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin12.4.0
Thread model: posix
Hexa:~ $ cat fem.c
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <fenv.h>
double x;
double y = 2.0;
double z = 1.0;
int main(){
x = y + z;
printf("%d\n", (int) FLT_EVAL_METHOD);
}
Hexa:~ $ clang …Run Code Online (Sandbox Code Playgroud) 是否有一个OCaml库可以利用IA-32和x86-64架构上的80位扩展精度浮点类型?
我知道MPFR绑定,但我理想的库会更轻量级.利用历史浮点指令将是理想的.
有一个现有的问题“3 个长整数的平均值”,它特别关注三个有符号整数的平均值的有效计算。
然而,无符号整数的使用允许额外的优化不适用于上一个问题中涵盖的场景。这个问题是关于三个无符号整数的平均值的有效计算,其中平均值向零舍入,即在数学术语中我想计算?(a + b + c) / 3 ?。
计算此平均值的一种直接方法是
avg = a / 3 + b / 3 + c / 3 + (a % 3 + b % 3 + c % 3) / 3;
Run Code Online (Sandbox Code Playgroud)
首先,现代优化编译器会将除法转换为具有倒数加移位的乘法,并将模运算转换为反向乘法和减法,其中反向乘法可能使用许多体系结构上可用的scale_add习语,例如leax86_64的,add用lsl #n在ARM,iscadd在NVIDIA GPU。
在尝试以适用于许多常见平台的通用方式优化上述内容时,我观察到整数运算的成本通常在逻辑关系中?(添加|子)?转移?规模_添加?MUL。这里的成本是指所有延迟、吞吐量限制和功耗。当处理的整数类型比本地寄存器宽度更宽时,例如在uint64_t32 位处理器上处理数据时,任何此类差异都会变得更加明显。
因此,我的优化策略是尽量减少指令数量,并在可能的情况下用“廉价”操作替换“昂贵”操作,同时不增加寄存器压力并为宽无序处理器保留可利用的并行性。
第一个观察结果是,我们可以通过首先应用产生和值和进位值的 CSA(进位保存加法器)将三个操作数的和减少为两个操作数的和,其中进位值的权重是和的两倍价值。在大多数处理器上,基于软件的 CSA 的成本是五个逻辑s。一些处理器,如 …
c algorithm bit-manipulation micro-optimization extended-precision
gcc是否支持amd64上的128位int?
如何定义?
如何使用scanf/printf进行读/写?
data Double双精度浮点数.希望这种类型在范围和精度上至少与IEEE双精度类型相同.
GHC/Haskell是否也提供扩展精度(80位)浮点数,也许使用一些外部库?
floating-point haskell ghc floating-point-precision extended-precision
我想获得在c中添加两个无符号64位整数的进位位。如果需要,我可以使用x86-64 asm。码:
#include <stdio.h>
typedef unsigned long long llu;
int main(void){
llu a = -1, b = -1;
int carry = /*carry of a+b*/;
llu res = a+b;
printf("a+b = %llu (because addition overflowed), carry bit = %d\n", res, carry);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 以下是插值函数的两种实现.争论u1始终在0.和之间1..
#include <stdio.h>
double interpol_64(double u1, double u2, double u3)
{
return u2 * (1.0 - u1) + u1 * u3;
}
double interpol_80(double u1, double u2, double u3)
{
return u2 * (1.0 - (long double)u1) + u1 * (long double)u3;
}
int main()
{
double y64,y80,u1,u2,u3;
u1 = 0.025;
u2 = 0.195;
u3 = 0.195;
y64 = interpol_64(u1, u2, u3);
y80 = interpol_80(u1, u2, u3);
printf("u2: %a\ny64:%a\ny80:%a\n", u2, y64, y80);
}
Run Code Online (Sandbox Code Playgroud)
在具有80位 …
我目前正在研究进行多精度浮点运算的代码.为了正常工作,该代码要求在明确定义的点处将值降低到最终精度.因此,即使将中间结果计算到80位扩展精度浮点寄存器,在某些时候也必须将其四舍五入为后续操作的64位双精度.
代码使用宏INEXACT来描述此要求,但没有完美的定义.在GCC手册中提到-fexcess-precision=standard的办法迫使流延和赋值操作定义良好的精度.但是,它还写道:
对于C以外的语言,未实现"-fexcess-precision = standard"
现在我正在考虑将这些想法移植到C++(如果有人知道现有的实现,则欢迎评论).所以我似乎无法将该开关用于C++.但是没有任何开关的g ++默认行为是什么?是否有更多类似C++的方法来控制过度精度的处理?
我想对于我目前的用例,我可能会-mfpmath=sse在任何情况下使用,据我所知,这不应该产生任何过多的精度.但我仍然很好奇.
c++ floating-point gcc floating-point-precision extended-precision
SSE/AVX寄存器可以被视为整数或浮点BigNums.也就是说,人们可以忽视存在通道.是否有一种简单的方法可以利用这种观点并将这些寄存器单独或组合用作BigNum?我问,因为我从BigNum库中看到的很少,它们几乎普遍存储并对数组进行算术运算,而不是SSE/AVX寄存器.可移植性?
例:
假设您将SSE寄存器的内容存储为a中的键std::set,您可以将这些内容作为BigNum进行比较.
如何将扩展精度浮点值转换为字符串?
Intel CPU支持三种浮点格式:
Delphi本身支持Extended精度浮点格式.
扩展精度分为:
0.或开头1.)您可以将Extended的尾数大小与其他float类型的尾数进行比较:
| Type | Sign | Exponent | Integer | Mantissa |
|----------|-------|----------|---------|----------|
| Single | 1 bit | 8 bits | n/a | 23 bits |
| Double | 1 bit | 11 bits | n/a | 52 bits |
| Extended | 1 bit | 15 bits | 1 bit | 63 bits |
Run Code Online (Sandbox Code Playgroud)
扩展能够实现单倍和双倍的更高精度. …