双精度数

四倍精度数 (QDouble) 是四个 IEEE 双精度浮点数的未计算和,能够表示至少 212 位或 62 位有效数字。 二次双精度数 (DDouble) 也可用,它具有双精度数的两倍精度,精度为 31 位数字(106 位),但速度比 QDouble 快。 由于使用了 FP 硬件,因此计算速度比等效的软件实现快得多。 介绍了各种算术运算(包括四个基本运算以及各种代数和超越运算)的算法。 附带了这些算法的 Swift 实现及其接口。 请报告和/或修复任何错误。

如果有人能够加快 Swift 基准测试的速度以匹配 C++ 基准测试(请参阅原始软件包 https://www.davidhbailey.com/dhbsoftware/qd-2.3.23.tar.gz),也将不胜感激。 我花了一些时间来尝试这样做,但没有成功。 我怀疑类型检查或其他与安全相关的机制存在一些固有的开销,而 C++ 没有这些开销。 可惜这些检查无法在性能关键的代码中关闭。

从 Yozo Hida、Xiaoye S. Li 和 David H. Bailey 的名为 qd-2.3.15 的原始作品翻译成 Swift。错误修复已从 qd-2.3.22 合并 - MG - 2019 年 3 月 24 日。

它的文档是使用 DocC 插件构建的,并发布在 GitHub Pages 上的这个位置

https://mgriebling.github.io/Doubles/documentation/doubles

该文档也可以在 *Doubles.doccarchive* 文件中找到。

注意:源代码是从原始作品翻译而来,该作品的版权为:Copyright (c) 2003-2009, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from U.S. Dept. of Energy) 保留所有权利。

Swift 示例

import Doubles

let x = QDouble("12345678901234567890123456789012345678901234567890123456789012")
let y = 123456789012345678901234567890.0
let two : QDouble = 2
let ptOne = QDouble("0.1")
     
print("QDouble precision \(x)\nDouble precision  \(y)")
print("Sqrt(2) = \(two.sqrt())")
print("2^1000 = \(two.pow(1000))")
print("Sqrt(\(x)^2) = \(x.sqr().sqrt())")
print("π = \(QDouble.pi)")
print("1/3 = \(QDouble(1)/3)")
print("sqrt(0.1) = \(ptOne.sqrt())")
print("sqrt(0.1)^2 = \(ptOne.sqrt().sqr())")
print("Comparison operations: \(x) == \(y) -> \(x == QDouble.zero+y)")

相应的输出

QDouble precision 1.23456789012345678901234567890123456789012345678901234567890120e+61
Double precision  1.2345678901234568e+29
Sqrt(2) = 1.41421356237309504880168872420969807856967187537694807317667974e+00
2^1000 = 1.07150860718626732094842504906000181056140481170553360744375039e+301
Sqrt(1.23456789012345678901234567890123456789012345678901234567890120e+61^2) = 1.23456789012345678901234567890123456789012345678901234567890120e+61
π = 3.14159265358979323846264338327950288419716939937510582097494459e+00
1/3 = 3.33333333333333333333333333333333333333333333333333333333333333e-01
sqrt(0.1) = 3.16227766016837933199889354443271853371955513932521682685750485e-01
sqrt(0.1)^2 = 1.00000000000000000000000000000000000000000000000000000000000000e-02
Comparison operations: 1.23456789012345678901234567890123456789012345678901234567890120e+61 == 1.2345678901234568e+29 -> false

Swift 基准测试

以下是来自 3.6GHz 10 核 Intel Core i9 的一些基准测试

Double 的计时

操作 时间 MOPs
加法 0.000212 微秒 4705.8824 mop/s
乘法 0.000215 微秒 4651.1628 mop/s
除法 0.000748 微秒 1337.7926 mop/s
平方根 0.001200 微秒 833.3333 mop/s
正弦 0.018250 微秒 54.7945 mop/s
对数 0.001000 微秒 1000.0000 mop/s
点积 0.000214 微秒 4678.3626 mop/s
指数 0.001000 微秒 1000.0000 mop/s
余弦 0.030750 微秒 32.5203 mop/s

DDouble 的计时

操作 时间 MOPs
加法 0.012675 微秒 78.8955 mop/s
乘法 0.005585 微秒 179.0510 mop/s
除法 0.009395 微秒 106.4396 mop/s
平方根 0.042325 微秒 23.6267 mop/s
正弦 0.454000 微秒 2.2026 mop/s
对数 0.341000 微秒 2.9326 mop/s
点积 0.004325 微秒 231.2139 mop/s
指数 0.368000 微秒 2.7174 mop/s
余弦 0.460750 微秒 2.1704 mop/s

QDouble 的计时

操作 时间 MOPs
加法 0.053525 微秒 18.6829 mop/s
乘法 0.124817 微秒 8.0117 mop/s
除法 0.527525 微秒 1.8956 mop/s
平方根 1.626325 微秒 0.6149 mop/s
正弦 5.922500 微秒 0.1688 mop/s
对数 11.939000 微秒 0.0838 mop/s
点积 0.046288 微秒 21.6041 mop/s
指数 3.253000 微秒 0.3074 mop/s
余弦 5.614750 微秒 0.1781 mop/s

C++ 基准测试

double 的计时

操作 时间 MOPs
加法 0.000208 微秒 4819.2771 mop/s
乘法 0.000210 微秒 4761.9048 mop/s
除法 0.000733 微秒 1365.1877 mop/s
平方根 0.001150 微秒 869.5652 mop/s
正弦 0.007250 微秒 137.9310 mop/s
对数 0.005000 微秒 200.0000 mop/s
点积 0.000209 微秒 4790.4192 mop/s
指数 0.005000 微秒 200.0000 mop/s
余弦 0.007500 微秒 133.3333 mop/s

dd_real 的计时

操作 时间 MOPs
加法 0.002230 微秒 448.4305 mop/s
乘法 0.002975 微秒 336.1345 mop/s
除法 0.006390 微秒 156.4945 mop/s
平方根 0.011300 微秒 88.4956 mop/s
正弦 0.236500 微秒 4.2283 mop/s
对数 0.287000 微秒 3.4843 mop/s
点积 0.002363 微秒 423.2804 mop/s
指数 0.251000 微秒 3.9841 mop/s
余弦 0.254000 微秒 3.9370 mop/s

qd_real 的计时

操作 时间 MOPs
加法 0.021325 微秒 46.8933 mop/s
乘法 0.044258 微秒 22.5950 mop/s
除法 0.256070 微秒 3.9052 mop/s
平方根 0.666375 微秒 1.5007 mop/s
正弦 2.489750 微秒 0.4016 mop/s
对数 8.771000 微秒 0.1140 mop/s
点积 0.037615 微秒 26.5851 mop/s
指数 2.707000 微秒 0.3694 mop/s
余弦 2.527750 微秒 0.3956 mop/s