我想将位置 i
处的静态数组 A
增加 x
。如果它是一个可变数组,我只会执行A[i] += x
。但由于它是 StaticArray,我需要创建一个新的。但是,如果我新的 A
的大小,那么我会做类似的事情
A = A + @SVector [0,0,x]
并且每个i
都有一个分支。但在本例中,SVector 是用户输入,因此我只能使用类型信息提前知道。我不想让我的核心逻辑全部成为一个生成函数来处理这个问题,所以我希望有一个简单的解决方案,或者这可能需要一个 @ generated
辅助函数。
请注意,此问题相当于创建一个 @SVector
,其在位置 i
处具有值 x
,但其他位置为零。如果有一个简单的方法可以做到这一点,那么我的问题也解决了。
最佳答案
使用 array comprehensions 的简单方法将会是
Julia > k = 4
4
julia> @SVector [i == k? 1.0 : 0 对于 i 在 1:5]
5 元素 SVector{10,Float64}:
0.0
0.0
0.0
1.0
0.0
这是您在阅读StaticArrays.jl时可以采取的良好的第一步。自述文件的“快速入门”部分。
但是,我们在 Julia 中非常关心 type stability和通用代码, 因为:
- 函数的类型稳定性让编译器优化 -> 速度
- 可以利用multiple dispatch以强大的方式重用和扩展代码。
所以更朱利安的方法是使用
julia> 函数increment_value(A::SVector{L,T},x,k) 其中{L,T}
_A = [i == k ? x : 1:L 中的 i 为零(x)]
A+_A
结尾
Julia > A = @SVector [0, 0, 0, 0, 10]
5 元素 SVector{5,Int64}:
0
0
0
0
10
Julia > 增量值(A,5,2)
5 元素 SVector{5,Int64}:
0
5
0
0
10
但是,我们的最终答案应该包括一种避免额外变量分配的方法,并利用一些 compiler pipelining使用方便的 ifelse
函数:
`julia> 使用 StaticArrays、BenchmarkTools
julia> 函数increment_value(A::SVector{L,T}, x,k) 其中 {T,L}
SVector(ntuple(i->ifelse(i == k, A[i]+x, A[i]), Val{L}))
结尾
increment_value(具有 1 个方法的通用函数)
Julia > a = @SVector [ 1, 2, 3, 4, 5]
5 元素 SVector{5,Int64}:
1
2
3
4
5
Julia > @benchmarkincrement_value($a,$3,$5)
BenchmarkTools.试用版:
内存估计:0 字节
分配估计:0
最短时间:3.178 ns (0.00% GC)
中位时间:3.285 ns (0.00% GC)
平均时间:3.293 ns (0.00% GC)
最大时间:13.620 ns (0.00% GC)
sample :10000
评估/样本:1000
关于arrays - 在索引处增加 StaticVector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47580303/