# Creating one's own Matrix type

**URL:** https://discourse.julialang.org/t/creating-ones-own-matrix-type/33553
**Category:** General Usage
**Created:** [January 19, 2020, 2:20pm UTC](https://discourse.julialang.org/t/creating-ones-own-matrix-type/33553 "2020-01-19T14:20:59Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![timueh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timueh/32/12379_2.png) [@timueh](https://discourse.julialang.org/u/timueh)
#### Post date: [January 19, 2020, 2:20pm UTC](https://discourse.julialang.org/t/creating-ones-own-matrix-type/33553/1 "2020-01-19T14:20:59Z")

</div>

I have a question related to [13:45 in Alan Edelman’s recent award presentation](https://youtu.be/nwdGsz4rc3Q?t=825):

In the following two code snippets, is there a deeper difference other than `MyMatrix` being more _descriptive_, i.e. the type tells me the type of the elements _and_ that it stores those elements as a vector? Is the first version _more_ Julian? If so, why? Are there performance differences? The struct definition of Version 2 seems a little cleaner?!

## Version 1

```julia
struct MyMatrix{T, V<:AbstractVector{T}} <: AbstractMatrix{T}
    v::V
end

Base.size(A::MyMatrix) = length(A.v), length(A.v)
Base.getindex(A::MyMatrix, i, j) = A.v[i]*(i==j) + A.v[i]*A.v[j]

julia> A = MyMatrix([1,2,3])

3×3 MyMatrix{Int64,Array{Int64,1}}:
 1 0 0
 0 2 0
 0 0 3

```

## Version 2

```julia
struct MyNewMatrix{T} <: AbstractMatrix{T}
    v::AbstractVector{T}
end

Base.size(A::MyNewMatrix) = length(A.v), length(A.v)
Base.getindex(A::MyNewMatrix, i, j) = A.v[i]*(i==j) + A.v[i]*A.v[j]

julia>B = MyNewMatrix([1,2,3])

3×3 MyNewMatrix{Int64}:
 1 0 0
 0 2 0
 0 0 3

```

---

<div class="post-metadata">

### Author: ![abulak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abulak/32/28314_2.png) [@abulak](https://discourse.julialang.org/u/abulak)
#### Post date: [January 19, 2020, 2:39pm UTC](https://discourse.julialang.org/t/creating-ones-own-matrix-type/33553/2 "2020-01-19T14:39:22Z")

</div>

> [@timueh](#):
>
> type tells me the type of the elements _and_ that it stores those elements as a vector? Is the first version _more_ Julian? If so, why? Are there performance differences? The struct definition of Version 2 seems a little cleaner?!

Version 2 is not concrete. `v` is of abstract type at the moment of creation and (in principle) it will be much slower than the first one; You can always fix this by fixing the actual concrete type, i.e. declaring `v::Vector{T}`, but that makes the approach less flexible (you can’t use it with e.g. sparse vectors, before the’re converted to dense ones)

---

<div class="post-metadata">

### Author: ![timueh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timueh/32/12379_2.png) [@timueh](https://discourse.julialang.org/u/timueh)
#### Post date: [January 19, 2020, 2:48pm UTC](https://discourse.julialang.org/t/creating-ones-own-matrix-type/33553/3 "2020-01-19T14:48:28Z")

</div>

When you say

> [@abulak](#):
>
> it will be much slower than the first one;

do you refer to creating matrices or do you refer to doing computations with them?

---

<div class="post-metadata">

### Author: ![timueh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timueh/32/12379_2.png) [@timueh](https://discourse.julialang.org/u/timueh)
#### Post date: [January 19, 2020, 2:53pm UTC](https://discourse.julialang.org/t/creating-ones-own-matrix-type/33553/4 "2020-01-19T14:53:22Z")

</div>

As a follow up:

```julia
julia> using BenchmarkTools
julia> n = 10000000
julia> A = @btime MyMatrix(rand(n))
julia> B = @btime MyNewMatrix(rand(n))

  20.005 ms (3 allocations: 76.29 MiB)
  19.737 ms (3 allocations: 76.29 MiB)

```

---

<div class="post-metadata">

### Author: ![abulak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abulak/32/28314_2.png) [@abulak](https://discourse.julialang.org/u/abulak)
#### Post date: [January 19, 2020, 3:10pm UTC](https://discourse.julialang.org/t/creating-ones-own-matrix-type/33553/5 "2020-01-19T15:10:10Z")

</div>

you’re benchmarking mostly the `rand` function:

```julia
julia> let v = rand(n)
          @btime MyMatrix($v);
          @btime MyNewMatrix($v);
       end;
  5.882 ns (1 allocation: 16 bytes)
  5.854 ns (1 allocation: 16 bytes)

```

however using those matrices has significant penalty leading to

```julia
julia> let v = rand(10_000)
          @btime sum(MyMatrix($v));
          @btime sum(MyNewMatrix($v));
       end;
  207.626 ms (7 allocations: 144 bytes)
  28.082 s (984670013 allocations: 14.67 GiB)

```

Edit: simple indexing is 70x slower

```julia
let v = rand(100)
          @btime MyMatrix($v)[10,40]
          @btime MyNewMatrix($v)[10,40]
       end
  2.320 ns (0 allocations: 0 bytes)
  152.165 ns (7 allocations: 112 bytes)

```

---

<div class="post-metadata">

### Author: ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)
#### Post date: [January 19, 2020, 3:31pm UTC](https://discourse.julialang.org/t/creating-ones-own-matrix-type/33553/6 "2020-01-19T15:31:04Z")

</div>

See [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1.3/manual/performance-tips/#Avoid-fields-with-abstract-type-1) and the following section. The short answer is that you should declare the type in such as way that the type system knows exactly what it’s going to get from `A.v`.

---

<div class="post-metadata">

### Author: ![timueh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timueh/32/12379_2.png) [@timueh](https://discourse.julialang.org/u/timueh)
#### Post date: [January 20, 2020, 7:05am UTC](https://discourse.julialang.org/t/creating-ones-own-matrix-type/33553/7 "2020-01-20T07:05:26Z")

</div>

Thanks for the pointer!
