GCC对四精度浮点型的支持

本文详细介绍了GCC编译器提供的__float128型浮点数类型及其与quadmath库的集成使用方法。包括如何在程序中声明、初始化、输入输出__float128型数,以及如何利用quadmath库中的高级数学函数进行高效计算。特别强调了这种类型与双精度float型相比的优势以及在计算精度上的显著提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C语言标准中只提供了float型和double 型两种浮点类型。但是有些情况下,我们需要比double 型更大数据范围或更多的有效位数,为此,GCC 为我们提供了__float128型浮点类型。这种扩展类型可以表示的数据范围非常大,大约为-10e4932到10e4932,可以表示的最接近0的数大约为3.36*e-4932,可以表示的10进制有效位大约为33位。比起double 类型,无论是数据范围还是精度都有了一个极大的提升。当然,由于现在日常使用的计算机的CPU的浮点处理器不能直接对__float128进行运算,所以即使是两个简单的__float128型变量相加运算都要耗费CPU的相当多条指令来完成。因此程序中使用__float128 型后运算速度会降低很多。


除了对__float128数据类型的支持之外,GCC还提供一个GCC Quad-PrecisionMath Library(简称为quadmath),里面提供了基本数学函数库中相应函数的__float128型的版本。


下面简单的讲讲如何在程序中使用__float128数据和quadmath库。


首先,__float128 型和各种相关的函数声明在了 quadmath.h 中。因此,如果要在C程序中使用__float128 型浮点数就要包含这个头文件。相应的处理函数打包在了 libquadmath.o 中,为此,在最后链接(link)阶段要包括这个库文件,也就是加入链接命令行参数 -lquadmath。


除了 __float128 型,还有 __complex128 型,它是complex 型向4精度浮点型的升级。


基本输入输出

既然有了__float128类型,就要提供对这种类型的输入输出的支持。GCC扩展了C语言的标准,增加了以Q结尾的__float128类型的数值常量。比如下面的例子:


__float128 a = 1.23456789012345Q;

还提供了两个函数以支持__float128类型与字符串间的转换:

__float128 strtoflt128 (const char *s, char **sp)
int quadmath_snprintf (char *str, size_t size, const char *format, ...)

strtoflt128 函数是 strtod 函数的__float128类型版本,参数类型与strtod 函数完全一样,只不过返回值是__float128类型。

quadmath_snprintf 函数是snprintf的__float128类型版本。通过在传统的解析字符串中增加了字符Q来表示__float128类型,比如“%f”表示的读取一个浮点数,“%Qf”则是读取一个__float128类型的数据。除了“%Qf”之外,还可以用“%QF”、“%Qe”、“%QE”、“%Qg”、“%QG”。

Quadmath 库中包含的数学函数如下,基本上就是对应的double 类型的函数的函数名后加了后缀q。因此,每个函数的含义就不一一解释了。

__float128 acosq (__float128)
 __float128 acoshq (__float128)
 __float128 asinq (__float128)
 __float128 asinhq (__float128)
 __float128 atanq (__float128)
 __float128 atanhq (__float128)
 __float128 atan2q (__float128, __float128)
 __float128 cbrtq (__float128)
 __float128 ceilq (__float128)
 __float128 copysignq (__float128, __float128)
 __float128 coshq (__float128)
 __float128 cosq (__float128)
 __float128 erfq (__float128)
 __float128 erfcq (__float128)
 __float128 expq (__float128)
 __float128 expm1q (__float128)
 __float128 fabsq (__float128)
 __float128 fdimq (__float128, __float128)
 int finiteq (__float128)
 __float128 floorq (__float128)
 __float128 fmaq (__float128, __float128, __float128)
 __float128 fmaxq (__float128, __float128)
 __float128 fminq (__float128, __float128)
 __float128 fmodq (__float128, __float128)
 __float128 frexpq (__float128, int *)
 __float128 hypotq (__float128, __float128)
 int isinfq (__float128)
 int ilogbq (__float128)
 int isnanq (__float128)
 __float128 j0q (__float128)
 __float128 j1q (__float128)
 __float128 jnq (int, __float128)
 __float128 ldexpq (__float128, int)
 __float128 lgammaq (__float128)
 long long int llrintq (__float128)
 long long int llroundq (__float128)
 __float128 logq (__float128)
 __float128 log10q (__float128)
 __float128 log2q (__float128)
 __float128 log1pq (__float128)
 long int lrintq (__float128)
 long int lroundq (__float128)
 __float128 modfq (__float128, __float128 *)
 __float128 nanq (const char *)
 __float128 nearbyintq (__float128)
 __float128 nextafterq (__float128, __float128)
 __float128 powq (__float128, __float128)
 __float128 remainderq (__float128, __float128)
 __float128 remquoq (__float128, __float128, int *)
 __float128 rintq (__float128)
 __float128 roundq (__float128)
 __float128 scalblnq (__float128, long int)
 __float128 scalbnq (__float128, int)
 int signbitq (__float128)
 void sincosq (__float128, __float128 *, __float128 *)
 __float128 sinhq (__float128)
 __float128 sinq (__float128)
 __float128 sqrtq (__float128)
 __float128 tanq (__float128)
 __float128 tanhq (__float128)
 __float128 tgammaq (__float128)
 __float128 truncq (__float128)
 __float128 y0q (__float128)
 __float128 y1q (__float128)
 __float128 ynq (int, __float128)


