Plinth

Swift 硬件加速的矩阵/数值编程库。

let frumb: Matrix<Double> = .random(shape: .square(length: 4), in: -1.0...1.0)
let brumf = frumb <*> frumb.transposed()

安装

Swift Package Manager

只需将 Plinth 添加到您的 Package.swift 文件中

let package = Package(
    name: "Example",
    dependencies: [
        .package(url: "https://github.com/dclelland/Plinth.git", from: "2.0.0"),
    ],
    targets: [
        .target(name: "Example", dependencies: ["Plinth"])
    ]
)

然后将 Plinth 导入到您的 Swift 文件中

import Plinth

或者,为了完全支持 ComplexMatrix,您还应该导入 swift-numerics,因为 Complex 类型存在于其中。

import Plinth
import Numerics

链接

依赖项

参考/现有技术

待办事项

理念

Plinth 的理念是做“能工作的最简单的事情”。例如,许多算术/数值函数都实现了两次 - 针对 Matrix<Float>Matrix<Double> - 而不是通过协议和协议实现的沼泽来管理它,我们只需使用复制和粘贴来实现给定的函数两次。 Plinth 不是 DRY(不要重复自己)。

文档

类型

Shape

使用 rowscolumns 属性定义矩阵的形状。

public struct Shape {
    
    public let rows: Int
    public let columns: Int
    
}

这包括许多方便的属性,如 countlengthbreadth;以及方便的初始化器 .row(length:).column(length:).square(length:)

Matrix

具有 Scalar 类型参数以及 shapeelements 属性的泛型矩阵结构体。元素以行优先格式存储为单个数组。

public struct Matrix<Scalar> {
    
    public let shape: Shape
    public var elements: [Scalar]
    
}

这还包括大量的便利初始化器和典型类型类的实现,例如 CodableExpressibleByArrayLiteral

elements 属性是直接可变的,但理想情况下应该避免;除非在编码到或解码自序列化格式时,否则不会强制执行矩阵规则性。

存在一个计算属性 state,可用于检查矩阵是否被认为是畸形的

let malformed = Matrix<Double>(
    shape: .init(rows: 2, columns: 2),
    elements: [1.0, 2.0, 3.0, 4.0, 5.0]
)

print(malformed.state)
> Malformed: Mismatched shape and elements; 2×2 != 5

ComplexMatrix

泛型复数矩阵结构体,封装了 realimaginary 部分的两个单独的矩阵。

public struct ComplexMatrix<Scalar> where Scalar: Real {
    
    public var real: Matrix<Scalar>
    public var imaginary: Matrix<Scalar>
    
}

这还包括大量的便利初始化器和典型类型类的实现,例如 CodableExpressibleByArrayLiteral

realimaginary 属性也是直接可变的; ComplexMatrix 具有自己的 state 属性,可用于检查各个部分是否不匹配或畸形。

核心

算术

+- 前缀运算符以及 +-*/ 中缀运算符。

ScalarComplex<Scalar>Matrix<Scalar>ComplexMatrix<Scalar> 的组合实现快速逐点算术,其中 ScalarFloatDouble

转换

整数类型 UInt8UInt16UInt32Int8Int16Int32 和浮点类型 FloatDouble 之间的快速类型转换。

函子

用于对矩阵元素进行形状保留操作的高阶函数。

包括对 DSPSplitComplex/DSPDoubleSplitComplex 的复数矩阵运算的支持。

免责声明:这些不是真正的函子,Swift 缺少高阶类型...

子矩阵

使用 Swift 下标界面进行快速子矩阵读/写访问。

使用 Accelerate 的 vDSP_mmov/vDSP_mmovD

包装器

Accelerate 中大多数基本 vDSPvForce 函数的包装器。

变换

中心

给定舍入规则,找到矩阵的中心点。

裁剪

给定舍入规则,将矩阵向中心裁剪。

填充

给定舍入规则,从中心向外零填充矩阵。

重塑

