How do I use an arugment to a function that is either a vector or a 1D view

I have a simulation which is given by a t x N matrix abundances_timeseries, where t is the timestep and N the amount of variables. (This can for example be a 10^3 x 5 matrix).

I want to check for oscillating behaviour by comparing if the value at the last timestep equals the values at some earlier timestep. I do this with the following (simplified here) code:

using Random
# generate random abundances_timeseries. Usually this is not random but 
# from a simulation
abundances_timeseries = rand(1:100, (10000, 5))
# n_final is the final value of all the variables in the simulation
n_final = abundances_timeseries[:, t_max]

for t in t_max:-1:1
    n_t = abundances_timeseries[:, t]
    if is_similar(n_t, n_final)
       println("the system is oscillating")
    end
end

function is_similar(n1::Vector{<:Real}, n2::Vector{<:Real})
    if length(n1) != length(n2)
        return false
    end
    N = length(n1)
    for i in 1:N
        if !is_similar(n1[i], n2[i])
            return false
        end
    end
    return true
end

function is_similar(ni::Real, nj::Real)
    cutoff = 0.99
    if cutoff*ni <= nj <= ni/cutoff
        return true
    end
    return false
end

This works fine, but I want to use @view for n_final and n_t for performance reasons, but I still want the code to work for regular vectors as well. If I change them to views I get the error:

ERROR: MethodError: no method matching is_similar(::Vector{Float64}, ::SubArray{Float64, 1, Matrix{Float64}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true})
Closest candidates are:
  is_similar(::Vector{<:Real}, ::Vector{<:Real})

Is there a sort of common type I can assign to n1 and n2 in my is_similar function to work on both? Or is the only way to use
Union{Vector{<:Real}, ::SubArray{Float64, 1, Matrix{Float64}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true})}?

1 Like

Use ::AbstractVector instead of ::Vector.

2 Likes

This works, thank you!

1 Like