how to make my own 3d array type

202 views
Skip to first unread message

Evan

unread,
Nov 16, 2015, 6:54:15 AM11/16/15
to julia-users
For a 2d array the following works:

type mytype{T}
   
var :: AbstractMatrix{T}
end

julia
> t = mytype(zeros(4, 3))
mytype
{Float64}(4x3 Array{Float64,2}:
 
0.0  0.0  0.0
 
0.0  0.0  0.0
 
0.0  0.0  0.0
 
0.0  0.0  0.0)



But how do I extend this to a 3d array?

julia> t = mytype(zeros(2, 4, 3))
ERROR
: MethodError: `convert` has no method matching convert(::Type{mytype{T}}, ::Array{Float64,3})
This may have arisen from a call to the constructor mytype{T}(...),
since type constructors fall back to convert methods
.
Closest candidates are:
  call
{T}(::Type{T}, ::Any)
  convert
{T}(::Type{T}, ::T)
  mytype
{T}(::AbstractArray{T,2})
 
in call at essentials.jl:56




Patrick Kofod Mogensen

unread,
Nov 16, 2015, 6:59:51 AM11/16/15
to julia-users
Well, try running

 isa(zeros(2,4,3), AbstractMatrix)

The problem here is that a(n) (Abstract)Matrix is 2-dimensional array.

Tim Holy

unread,
Nov 16, 2015, 7:03:05 AM11/16/15
to julia...@googlegroups.com
This fixes two problems:

type MyType{T,N,A<:AbstractArray} <: AbstractArray{T,N}
var::A
end

MyType{T,N}(var::AbstractArray{T,N}) = MyType{T,N,typeof(var)}(var)



If performance matters, you should not use abstract types for fields. See
http://docs.julialang.org/en/stable/manual/faq/#how-do-abstract-or-ambiguous-fields-in-types-interact-with-the-compiler and the section after that.

--Tim

Evan

unread,
Nov 16, 2015, 9:08:15 AM11/16/15
to julia-users
Thank you, Tim, I understand the motivation for the approach in the link you sent.

I'm still unable to create the type that I want. I actually want two arrays in my type, one 2d and the other 3d.

First though, I'm still stuck on just the 2d when I try to implement your suggestion:
julia> type MyType{T,N,A<:AbstractArray} <: AbstractArray{T,N}
           
var::A
       
end

julia
> MyType{T,N}(var::AbstractArray{T,N}) = MyType{T,N,typeof(var)}(var)
MyType{T,N,A<:AbstractArray{T,N}}

julia
> aa = MyType(zeros(2,3))
Error showing value of type MyType{Float64,2,Array{Float64,2}}:
ERROR
: MethodError: `size` has no method matching size(::MyType{Float64,2,Array{Float64,2}})
Closest candidates are:
  size
{T,n}(::AbstractArray{T,n}, ::Any)
  size
(::Any, ::Integer, ::Integer, ::Integer...)
 
in showarray at show.jl:1231
 
in anonymous at replutil.jl:29
 
in with_output_limit at ./show.jl:1271
 
in writemime at replutil.jl:28
 
in display at REPL.jl:114
 
in display at REPL.jl:117
 
[inlined code] from multimedia.jl:151
 
in display at multimedia.jl:162
 
in print_response at REPL.jl:134
 
in print_response at REPL.jl:121
 
in anonymous at REPL.jl:624
 
in run_interface at ./LineEdit.jl:1610
 
in run_frontend at ./REPL.jl:863
 
in run_repl at ./REPL.jl:167
 
in _start at ./client.jl:420

julia
>

Performance is important, but it's not clear what I should use in place of abstract types; I've tried replacing AbstractArray with just Array but that does not appear to work.

Tim Holy

unread,
Nov 16, 2015, 9:45:43 AM11/16/15
to julia...@googlegroups.com
Totally different error (it's a missing size method). You also need to read
this:
http://docs.julialang.org/en/stable/manual/interfaces/#abstract-arrays

--Tim

Evan

unread,
Nov 25, 2015, 6:24:39 AM11/25/15
to julia-users
Thanks Tim,

Following the link you suggested I made the following type which does what I want:

immutable MyType{T,N,A<:AbstractArray} <: AbstractArray{Float64,3}
    conf_lims
:: A
end
MyType{T,N}(conf_lims::AbstractArray{T,N}) = MyType{T,N,typeof(conf_lims)}(conf_lims)
Base.size(S::MyType) = (S.count,)
Base.linearindexing(::Type{MyType}) = Base.LinearFast();


What I haven't figured out is how to add more than just the one variable; for instance I'd like to have a "count" variable which would be an integer?

Tim Holy

unread,
Nov 25, 2015, 6:53:40 AM11/25/15
to julia...@googlegroups.com
Check out the "Types" section of the manual, esp. the part about "Composite
Types."

Also, see base/subarray.jl if you want an example of a complex but full-
featured AbstractArray type.

Best,
--Tim

Evan Mason

unread,
Nov 25, 2015, 12:29:38 PM11/25/15
to julia...@googlegroups.com
Great, thanks.  So, I now have:

immutable MyType2{T,N,A<:AbstractArray, I<:Int} <: AbstractArray{T,N}
    var :: A
    nstar :: I
end

MyType2{T,N}(var::AbstractArray{T,N}, nstar::Int) = MyType2{T,N, typeof(var), typeof(nstar)}(var, nstar)

Base.linearindexing(::Type{MyType2}) = Base.LinearFast()
Base.size(S::MyType2) = (S.nstar,)

and I found base/linalg/eigen.jl helpful in figuring this out.

Tim Holy

unread,
Nov 25, 2015, 12:38:11 PM11/25/15
to julia...@googlegroups.com
One more small tweak: Int is a concrete type, so you can use nstar::Int in the
type definition (you don't need to add another type parameter).

Glad to hear you're off to the races now.

Best,
--Tim
Reply all
Reply to author
Forward
0 new messages