# Similar MArray with different size

**URL:** <https://discourse.julialang.org/t/similar-marray-with-different-size/100490>\
**Category:** General Usage\
**Tags:** question, package, staticarrays\
**Created:** [June 17, 2023, 2:21pm UTC](https://discourse.julialang.org/t/similar-marray-with-different-size/100490 "2023-06-17T14:21:44Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![nicolas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nicolas/32/26439_2.png) [@nicolas](https://discourse.julialang.org/u/nicolas)\
**Post date:** [June 17, 2023, 2:21pm UTC](https://discourse.julialang.org/t/similar-marray-with-different-size/100490/1 "2023-06-17T14:21:44Z")

</div>

I want to create an array similar to some other array, which could be an Array, a MArray, or some other kind of mutable array-like container. But I would also like to set its dimensions to m×n. I’ve tried similar and it doesn’t seem to work. Consider the following:

```julia
using StaticArrays
m = n = 2
println(typeof(similar([1, 2, 3])))
println(typeof(similar([1, 2, 3], m, n)))
println(typeof(similar(@MVector([1, 2, 3]))))
println(typeof(similar(@MVector([1, 2, 3]), m, n)))

```

which outputs

```julia
Vector{Int64}
Matrix{Int64}
MVector{3, Int64}
Matrix{Int64}

```

I would have hoped

```julia
typeof(similar(@MVector([1, 2, 3]), m, n))

```

to output

```julia
MMatrix{2, 2, Int64, 4}

```

Is this expectation unreasonable? To get the behavior I want, the only way I have found for now is to test explicitly:

```julia
x = @MVector([1, 2, 3])
typeof(isa(x, MArray) ? MMatrix{m, n, eltype(x)}(undef) : similar(x, m, n))

```

which outputs what I expect

```julia
MMatrix{2, 2, Int64, 4}

```

Of course, that just works for MArrays. Is there a better way?

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [June 17, 2023, 4:50pm UTC](https://discourse.julialang.org/t/similar-marray-with-different-size/100490/2 "2023-06-17T16:50:26Z")

</div>

I think `reshape` is what you want, see example [here](https://juliaarrays.github.io/StaticArrays.jl/stable/pages/api/#The-Size-trait).

---

<div class="post-metadata">

**Author:** ![mateuszbaran](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateuszbaran/32/221842_2.png) [@mateuszbaran](https://discourse.julialang.org/u/mateuszbaran)\
**Post date:** [June 17, 2023, 5:49pm UTC](https://discourse.julialang.org/t/similar-marray-with-different-size/100490/3 "2023-06-17T17:49:00Z")

</div>

> [@nicolas](#):
>
> Is this expectation unreasonable? To get the behavior I want, the only way I have found for now is to test explicitly:

This is slightly unreasonable because in your `similar` variables `n` and `m` have values that are not statically known, so `similar` that returns `MMatrix` would be type unstable. StaticArrays.jl generally prefers to fall back to normal `Array`s when the alternative is type instability, and IMO that choice makes sense. Type-unstable StaticArrays.jl code is generally slower than just using `Array`.

> [@nicolas](#):
>
> Is there a better way?

It depends on the context. Is this just for top level data allocation before actual performance-sensitive part is run? If so, then it can’t get much nicer than your explicit test. If you need to call `similar` in actually performance-critical part, then you likely need some additional adjustments to your code to ensure type stability.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [June 17, 2023, 8:05pm UTC](https://discourse.julialang.org/t/similar-marray-with-different-size/100490/4 "2023-06-17T20:05:26Z")

</div>

> [@mateuszbaran](#):
>
> `similar` that returns `MMatrix` would be type unstable

You could write a `similar` method for `MArray` that takes `Val` arguments (for sizes that are known statically) pretty easily.

---

<div class="post-metadata">

**Author:** ![mateuszbaran](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateuszbaran/32/221842_2.png) [@mateuszbaran](https://discourse.julialang.org/u/mateuszbaran)\
**Post date:** [June 17, 2023, 8:35pm UTC](https://discourse.julialang.org/t/similar-marray-with-different-size/100490/5 "2023-06-17T20:35:40Z")

</div>

Yes, and there is already `similar` that takes `Size` which does pretty much the same thing.

---

<div class="post-metadata">

**Author:** ![nicolas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nicolas/32/26439_2.png) [@nicolas](https://discourse.julialang.org/u/nicolas)\
**Post date:** [June 17, 2023, 9:12pm UTC](https://discourse.julialang.org/t/similar-marray-with-different-size/100490/6 "2023-06-17T21:12:49Z")

</div>

Thanks everyone for the very good suggestions and warnings. I think I came up with a decent solution. As @stevengj pointed out, it is pretty easy to create a new similar function. As @mateuszbaran pointed out, we must be mindful of type stability. To test the speed gain, I just execute mul! 1000 times.

```julia
using StaticArrays, BenchmarkTools, LinearAlgebra

similar2(x, dims) = similar(x, dims)
similar2(x :: MArray, dims) = MArray{Tuple{dims...}, eltype(x), length(dims), prod(dims)}(undef)

function mul_many_times!(out,A,x, n)
    for _ in 1:n
        mul!(out,A,x)
    end
end

function test_mul(x)
    d = length(x)
    A = similar2(x,(d,d))
    out = similar2(x,d)
    out .= 1
    return mul_many_times!(out,A,x,1000)
end

x = [1,2,3,4]
xm = @MVector [1,2,3,4]

```

Then

```julia
@btime test_mul($x)
@btime test_mul($xm)

```

outputs

```julia
  12.200 μs (2 allocations: 288 bytes)
  3.375 μs (6 allocations: 384 bytes)

```

---

<div class="post-metadata">

**Author:** ![longemen3000](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/longemen3000/32/7298_2.png) [@longemen3000](https://discourse.julialang.org/u/longemen3000)\
**Post date:** [June 18, 2023, 4:36am UTC](https://discourse.julialang.org/t/similar-marray-with-different-size/100490/7 "2023-06-18T04:36:55Z")

</div>

hmm, is this just used to generate a Matrix type from a Vector type? ArrayInterface docs mention a similar problem: [Julia's Extended Linear Algebra Interface · ArrayInterface.jl](https://docs.sciml.ai/ArrayInterface/stable/linearalgebra/#ArrayInterface.zeromatrix)

```julia
zeromat(u) = u .* u' .* false

function mul_many_times!(out,A,x, n)
    for _ in 1:n
        mul!(out,A,x)
    end
end

function test_mul(x)
    A = zeromat(x)
    out = similar(x)
    out .= 1
    return mul_many_times!(out,A,x,1000)
end

```

that gives:

```julia
julia> @btime test_mul($x)
  25.600 μs (2 allocations: 288 bytes)

julia> @btime Clapeyron.test_mul($xm)
  8.900 μs (2 allocations: 192 bytes)

```

so the additional allocations in the static case are gone.

---

<div class="post-metadata">

**Author:** ![mateuszbaran](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateuszbaran/32/221842_2.png) [@mateuszbaran](https://discourse.julialang.org/u/mateuszbaran)\
**Post date:** [June 18, 2023, 12:37pm UTC](https://discourse.julialang.org/t/similar-marray-with-different-size/100490/8 "2023-06-18T12:37:43Z")

</div>

You’re welcome 🙂 .

Additional allocations are also gone if the `MArray` `similar2` is marked as `@inline`.
