Ваш тип матрицы определен как подтип AbstractArray{T, 2}
.Вам нужно реализовать несколько методов в неофициальном интерфейсе массива Julia для вашего типа, чтобы сделать функции и функции, работающие на AbstractArray{T, 2}
, также работать с вашим пользовательским типом, то есть сделать ваш CircularMatrix
итеративным, индексируемым,полностью функционирующая матрица.
Методы реализации:
size(M::CircularMatrix)
getindex(M::CircularMatrix, i::Int)
getindex(M::CircularMatrix, I::Vararg{Int, N})
setindex!(M::CircularMatrix, v, i::Int)
setindex!(M::CircularMatrix, v, I::Vararg{Int, N})
Вы уже реализовали 1, 2 и 4, но еще не установили свой стиль индексации.Вам может не понадобиться 3 и 5, если вы выберете стиль линейного индексирования .Вам нужно только установить IndexStyle
равным IndexLinear()
и, возможно, несколько модификаций, тогда все должно работать только для вашей матрицы.
1.size(M::CircularMatrix)
Первый - size
.size(A::CircularMatrix)
возвращает Tuple
размеров A
.Я считаю, что для вашей матрицы, вероятно, что-то вроде следующего
Base.size(M::CircularMatrix) = size(M.data)
2getindex(M::CircularMatrix, i::Int)
Этот метод необходим, если вы выберете стиль линейного индексирования .getindex(M, i::Int)
должно дать вам значение по линейному индексу i
.Вы уже реализовали это в своем коде.Если вы выбираете линейное индексирование, вам нужно установить IndexStyle
для вашего типа, а затем просто пропустить 3 и 5. Джулия автоматически преобразует несколько обращений к индексу, например, a[3, 5]
, в доступ к линейному индексу.
Base.IndexStyle(::Type{<:CircularMatrix}) = IndexLinear()
Base.@propogate_inbounds function Base.getindex(M::CircularMatrix, i::Int)
@boundscheck checkbounds(M, i)
@inbounds M.view[i]
end
Возможно, лучше использовать @inbounds
здесь во второй строке.Если вызывающая сторона не использует @inbounds
, мы сначала проверяем границы, и это , надеюсь, делает последующую проверку границ ненужной.Возможно, вы захотите пропустить это во время разработки.
3.getindex(M::CircularMatrix, I::Vararg{Int, N})
Третий - для декартового стиля индексации.Если вы выбираете этот стиль, вам нужно реализовать этот метод.Vararg{Int, N}
в подписи означает "ровно N
Int
аргументов".Здесь N
должно быть равно размерности CircularMatrix
.Поскольку это матрица, N должно быть два.Если вы выбираете этот стиль, вам нужно определить что-то вроде следующего
Base.@propogate_inbounds function Base.getindex(A::CircularMatrix, I::Vararg{Int, 2})
@boundscheck checkbounds(A, I...)
@inbounds A.view[# convert I[1]` and `I[2]` to a linear index in `view`]
end
или поскольку ваша размерность не параметрическая, а матрица двумерная, просто
Base.@propogate_inbounds function Base.getindex(A::CircularMatrix, i::Int, j::Int)
@boundscheck checkbounds(A, i, j)
@inbounds A.view[# convert i` and `j` to a linear index in `view`]
end
4.setindex!(M::CircularMatrix, v, i::Int)
Четвертый похож на второй.Этот метод должен установить значение на линейный индекс i
, если вы выбираете стиль линейного индексирования.
5.setindex!(M::CircularMatrix, v, I::Vararg{Int, N})
Пятый должен быть похож на третий, если вы выбираете декартовой стиль индексации.
После реализаций для 1, 2 и 4 и установки IndexStyle
, у вас должен быть собственный тип матрицы, который просто работает.
m[1, 1] = 5
x = view(m, 1, :)
for e in
...
end
for i in eachindex(m)
...
end
display(m)
println(m)
length(m)
ndims(m)
map(f, A)
....
Все это должно работать.
Несколько заметок
Документация по интерфейсу Abstract Arrays здесь с несколькими примерами.Вы также можете увидеть Необязательные методы для реализации.
На GitHub существует организация JuliaArray , которая предоставляет множество полезных реализаций пользовательских массивов, включая StaticArrays
, OffsetArrays
и т. Д., А также организация JuliaMatrices , предоставляющая пользовательские типы матриц.Возможно, вы захотите взглянуть на их реализации.
@inline
является избыточным, если вы используете Base.@propogate_inbounds
.
@ spreadate_inbounds
Сообщает компилятору встроенную функцию, сохраняя при этом контекст входящих вызовов.
- Вам не нужно определять
eltype
дляваша матрица, так как уже есть определение для AbstractArray{T, N}
, которое возвращает T
.