将新形状应用于矩阵,或将其重塑为单行或单列。

这也支持 .rowMajor.columnMajor 排序。

移位

将循环移位应用于矩阵。

连接

按行或按列将多个矩阵连接在一起。

数学

比较

<, <=, >, >=, ==, !== 中缀运算符。

逐点比较或相等性检查,false 返回 0.0true 返回 1.0

插值

将值从给定范围线性插值到/从 0.0...1.0

这类似于 C++ 的 std::lerp

** 中缀运算符。

ScalarMatrix 实现快速逐点幂运算。

包括用于计算矩阵整数幂的特殊函数,以便在递归应用 vDSP.multiplyvForce.pow 更快时使用(这是一个非常昂贵的操作)。

这也支持负整数,通过将 vForce.reciprocal 应用于结果。

斜坡

生成从一系列值的开始到结束,沿笛卡尔或极坐标倾斜的矩阵。

统计

随机

使用 Swift 随机数生成器或 LAPACK 函数生成填充有随机噪声的矩阵,以便在设置的分布中更快地生成。

对于实矩阵,使用 LAPACK 的 slarnv_/dlarnv_,对于复数矩阵,使用 clarnv_/zlarnv_

高斯

使用 Swift 随机数生成器生成填充有高斯噪声的矩阵。

这源于 comp.lang.c FAQ 上的一个答案。

计算中心矩和标准化矩; variancestandardDeviationskewnesskurtosis 的便利方法。

标准化

使用其 minimum()maximum() 值将矩阵标准化为 0.0...1.0;或者移动它,使其 mean() 居中于零。

线性代数

生成填充有零的矩阵。

生成填充有 1 的矩阵。

单位

生成单位矩阵。

对角

生成对角矩阵。

转置

转置矩阵。

使用 Accelerate 的 vDSP_mtrans/vDSP_mtransD

求逆

计算矩阵的逆矩阵。

对于实矩阵,使用 LAPACK 的 sgetri_/dgetri_;对于复数矩阵,使用 cgetri_/zgetri_

乘法

<*> 中缀运算符。

实现矩阵乘法。

对于实矩阵,使用 Accelerate 的 vDSP_mmul/vDSP_mmulD;对于复数矩阵,使用 vDSP_zmmul/vDSP_zmmulD

除法

/></ 中缀运算符。

实现左右矩阵除法(乘以矩阵的逆矩阵)。

平方根

复数平方根。

公式取自 MATLAB 的 sqrt 函数。

指数

复数指数。

公式取自 MATLAB 的 exp 函数。

内积和外积。

特征分解

计算矩阵的特征分解。 包括仅计算必要组件的支持。 还包括通过特征值的属性对特征向量进行排序的支持。

使用 LAPACK 的 sgeev_/dgeev_。 Swift 实现抄袭自 Surge

通过获取伴随矩阵的特征值来计算多项式的根。

图像处理

位图

0.0...1.0 范围内的浮点格式与在 0...255 范围内的 8 位位图之间的转换。

图像

vImage.PixelBufferCGImageCIImageNSImageUIImage 之间的转换。

信号处理

FFT

正向和反向二维傅里叶变换。

包括对创建、重用和销毁您自己的 FFTSetup/FFTSetupD 结构的支持。

某些逆傅里叶变换方法通过除以矩阵的大小来实现能量守恒。

使用Accelerate 的 vDSP_fft2d_zip/vDSP_fft2d_zipD

FFTShift (傅里叶变换移位)

对频域矩阵应用循环旋转,使直流/直流信号位于右下象限的左上方。

FFTRamp (傅里叶变换斜坡)

生成与二维FFT布局对齐的斜坡,用于屏蔽二维FFT信号。

自相关

通过将频谱与其复共轭或幅度相乘,计算矩阵的自相关。

自卷积

通过对频谱或其幅度求平方,计算矩阵的自卷积。

卷积

使用 3x3、5x5 和图像内核计算卷积。