Swift Numerics 库在 2019 年底就开源了,它主要聚焦于浮点数的各类常规计算,下面我们简单看看有些什么内容。
概述
Swift Numerics 抽象了两种数据类型:实数与复数,分别通过 Real 协议和 Complex 结构体来表示,同时 Complex 又是基于 Real 协议来定义的。
Real 协议
Real 是使用 Swift 协议的一个很好范例,它充分展示了如何对现有的类型进行扩展与组合,创造出更强大的功能。
Real 协议定义了一个实数浮点数常用的各类计算方法集合,这些方法底层都是系统内置方法,但是不够通用,无法支持 Swift 范型特性,对新的浮点数类型支持不够友好,写起来很不 Swift,这些都是 Real 协议在设计时重点解决的问题。
协议链
下面简单看看 Real 协议的关系链,看看它是如何构建的:
Real 协议组合了 3 个协议:FloatingPoint, RealFunctions, AlgebraicField。
FloatingPoint 以及它所继承的 SignedNumeric, AdditiveArithmetic 都是标准库中的内置协议,使 Real 可以直接沿用现有的浮点数特性。
而在这个项目中新增的 AlgebraicField, RealFunctions, ElementaryFunctions 这几个协议是 Real 协议对实数这个概念更完善的封装。
最后在项目中对 Double, Float, Float80, Float16 这几个类型都实现了 Real 协议,这几个常用的浮点数类型就可以无缝的支持 Real 所带来的实数特性。
实数
Real 对实数概念的封装体现在如下两个方面:
- 代数数域的定义:在数学中代数数域的首要特性就是支持四则运算,而 AlgebraicField 协议主要就是定义了四则运算方法,它在 SignedNumeric 协议的基础上增加了除法计算。
- 指数、三角函数、对数、平方根等浮点运算:这些方法是浮点数用的最多的地方,在图形、动画、AR等领域都有很多的应用。ElementaryFunctions 协议即支持了其中最常用的方法, RealFunctions 协议进一步扩展了一些方法组成了最完整的浮点数方法集合。
Real 协议自带方法
Real 协议自身提供的方法并不多,大部分方法都在其他 3 个协议里,方法如下:
- exp10(_:) 以10 为底的指数计算
- cosMinusOne(_:) cos(x) - 1 的另一种计算方式,可保留精度。
- signGamma(_:) 伽马函数的符号(正负)
- mulAdd(:::) 计算 a*b + c
- sqrt(_:) 平方根计算
ElementaryFunctions 协议
ElementaryFunctions 协议提供了指数、三角函数、对数、平方根等运算,都是浮点数中比较常规的计算,同时它是基于 AdditiveArithmetic 协议的,因此也支持加减运算。它支持的方法如下:
- exp(_:) 指数计算,以自然对数为底。
- expMinusOne(_:) exp(x) - 1,比 exp(x)提供更好精度。
- cosh(_:) 双曲余弦函数
- sinh(_:) 双曲正弦函数
- tanh(_:) 双曲正切函数
- cos(_:) 余弦函数
- sin(_:) 正弦函数
- tan(_:) 正切函数
- log(_:) 自然对数计算
- log(onePlus:_) log(1 + x), 比 log(x)提供更好精度。
- acosh(_:) 反双曲余弦函数
- asinh(_:) 反双曲正弦函数
- atanh(_:) 反双曲正切函数
- acos(_:) 反余弦函数
- asin(_:) 反正弦函数
- atan(_:) 反正切函数
- pow(::) 指数的另一种计算方式,与 exp(y * log(x)) 等价,但精度不同。
- pow(::Int) 幂运算
- sqrt(_:) 平方根计算
- root(::) 计算次方根
RealFunctions 协议
RealFunctions 协议在 ElementaryFunctions 基础上又扩展了一些不太常用的方法,有兴趣的可以去详细了解一下:
atan2(y:x:)
erf(_:)
erfc(_:)
exp2(_:)
exp10(_:)
hypot(_:_:)
gamma(_:)
log2(_:)
log10(_:)
logGamma(_:)
signGamma(_:)
_mulAdd(_:_:_:)
Complex 结构体
Complex 定义了数学上复数的一些基础属性及方法,通过两个都遵守 Real 协议的值 x, y 分别表示实数与虚数部分,具体用法比较简单,可以大概看看:
仓库使用
如果是使用 Xcode 11 及以上,直接在工程的 project 设置中添加一个 package 即可,地址:github.com/apple/swift…, 选择 0.0.8 版本。
模块引用
目前该项目提供了两大模块:
- RealModule
- ComplexModule
同时提供了这两个模块的统一封装模块 Numerics, 既可单独使用这两个模块,也可统一使用 Numerics:
import RealModule
import ComplexModule
import Numerics // 不需要再引入上面两个模块
总结
Swift 开源库现在四面开花,使用场景也越来越丰富了,这个库向我们展示了协议的优雅使用方式,这些都可以指导我们写的 Swift 越来越原汁原味。