/* Prototypes for complex functions */
 __float128 cabsq (__complex128)
 __float128 cargq (__complex128)
 __float128 cimagq (__complex128)
 __float128 crealq (__complex128)
 __complex128 cacosq (__complex128)
 __complex128 cacoshq (__complex128)
 __complex128 casinq (__complex128)
 __complex128 casinhq (__complex128)
 __complex128 catanq (__complex128)
 __complex128 catanhq (__complex128)
 __complex128 ccosq (__complex128)
 __complex128 ccoshq (__complex128)
 __complex128 cexpq (__complex128)
 __complex128 cexpiq (__float128)
 __complex128 clogq (__complex128)
 __complex128 clog10q (__complex128)
 __complex128 conjq (__complex128)
 __complex128 cpowq (__complex128, __complex128)
 __complex128 cprojq (__complex128)
 __complex128 csinq (__complex128)
 __complex128 csinhq (__complex128)
 __complex128 csqrtq (__complex128)
 __complex128 ctanq (__complex128)
 __complex128 ctanhq (__complex128) 
下面举一个简单的例子:
#include <stdio.h>
#include <stdlib.h>
#include <quadmath.h>
int main(void)
{
    __float128 r1;
    __float128 r2;
    __float128 r3;

    char buf[64];
    char *pEnd = buf;
    r1 = strtoflt128 ("1.234567890123456789   9.876543210987654321e5", &pEnd);
    r2 = strtoflt128 (pEnd, NULL);

    quadmath_snprintf (buf, sizeof buf, "%+-#*.20Qf", 64, r1);
    puts(buf);
    quadmath_snprintf (buf, sizeof buf, "%+-#*.20Qe", 64, r2);
    puts(buf);

    r3 = hypotq (r1, r2);
    quadmath_snprintf (buf, sizeof buf, "%.30Qe", 64, r3);
    puts(buf);
    return 0;
}


输出的结果为:

+1.23456789012345678900

+9.87654321098765432100e+05

9.876543210995370370242956091483e+05

 

结果是否准确,我们可以用 maxima 来验算一下:

fpprec:35$

r1:bfloat(1.234567890123456789b0)$

r2:bfloat(9.876543210987654321b05)$

r3:sqrt(r1*r1+r2*r2);

(%o4) 9.8765432109953703702429560914832608b5

 

小数点后30位全都是正确的。说明quadmath 库的计算精度还是相当不错的,至少hypotq函数的精度相当高。

__float128型浮点不是C语言标准类型,因此这里的介绍只对GCC编译器成立。另外,我使用的gcc的版本信息如下:

COLLECT_GCC=gcc

COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/4.6.1/lto-wrapper.exe

mingw32

../gcc-4.6.1/configure--enable-languages=c,c++,fortran,objc,obj-c++ --disable-sjlj-exceptions--with-dwarf2 --enable-shared --enable-libgomp --disable-win32-registry--enable-libstdcxx-debug --enable-version-specific-runtime-libs --build=mingw32--prefix=/mingw

