Analog of `diff` operator for adjacent sum

I want to return the sum of adjacent elements in an array, ie, a function sumadj that produces

julia> a = [2, 3, 4]

julia> sumadj(a)
2-element Vector{Int64}:
 5
 7

diff computes the difference between adjacent pairs of elements in an array, but I want an analog that computes the sum.

Also looking for a solution that doesn’t use a for loop because I need it to work on a GPU with CUDA.jl, which doesn’t allow indexing.

julia> function adjsum(ary)
           ary1 = @view ary[begin:end-1]
           ary2 = @view ary[begin+1:end]
           ary1 + ary2
       end
adjsum (generic function with 1 method)

julia> adjsum([2, 3, 4])
2-element Vector{Int64}:
 5
 7
1 Like

Awesome, thank you! Didn’t know about views, cool tip

More compact to write:

@views adjsum(a) = a[begin:end-1] + a[begin+1:end]

Using the @views macro you can opt-in to views for slices for a whole function at once.

8 Likes

I couldn’t resist:

julia> struct AddOnly{T}
           x::T
       end

julia> Base.:(-)(x::AddOnly, y::AddOnly) = x.x + y.x

julia> a = AddOnly.([2, 3, 4])
3-element Vector{AddOnly{Int64}}:
 AddOnly{Int64}(2)
 AddOnly{Int64}(3)
 AddOnly{Int64}(4)

julia> diff(a)
2-element Vector{Int64}:
 5
 7

:smile:

(note this is a bad idea: defining a method of - that has a different meaning from that of the overall function is bad practice and can lead to bugs).

1 Like

You could also just write a loop.

Did you read the OP? don’t want an explicit loop because they want to use it on CUDA areay

I read it, but that was yesterday, so I forgot.

Taking into account that the addition operation is associative, it might make sense to deal with the more general case of the sum of n adjacent elements.


using IterTools

a = [2, 3, 4]

sumadj(v,n) = sum.(partition(v,n,1))

sumadj(a,2)
1 Like

using DSP
conv(a,[1,1])[2:end-1]

2 Likes