# Kronecker doesn't work, kron yes, in this case

**URL:** <https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474>\
**Category:** New to Julia\
**Tags:** question, matrices\
**Created:** [January 30, 2024, 9:35pm UTC](https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474 "2024-01-30T21:35:56Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Enlil50](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/enlil50/32/206539_2.png) [@Enlil50](https://discourse.julialang.org/u/Enlil50)\
**Post date:** [January 30, 2024, 9:35pm UTC](https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474/1 "2024-01-30T21:35:56Z")

</div>

This is the program I made:

```julia
import Random
using LinearAlgebra

N::Int64 = 100
matr_A = Array{Float64}(undef, N, N)
matr_B = Array{Float64}(undef, N, N)
matr_C = Array{Float64}(undef, N*N, N*N)

Random.seed!(1)

for j = 1:N
    for i = 1:N
        matr_A[i,j] = rand(Float64)
        matr_B[i,j] = rand(Float64)
    end
end

matr_C = kron(matr_A, matr_B)

```

If you instead use Kronecker:

```julia
import Random
using LinearAlgebra
using Kronecker

N::Int64 = 100
matr_A = Array{Float64}(undef, N, N)
matr_B = Array{Float64}(undef, N, N)
matr_C = Array{Float64}(undef, N*N, N*N)

Random.seed!(1)

for j = 1:N
    for i = 1:N
        matr_A[i,j] = rand(Float64)
        matr_B[i,j] = rand(Float64)
    end
end

matr_C = Kronecker(matr_A, matr_B)

```

It gives this error:

```julia
ERROR: LoadError: MethodError: objects of type Module are not callable
Stacktrace:
 [1] top-level scope
   @ ~/Desktop/Programmi/MODULO_05/executable_and_libraries/bin/parova1.jl:22

```

---

<div class="post-metadata">

**Author:** ![eduardosalaz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eduardosalaz/32/22287_2.png) [@eduardosalaz](https://discourse.julialang.org/u/eduardosalaz)\
**Post date:** [January 30, 2024, 9:46pm UTC](https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474/2 "2024-01-30T21:46:57Z")

</div>

You should use the `kronecker` function or the `⊗` binary operator that they define and export. By using `Kronecker` you are refering to the module itself and not the function it exports. [Take a look at the docs.](https://michielstock.github.io/Kronecker.jl/dev/#Package-features)

---

<div class="post-metadata">

**Author:** ![Enlil50](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/enlil50/32/206539_2.png) [@Enlil50](https://discourse.julialang.org/u/Enlil50)\
**Post date:** [January 30, 2024, 10:09pm UTC](https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474/3 "2024-01-30T22:09:06Z")

</div>

Ok so there was a typo with the cap letter K.  
No, it works, however i can’t really understand how it can be so fast.

you can display matrices with this and change kron with kroncecker to see the output is the same.

```julia
import Random
using LinearAlgebra
using BenchmarkTools
using Kronecker

# using MKL

N::Int64 = 2
matr_A = Array{Float64}(undef, N, N)
matr_B = Array{Float64}(undef, N, N)
matr_C = Array{Float64}(undef, N*N, N*N)

Random.seed!(1)

for j = 1:N
    for i = 1:N
        matr_A[i,j] = rand(Float64)
        matr_B[i,j] = rand(Float64)
    end
end

@time matr_C = kronecker(matr_A, matr_B)
display(matr_A)
display(matr_B)
display(matr_C)

```

However , setting N=100 (and removing the display), when I use @time, kronecker is 100 times faster and it’s mostly compilation time. I don’t know if most of the allocations are made in some arcane places (cause @time should see even in stack), cause it time sees kronecker allocates 1000 less than kron, while @btime doesn’t even understand

---

<div class="post-metadata">

**Author:** ![PeterSimon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petersimon/32/25193_2.png) [@PeterSimon](https://discourse.julialang.org/u/PeterSimon)\
**Post date:** [January 30, 2024, 10:17pm UTC](https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474/4 "2024-01-30T22:17:39Z")

</div>

The reason `kronecker` is so fast is that it is _lazy_. I.e., it doesn’t actually do the creation of the product’s elements until one is requested. From the documentation:

> `kronecker(A, B)` used to obtain an instance of the lazy `GeneralizedKroneckerProduct` type. In contrast to the native Julia function `kron(A, B)`, this does not compute the Kronecker product but instead stores the matrices in a specialized structure

---

<div class="post-metadata">

**Author:** ![mike.ingold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike.ingold/32/203749_2.png) [@mike.ingold](https://discourse.julialang.org/u/mike.ingold)\
**Post date:** [January 30, 2024, 11:48pm UTC](https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474/5 "2024-01-30T23:48:51Z")

</div>

> [@Enlil50](#):
>
> ```julia
> matr_A = Array{Float64}(undef, N, N)
> matr_B = Array{Float64}(undef, N, N)
> 
> for j = 1:N
> for i = 1:N
> matr_A[i,j] = rand(Float64)
> matr_B[i,j] = rand(Float64)
> end
> end
> 
> ```

For what it’s worth, just in case: according to the [docs for rand](https://docs.julialang.org/en/v1/stdlib/Random/#Base.rand) you should be able to replace all of this with two lines

```julia
matr_A = rand(Float64, (N,N))
matr_A = rand(Float64, (N,N))

```

---

<div class="post-metadata">

**Author:** ![PeterSimon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petersimon/32/25193_2.png) [@PeterSimon](https://discourse.julialang.org/u/PeterSimon)\
**Post date:** [January 31, 2024, 3:41am UTC](https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474/6 "2024-01-31T03:41:37Z")

</div>

Also, your pre-allocation of `matr_C` isn’t effective or needed, since that allocation is not used. Unlike in Fortran or Matlab, when you write `matr_C = ...`, this does not copy the right-hand side into `matr_C`. Instead, the label `matr_C` in effect is “re-pointed” to whatever is on the right-hand side, in this case a `KroneckerProduct` type as defined in the `Kronecker` package. So the memory you allocated for `matr_C` is discarded and eventually cleaned up by Julia’s garbage collector.

This is an important point to understand about Julia, and it is often discussed in this forum, e.g. [here](https://discourse.julialang.org/t/value-function-scoping-problem/20236/10).

---

<div class="post-metadata">

**Author:** ![Enlil50](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/enlil50/32/206539_2.png) [@Enlil50](https://discourse.julialang.org/u/Enlil50)\
**Post date:** [January 31, 2024, 9:23am UTC](https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474/7 "2024-01-31T09:23:44Z")

</div>

Isn’t it possible to preallocate it previously?

---

<div class="post-metadata">

**Author:** ![PeterSimon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petersimon/32/25193_2.png) [@PeterSimon](https://discourse.julialang.org/u/PeterSimon)\
**Post date:** [January 31, 2024, 5:46pm UTC](https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474/8 "2024-01-31T17:46:12Z")

</div>

Yes, it is possible to preallocate first and then fill the existing array using [dot syntax](https://docs.julialang.org/en/v1/manual/functions/#man-vectorized),

```julia
matr_C .= kronecker(matr_A, matr_B)

```

however the function call on the right-hand side will still allocate a new object, which is then copied elementwise into `matr_C`. If you want to completely eliminate allocations, then you need to call a version of the function that accepts a preallocated argument and modifies (“mutates” in Julia parlance) it in place. See, e.g. `kron!`. It is conventional in Julia to name functions which modify one or more of their arguements with a “!” (bang, or exclamation point) at the end of the function name. The modified arguments are typically the first one(s) in the argument list.

---

<div class="post-metadata">

**Author:** ![simsurace](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simsurace/32/30216_2.png) [@simsurace](https://discourse.julialang.org/u/simsurace)\
**Post date:** [January 31, 2024, 7:44pm UTC](https://discourse.julialang.org/t/kronecker-doesnt-work-kron-yes-in-this-case/109474/9 "2024-01-31T19:44:35Z")

</div>

There seems to be `Kronecker.collect!` to assign to a preallocated array. It seems that the broadcasted assignment is overloaded to use that. [See here](https://michielstock.github.io/Kronecker.jl/dev/man/basic/#Kronecker.collect!)
