Create A Matrix in Julia

How to creat such matrix in Julia:

CCP[:,:,1]= zeros(2,2)
CCP[:,:,2]= zeros(2,2)
CCP[:,:,3] = zeros(2,2)
CCP[:,:,4] = zeros(2,2)

this method works in matlab, but not in JUlia, namely ERROR: LoadError: UndefVarError: CCP not defined

CCP = zeros(2,2,4) ?

1 Like

That is not a matrix, but a three dimensional array. Create it like this

CCP = zeros(2, 2, 4)

2 Likes
CCP = zeros(2,2,4)

Is the easiest way. But this also works:

CCP = Array{Float64}(undef, 2, 2, 4);
CCP[:,:,1] .= zeros(2,2)
CCP[:,:,2] .= zeros(2,2)
CCP[:,:,3] .= zeros(2,2)
CCP[:,:,4] .= zeros(2,2)

Like the error says, you have to define CCP before assigning to it.

@Elrod 2x2x4 double type is equal to ```
Array{Float64}(undef, 2, 2, 4);

must we define type of matrix at first??

The type of that is Array{Float64, 3}.
zeros defaults to Float64, unless you specify otherwise.
Array needs you to specify the type.
Both methods infer the number of dimensions from how many dimensions you pass it. For example, passing 2,2,4 means you want a 3D Array.

But that would be pretty crazy, instead of

CCP = Array{Float64}(undef, 2, 2, 4); 
CCP .= 0

:wink:

2 Likes

I was thinking it might be a minimal example, and that OP really wanted to assign a bunch of blocks into an array.
Rather than just create a bunch of zeros.

But broadcasting is definitely one of the best ways to fill an array in general.

And your code is much better, both in terms of conciseness and performance.
If you care about performance, creating a bunch of temporary arrays like I did with zeros(2,2) is a bad idea.

I find this definition interesting as we have to define the matrix variable in Julia, but not for constant variable (not same to C++ and to MAtlab )

It depends what type you want your multi dimensional array to be. If you’re happy with Float64 (equivalent of double in Matlab) then no. If you want other types then yes, for example
CCP = zeros(Int64, 2, 2, 4)

1 Like

is it possible that I can set matrix as Array{Float64}(undef, *, *, *) in Julia? I donot need to calculate number at first.

Not really but may I ask what is your use case? The way you plan to write your code is very expensive in terms of performance.

You may consider using an array of arrays and push! into it and convert it to multi-dimensional array afterwards if you really need the result as one (which might be much faster than other alternatives), use ElasticArrays.jl if you plan to grow or shrink your array only in the last dimension, or create a new array and copy the values of the previous array into the new one in each or some iterations (the way MATLAB actually does).

1 Like

Yeah,

vector_of_matrices = Matrix{Float64}[]
push!(vector_of_matrices, zeros(2,2))
push!(vector_of_matrices, zeros(3,3))
push!(vector_of_matrices, zeros(4,4))

may be the best idea if you need to be that dynamic.

second goal (the way matlab actually does) is my plan in Julia …

is there a much more simple method to define a matrix (unknown dimension, like matlab way) in Julia?

No one has mentioned fill yet, but it is very useful for building an array with the same value in every element:

fill(0.0, 2, 2, 4)

The 0.0 bit can be anything, e.g.

fill("hello world", 2, 2, 4)

A couple of ways have been mentioned. There are also cat() methods..

But what is it you’re trying to do? Generally, just copying a strategy from one language to another isn’t the best approach. Do you want to do it this way because it’s what you’re used to, or because your problem actually requires it?

1 Like

It’s worth pointing out that MATLAB’s documention also recommends preallocating, whenever you care about performance. In their example, preallocating was about 25 times faster.

You could define a Julia type that automatically acts in that way. I would really recommend against it, because I think it is a bad idea. But…


mutable struct AutoResizeArray{T,N} <: AbstractArray{T,N}
    data::Array{T,N}
end
AutoResizeArray{T}(::UndefInitializer, I::Vararg{N}) where {T,N} = AutoResizeArray(Array{T}(undef, I))
Base.size(A::AutoResizeArray) = size(A.data)
Base.getindex(A::AutoResizeArray, I...) = A.data[I...]

@generated function Base.setindex!(A::AutoResizeArray{T,N}, v, I...) where {T,N}
    # I am using a generated function with Base.Cartesian.@nexprs to unroll the for loop
    # to ensure type stability, for when I... is not homogenous. Eg, if it is ::Colon, Int
    quote
        checkbounds(Bool, A, I...) && return A.data[I...] = v
        num_dim_inds = 0
        Base.Cartesian.@nexprs $N n -> begin
            if isa(I[n], Colon)
                num_dim_inds += 1
                # Maybe we have to grow to fit v?
                if isa(v, AbstractArray)
                    upper_bounds_n = max(size(A, n), size(v, num_dim_inds))
                else
                    # Don't grow
                    upper_bounds_n = size(A, n)
                end
            else
                isa(I[n], Integer) || (num_dim_inds += 1)
                upper_bounds_n = max(size(A, n), maximum(I[n]))
            end
        end
        # We obviously don't care about performance if we're using this
        # so, lets play it safer and zero-initialize the memory
        new_data = zeros(T, (Base.Cartesian.@ntuple $N n -> upper_bounds_n))
        @inbounds for i ∈ CartesianIndices(A)
            new_data[i] = A[i]
        end
        A.data = new_data
        A.data[I...] = v
    end
end

A = AutoResizeArray{Float64}(undef, 1,1,1)
A[2,:,5] = 1:4

I show this in hopes you don’t use it, but instead to show that it’s possible to do whatever you want in Julia. If you want something to behave in some way, make it!

1 Like

You cannot define a matrix (array) with unknown dimensions in Matlab either. All arrays have a size, but what happens is that when you assign to an index outside the current array size, Matlab automatically resizes the array.

That may happen by copying the entire contents of the array into a new larger array, or perhaps they sometimes have some extra ‘padding’ to work with. You have no control over that, though.

This way of working with arrays is not recommended in Matlab:

You can achieve the same behaviour in Julia by using push! on vectors, or with hcat/vcat/cat on higher dimensional arrays. (I mean, you can resize arrays like that, it will not automatically resize on assignment.)

5 Likes