Before taking transposes seriously one could conveniently use e.g. [5]' to build a 1x1 matrix containing 5. In v0.6+ this results in a RowVector instead. Do we have any compact syntax for building initialized 1x1 matrices now?
hcat(1) ![]()
That’s not half-bad! Thanks!
The following also works
julia> [5][:,:]
1×1 Array{Int64,2}:
5
Still ugly… ![]()
But functions can be defined for a reason (and compilers inline for a reason), so:
julia> mat(sc) = reshape([sc],1,1)
mat (generic function with 1 method)
julia> mat(5)
1×1 Array{Int64,2}:
5
and better yet to consider:
julia> using StaticArrays
julia> smat(sc) = @SMatrix [sc]
smat (generic function with 1 method)
julia> smat(5)
1×1 StaticArrays.SArray{Tuple{1,1},Int64,2,1}:
5
The little @code_llvm I looked at, made these methods preferable and ultimately more readable and correct.
The smat function indeed provides an extremely compact compilation, followed by hcat, followed by reshape (which is quite suboptimal). Marked this as the best solution, thanks!
EDIT: in cases where a conventional Matrix instead of SMatrix is preferred, the function
mat(s) = Matrix(@SMatrix [s])
is surprisingly efficient too, better even than hcat
julia> @code_llvm mat(1)
define %jl_value_t addrspace(10)* @julia_mat_62521(i64) #0 !dbg !5 {
top:
%"#temp#" = alloca %SArray.10, align 8
%1 = getelementptr inbounds %SArray.10, %SArray.10* %"#temp#", i64 0, i32 0, i64 0
store i64 %0, i64* %1, align 8
%2 = addrspacecast %SArray.10* %"#temp#" to %SArray.10 addrspace(11)*
%3 = call %jl_value_t addrspace(10)* @julia_convert_62498(%jl_value_t addrspace(10)* addrspacecast (%jl_value_t* inttoptr (i64 4464354096 to %jl_value_t*) to %jl_value_t addrspace(10)*), %SArray.10 addrspace(11)* nocapture readonly %2)
ret %jl_value_t addrspace(10)* %3
(I just love StaticArrays.jl !)
You do have a function call in there so not sure how you can say whether it is efficient or not.
Benchmarking them I found that hcat and your mat had pretty much identical performance .
Oops, you’re completely right. I’m no good reading llvm
. Actually hcat is in 25% faster than mat in my system! Still, smat is way faster than both.
A side note, it might be a good idea to avoid depending on the extra package StaticArrays if not otherwise needed.
using BenchmarkTools
julia> @btime reshape([1],1,1)
63.990 ns (3 allocations: 192 bytes)
1×1 Array{Int64,2}:
1
julia> @btime fill(1, (1,1))
29.674 ns (1 allocation: 96 bytes)
1×1 Array{Int64,2}:
1
julia> @btime hcat(1)
33.067 ns (1 allocation: 96 bytes)
1×1 Array{Int64,2}:
1
The difference between hcat and fill is small, but consistent. I also find fill more elegant.
fill is my favorite too.
With a function:
mat(s) = begin
m = Array{typeof(s)}(1,1)
@inbounds m[1] = s
return m
end
another 10% can be squeezed (on my system, Julia version, and LLVM version):
julia> @btime mat(5)
26.736 ns (1 allocation: 96 bytes)
1×1 Array{Int64,2}:
5
julia> @btime fill(5,(1,1))
28.640 ns (1 allocation: 96 bytes)
1×1 Array{Int64,2}:
5
And the @code_llvm looks nice and short.
I typically use diagm([5]).
This works, for array literals:
[5;;]
The number of semicolons indicate the rank of the final tensor, so for instance, [5;;;] is a 1x1x1 tensor.