In [1]:
## I like cell mode. 
# This let's me group a whole bunch of expressions together and run them all at once.
function f(x)
    y = x^2
    return y + 1
end
f(3)
Out[1]:
10
In [2]:
## This is a cell delimiter, so this won't run with the previous block 
f(4) 
Out[2]:
17
In [3]:
## Why I like cell mode is you can build up a lot of code and then run it piece by piece
# Now let's prepare a plot
using CairoMakie
fig = lines(0:10, f.(0:10))
Out[3]:
In [4]:
##
save("2025-Lecture-4-myplot.pdf", fig)
Out[4]:
CairoMakie.Screen{PDF}
In [5]:
## Julia great types and function support
module MyModule 
""" A simple matrix type
that represents a single non-zero entry
in a sparse matrix.
"""
struct MySingleIndexMatrix <: AbstractMatrix{Float64}
  i::Int
  j::Int
  m::Int
  n::Int
  value::Float64
end 
import Base.getindex, Base.size, Base.:+
function +(A::MySingleIndexMatrix, B::AbstractMatrix{Float64})
  #println("Adding MySingleIndexMatrix to a dense matrix")
  C = copy(B)
  C[A.i, A.j] += A.value
  return C
end 
size(A::MySingleIndexMatrix) = (A.m, A.n)
function getindex(A::MySingleIndexMatrix, i::Int, j::Int)
  if i == A.i && j == A.j
    return A.value
  else
    return 0.0
  end
end
end
A = MyModule.MySingleIndexMatrix(2, 3, 5, 5, 10.0)
A 
Out[5]:
5×5 Main.MyModule.MySingleIndexMatrix:
 0.0  0.0   0.0  0.0  0.0
 0.0  0.0  10.0  0.0  0.0
 0.0  0.0   0.0  0.0  0.0
 0.0  0.0   0.0  0.0  0.0
 0.0  0.0   0.0  0.0  0.0
In [6]:
##
B = MyModule.MySingleIndexMatrix(2, 3, 1_000, 10_000, 10.0)
@time B + zeros(1_000, 10_000); # This is fast?
  0.175680 seconds (5.75 k allocations: 152.875 MiB, 83.17% gc time, 3.19% compilation time)
In [7]:
## This is the way you should really do it
using BenchmarkTools
@btime begin 
  D2 = B + C;
end setup = (C = zeros(1_000, 10_000); B = MyModule.MySingleIndexMatrix(2, 3, 1_000, 10_000, 10.0);)
ArgumentError: Package BenchmarkTools not found in current path.
- Run `import Pkg; Pkg.add("BenchmarkTools")` to install the BenchmarkTools package.

Stacktrace:
 [1] macro expansion
   @ ./loading.jl:2296 [inlined]
 [2] macro expansion
   @ ./lock.jl:273 [inlined]
 [3] __require(into::Module, mod::Symbol)
   @ Base ./loading.jl:2271
 [4] #invoke_in_world#3
   @ ./essentials.jl:1089 [inlined]
 [5] invoke_in_world
   @ ./essentials.jl:1086 [inlined]
 [6] require(into::Module, mod::Symbol)
   @ Base ./loading.jl:2260
In [8]:
## Without the optimized routine, I see about 5ms vs. 3.6ms with it.