Вы можете сделать следующее с StaticArrays
, чтобы получить «кортежи, которые могут выполнять линейную алгебру»:
julia> using StaticArrays
julia> ⊗(u, v) = (i ⊗ j for i in u for j in v)
⊗ (generic function with 1 method)
julia> ⊗(x::Number, y::Number) = SVector(x, y)
⊗ (generic function with 2 methods)
julia> ⊗(x::SVector{N}, y::Number) where {N} = SVector(x..., y)
⊗ (generic function with 3 methods)
julia> collect((1:3) ⊗ (10:12) ⊗ (100:101))
18-element Array{SArray{Tuple{3},Int64,1,3},1}:
[1, 10, 100]
[1, 10, 101]
[1, 11, 100]
[1, 11, 101]
[1, 12, 100]
[1, 12, 101]
[2, 10, 100]
[2, 10, 101]
[2, 11, 100]
[2, 11, 101]
[2, 12, 100]
[2, 12, 101]
[3, 10, 100]
[3, 10, 101]
[3, 11, 100]
[3, 11, 101]
[3, 12, 100]
[3, 12, 101]
julia> using LinearAlgebra: norm
julia> for M in (1:3) ⊗ (10:12) ⊗ (100:101)
println(norm(M))
end
100.50373127401788
101.49876846543509
100.60815076324582
101.6021653312566
100.72239075796404
101.7152889196113
100.5186549850325
101.51354589413178
100.62305898749054
101.61692772368194
100.73728207570423
101.73003489628813
100.54352291420865
101.5381701627521
100.64790112068906
101.64152694642087
100.7620960480676
101.75460677532
Но я не уверен, что оно того стоит. В идеале, \otimes
для SVector
s и Number
s будет создавать ленивую структуру данных, которая создает только SVector
s соответствующего размера при итерации (вместо разделения, как здесь). Мне просто лень писать это сейчас.
Лучший вариант (но чуть менее математический синтаксис) - перегрузить ⨂(spaces...)
, чтобы сделать все сразу:
julia> ⨂(spaces::NTuple{N}) where {N} = (SVector{N}(t) for t in Iterators.product(spaces...))
⨂ (generic function with 1 method)
julia> ⨂(spaces...) = ⨂(spaces)
⨂ (generic function with 2 methods)
julia> collect(⨂(1:3, 10:11))
3×2 Array{SArray{Tuple{2},Int64,1,2},2}:
[1, 10] [1, 11]
[2, 10] [2, 11]
[3, 10] [3, 11]
julia> collect(⨂(1:3, 10:11, 100:101))
3×2×2 Array{SArray{Tuple{3},Int64,1,3},3}:
[:, :, 1] =
[1, 10, 100] [1, 11, 100]
[2, 10, 100] [2, 11, 100]
[3, 10, 100] [3, 11, 100]
[:, :, 2] =
[1, 10, 101] [1, 11, 101]
[2, 10, 101] [2, 11, 101]
[3, 10, 101] [3, 11, 101]
Это собирает в другую форму, хотя я бы посчитал это еще более уместным.