win32

gcc 4.6.1 (GCC)

 

其他版本的GCC 运行的结果不一定与这里相同。

如果需要更高的计算精度,就要考虑一些专用的多精度数值计算库了,比如大名鼎鼎的GMP。




<think>我们正在讨论双精度浮点运算单元(FPU)的实现代码下载。根据之前的对话,Falcon算法中双精度FPU用于加速高斯采样和NTT预处理计算。现在用户希望查找或下载双精度浮点运算单元相关的工具、模型或实现代码。 参考引用: [1] 提到在MCU中集成硬件浮点运算单元(如Cortex-M4F)可以提高效率和精度。 [2] 提到IEEE 754标准是设计FPU的基础,并提到了Verilog实现高效浮点运算单元设计。 [3] 提到ARM处理器的浮点运算单元(FPU)如VFPv3。 因此,我们可以从以下几个方面提供资源: 1. 开源硬件实现(Verilog/VHDL代码)—— 符合IEEE 754标准的双精度FPU。 2. 软件仿真库(用于在没有硬件FPU的处理器上模拟双精度浮点运算)。 3. ARM的FPU(VFP)相关文档和工具。 具体推荐: 一、开源硬件实现(RTL代码): 1. **Berkeley SoftFloat**:这是一个广泛使用的浮点库,提供多种精度的浮点运算,包括双精度。它用C语言编写,但可以用于硬件设计的参考,也可以集成到RTL设计中。 - 下载地址:http://www.jhauser.us/arithmetic/SoftFloat.html 2. **OpenCores上的FPU项目**:OpenCores是一个开源的硬件设计社区,上面有多个FPU项目,其中一些实现了双精度浮点运算单元。 - 例如:https://opencores.org/projects/fpu - 另一个项目:https://opencores.org/projects/double_fpu 3. **floating-point-unit**:一个用Verilog实现的双精度浮点运算单元,支持基本的加减乘除运算。 - GitHub地址:https://github.com/dawsonjon/fpu 4. **IEEE754-FPU**:一个符合IEEE 754标准的浮点运算单元,支持精度和双精度。 - GitHub地址:https://github.com/nturley/ieee754-fpu 二、软件仿真库: 1. **SoftFloat**:同样适用于软件仿真,可以在没有硬件FPU的平台上使用。 2. **libfixmath**:虽然主要针对定点数,但也包含一些浮点仿真功能。 3. **GCC的软浮点库**:GCC编译器内置的软浮点支持,通过编译选项(如`-msoft-float`)使用。 三、ARM相关: 1. ARM官方提供了VFP和NEON的文档,以及相关的工具链支持。 - 文档:https://developer.arm.com/documentation/ddi0406/latest - 工具链(GCC for ARM)已经包含对VFP的支持,编译时使用选项`-mfpu=vfpv3`(根据具体版本)来使用硬件FPU。 、FPGA厂商提供的FPU IP核: 1. Xilinx和Intel(Altera)都提供了FPU的IP核,但通常需要商业许可。不过,他们也有免费评估版本。 五、测试工具: 1. **FPgen**:一个浮点运算单元测试生成器,用于验证FPU设计的正确性。 - 下载:https://github.com/coruus/fpgen 六、模拟器: 1. **QEMU**:可以模拟带有FPU的处理器,用于测试软件。 下载步骤示例(以Berkeley SoftFloat为例): 1. 访问 http://www.jhauser.us/arithmetic/SoftFloat.html 2. 下载最新版本的SoftFloat(如SoftFloat-3e)。 3. 解压缩后,阅读文档(doc/SoftFloat.html)了解使用方式。 注意:硬件实现代码(Verilog/VHDL)通常需要仿真工具(如ModelSim)进行测试,并综合到FPGA或ASIC。 如果用户希望使用ARM的FPU,那么不需要下载代码,而是使用编译器选项来生成使用硬件FPU的代码。 总结:根据用户需求,如果是要硬件实现,则推荐OpenCores或GitHub上的开源项目;如果是软件仿真,则推荐SoftFloat库。 相关问题: 1. 如何验证双精度浮点运算单元的正确性? 2. 在嵌入式系统中如何启用硬件双精度FPU? 3. 双精度浮点运算单元在ASIC和FPGA实现中有何不同?</think>以下是双精度浮点运算单元(FPU)相关的开源实现、工具和代码资源,按类型分类整理: --- ### 一、开源硬件实现(Verilog/VHDL) 1. **IEEE 754双精度FPU核** - **项目地址**:[GitHub - dawsonjon/fpu](https://github.com/dawsonjon/fpu) - 支持加减乘除、平方根运算 - 完全兼容IEEE 754-2008标准 - 包含完整的测试平台(Testbench) - **下载方式**: ```bash git clone https://github.com/dawsonjon/fpu.git ``` 2. **Berkeley SoftFloat** - **项目地址**:[John Hauser's SoftFloat](http://www.jhauser.us/arithmetic/SoftFloat.html) - 提供C语言参考实现和Verilog移植版 - 支持单/双精度及扩展精度 - 包含完备的验证套件 - **下载**:官网直接下载ZIP包 3. **OpenCores FPU** - **项目地址**:[OpenCores Double Precision FPU](https://opencores.org/projects/double_fpu) - 支持精度基本运算 - 优化流水线设计(5级流水) - 提供FPGA综合报告 --- ### 二、软件仿真库 1. **SoftFloat(纯软件实现)** - **应用场景**:无硬件FPU的嵌入式系统 - **集成示例**: ```c #include "softfloat.h" double d_add(double a, double b) { float64_t fa = f64(a); float64_t fb = f64(b); return f64_to_double(f64_add(fa, fb)); } ``` 2. **GCC软浮点库** - 编译器选项:`-msoft-float` - 自动链接软件浮点库(libgcc) --- ### 三、ARM架构专用资源 1. **VFPv3-D32/NEON开发包** - **工具链**:ARM Development Studio - 包含双精度FPU指令集模拟器 - 下载地址:[ARM DS-5 Development Studio](https://developer.arm.com/Tools%20and%20Software/Development%20Studio%205) - **启用方法**(GCC编译选项): ```bash -mfloat-abi=hard -mfpu=neon-fp64 ``` 2. **Linux内核FPU支持** - 内核配置选项:`CONFIG_VFPv3` - 用户态访问示例: ```c #include <fpu_control.h> fpu_control_t cw = _FPU_DEFAULT; _FPU_SETCW(cw); ``` --- ### 、验证与测试工具 1. **FPGen测试生成器** - **功能**:自动生成IEEE 754合规性测试向量 - **地址**:[GitHub - FPGen](https://github.com/coruus/fpgen) 2. **Cocotb测试框架** - **应用**:FPU的硬件仿真验证 - **示例**: ```python from cocotb.triggers import Timer await Timer(100, units="ns") # 验证运算延迟 ``` --- ### 五、FPGA参考设计 1. **Xilinx FPU IP核** - **资源**:[Xilinx Floating-Point Operator](https://www.xilinx.com/products/intellectual-property/floating-point.html) - 特性: - 支持精度矩阵运算 - 可配置流水线级数 2. **Intel FPGA Math Library** - **下载**:[Intel FPGA DSP Builder](https://www.intel.com/content/www/us/en/software/programmable/quartus-prime/dsp-builder.html) --- ### 六、实用工具推荐 | 工具名称 | 类型 | 适用场景 | 链接 | |-------------------|------------|--------------------------|------------------------------------------| | Verilator | 仿真工具 | RTL功能验证 | [verilator.org](https://verilator.org) | | GTKWave | 波形查看器 | 时序分析 | [gtkwave.sourceforge.io](http://gtkwave.sourceforge.io) | | Icarus Verilog | 仿真器 | 轻量级RTL测试 | [iverilog.icarus.com](http://iverilog.icarus.com) | --- ### 下载与使用示例 **以GitHub项目为例**: ```bash # 克隆FPU仓库 git clone https://github.com/dawsonjon/fpu.git cd fpu/verilog # 使用Icarus编译 iverilog -o fpu_test fpu.v tb_fpu.v # 运行测试 vvp fpu_test gtkwave dump.vcd # 查看波形 ``` ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值