Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename Size to Space to avoid conflict with StaticArrays #25

Merged
merged 2 commits into from
Feb 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Tensorial"
uuid = "98f94333-fa9f-48a9-ad80-1c66397b2b38"
authors = ["Keita Nakamura <[email protected]>"]
version = "0.3.5"
version = "0.4.0"

[deps]
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Expand Down
12 changes: 6 additions & 6 deletions src/AbstractTensor.jl
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
abstract type AbstractTensor{S <: Tuple, T, N} <: AbstractArray{T, N} end

Base.size(::Type{TT}) where {S, TT <: AbstractTensor{S}} = Dims(Size(S))
Base.size(::Type{TT}) where {S, TT <: AbstractTensor{S}} = Dims(Space(S))
Base.size(x::AbstractTensor) = size(typeof(x))

# indices
for func in (:independent_indices, :indices, :duplicates)
@eval begin
$func(::Type{TT}) where {S, TT <: AbstractTensor{S}} = $func(Size(S))
$func(::Type{TT}) where {S, TT <: AbstractTensor{S}} = $func(Space(S))
$func(x::AbstractTensor) = $func(typeof(x))
end
end

Size(::Type{TT}) where {S, TT <: AbstractTensor{S}} = Size(S)
Size(::AbstractTensor{S}) where {S} = Size(S)
Space(::Type{TT}) where {S, TT <: AbstractTensor{S}} = Space(S)
Space(::AbstractTensor{S}) where {S} = Space(S)

# getindex_expr
function getindex_expr(ex::Union{Symbol, Expr}, x::Type{<: AbstractTensor}, i...)
Expand All @@ -22,8 +22,8 @@ end

# to SArray
@generated function convert_to_SArray(x::AbstractTensor)
S = Size(x)
NewS = Size(Dims(S)) # remove Symmetry
S = Space(x)
NewS = Space(Dims(S)) # remove Symmetry
exps = [getindex_expr(:x, x, i) for i in indices(NewS)]
quote
@_inline_meta
Expand Down
84 changes: 0 additions & 84 deletions src/Size.jl

This file was deleted.

84 changes: 84 additions & 0 deletions src/Space.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
struct Space{S}
function Space{S}() where {S}
new{S::Tuple{Vararg{Union{Int, Symmetry}}}}()
end
end

@pure Space(dims::Vararg{Union{Int, Symmetry}}) = Space{dims}()
@pure Space(dims::Tuple) = Space{dims}()

_construct(x::Int) = x
@pure _construct(::Type{Symmetry{S}}) where {S} = Symmetry{S}()
@pure function Space(::Type{S}) where {S <: Tuple}
check_size_parameters(S)
dims = map(_construct, tuple(S.parameters...))
Space(dims)
end

_ncomponents(x::Int) = x
_ncomponents(x::Symmetry) = ncomponents(x)
@pure ncomponents(::Space{S}) where {S} = prod(_ncomponents, S)

@pure Base.Dims(::Space{S}) where {S} = flatten_tuple(map(Dims, S))
@pure Base.Tuple(::Space{S}) where {S} = S

@pure Base.length(s::Space) = length(Dims(s))
Base.getindex(s::Space, i::Int) = Tuple(s)[i]

function Base.show(io::IO, ::Space{S}) where {S}
print(io, "Space", S)
end


# dropfirst/droplast
dropfirst() = error()
dropfirst(x::Int) = ()
@pure dropfirst(::Symmetry{NTuple{2, dim}}) where {dim} = (dim,)
@pure dropfirst(::Symmetry{NTuple{order, dim}}) where {order, dim} = (Symmetry{NTuple{order-1, dim}}(),)
_dropfirst(x, ys...) = (dropfirst(x)..., ys...)
@pure dropfirst(::Space{S}) where {S} = Space(_dropfirst(S...))
@pure droplast(::Space{S}) where {S} = Space(reverse(_dropfirst(reverse(S)...)))
for op in (:dropfirst, :droplast)
@eval begin
$op(x::Space, ::Val{0}) = x
$op(x::Space, ::Val{N}) where {N} = $op($op(x), Val(N-1))
end
end

# otimes/contraction
@pure otimes(x::Space, y::Space) = Space(Tuple(x)..., Tuple(y)...)
@pure function contraction(x::Space, y::Space, ::Val{N}) where {N}
if !(0 ≤ N ≤ length(x) && 0 ≤ N ≤ length(y) && Dims(x)[end-N+1:end] === Dims(y)[1:N])
throw(DimensionMismatch("dimensions must match"))
end
otimes(droplast(x, Val(N)), dropfirst(y, Val(N)))
end

# promote_space
promote_space(x::Space) = x
function promote_space(x::Space, y::Space)
Dims(x) == Dims(y) || throw(DimensionMismatch("dimensions must match"))
Space(_promote_space(Tuple(x), Tuple(y), ()))
end
promote_space(x::Space, y::Space, z::Space...) = promote_space(promote_space(x, y), z...)
## helper functions
_promote_space(x::Tuple{}, y::Tuple{}, promoted::Tuple) = promoted
function _promote_space(x::Tuple, y::Tuple, promoted::Tuple)
if x[1] == y[1]
_promote_space(Base.tail(x), Base.tail(y), (promoted..., x[1]))
else
_promote_space(_dropfirst(x...), _dropfirst(y...), (promoted..., Dims(x[1])[1]))
end
end

# tensortype
_typeof(x::Int) = x
_typeof(x::Symmetry) = typeof(x)
@pure function tensortype(x::Space)
Tensor{Tuple{map(_typeof, Tuple(x))...}, T, length(x), ncomponents(x)} where {T}
end

# LinearIndices/CartesianIndices
for IndicesType in (LinearIndices, CartesianIndices)
@eval (::Type{$IndicesType})(x::Space) = $IndicesType(Dims(x))
end
4 changes: 2 additions & 2 deletions src/Symmetry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ end

@generated function check_symmetry_parameters(::Type{S}) where {S <: Tuple}
if !all(x -> isa(x, Int), S.parameters)
return :(throw(ArgumentError("Symmetry parameter Size must be a tuple of Ints (e.g., `Symmetry{Tuple{3,3}}` or `@Symmetry{3,3}`).")))
return :(throw(ArgumentError("Symmetry parameter must be a tuple of Ints (e.g., `Symmetry{Tuple{3,3}}` or `@Symmetry{3,3}`).")))
end
if length(unique(S.parameters)) != 1
return :(throw(ArgumentError("Symmetry parameter Size must be unique, got $S.")))
return :(throw(ArgumentError("Symmetry parameter must be unique, got $S.")))
end
end

Expand Down
24 changes: 12 additions & 12 deletions src/Tensor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ end

@generated function check_tensor_parameters(::Type{S}, ::Type{T}, ::Val{N}, ::Val{L}) where {S, T, N, L}
check_size_parameters(S)
if length(Size(S)) != N
return :(throw(ArgumentError("Number of dimensions must be $(ndims(Size(S))) for $S size, got $N.")))
if length(Space(S)) != N
return :(throw(ArgumentError("Number of dimensions must be $(ndims(Space(S))) for $S size, got $N.")))
end
if ncomponents(Size(S)) != L
return :(throw(ArgumentError("Length of tuple data must be $(ncomponents(Size(S))) for $S size, got $L.")))
if ncomponents(Space(S)) != L
return :(throw(ArgumentError("Length of tuple data must be $(ncomponents(Space(S))) for $S size, got $L.")))
end
end

Expand All @@ -26,11 +26,11 @@ const Vec{dim, T} = Tensor{Tuple{dim}, T, 1, dim}

# constructors
@inline function Tensor{S, T}(data::Tuple{Vararg{Any, L}}) where {S, T, L}
N = length(Size(S))
N = length(Space(S))
Tensor{S, T, N, L}(data)
end
@inline function Tensor{S}(data::Tuple{Vararg{Any, L}}) where {S, L}
N = length(Size(S))
N = length(Space(S))
T = promote_ntuple_eltype(data)
Tensor{S, T, N, L}(data)
end
Expand All @@ -45,7 +45,7 @@ end
end
## from Function
@generated function (::Type{TT})(f::Function) where {TT <: Tensor}
S = Size(TT)
S = Space(TT)
tocartesian = CartesianIndices(S)
exps = [:(f($(Tuple(tocartesian[i])...))) for i in indices(S)]
quote
Expand All @@ -55,7 +55,7 @@ end
end
## from AbstractArray
@generated function (::Type{TT})(A::AbstractArray) where {TT <: Tensor}
S = Size(TT)
S = Space(TT)
if IndexStyle(A) isa IndexLinear
exps = [:(A[$i]) for i in indices(S)]
else
Expand Down Expand Up @@ -99,7 +99,7 @@ end
for (op, el) in ((:zero, :(zero(T))), (:ones, :(one(T))), (:rand, :(()->rand(T))), (:randn,:(()->randn(T))))
@eval begin
@inline Base.$op(::Type{Tensor{S}}) where {S} = $op(Tensor{S, Float64})
@inline Base.$op(::Type{Tensor{S, T}}) where {S, T} = Tensor{S, T}(fill_tuple($el, Val(ncomponents(Size(S)))))
@inline Base.$op(::Type{Tensor{S, T}}) where {S, T} = Tensor{S, T}(fill_tuple($el, Val(ncomponents(Space(S)))))
# for aliases
@inline Base.$op(::Type{Tensor{S, T, N}}) where {S, T, N} = $op(Tensor{S, T})
@inline Base.$op(::Type{Tensor{S, T, N, L}}) where {S, T, N, L} = $op(Tensor{S, T})
Expand Down Expand Up @@ -154,8 +154,8 @@ end
@inline Base.convert(::Type{TT}, x::TT) where {TT <: Tensor} = x
@inline Base.convert(::Type{TT}, x::AbstractArray) where {TT <: Tensor} = TT(x)
@generated function Base.convert(::Type{TT}, x::AbstractTensor) where {TT <: Tensor}
S = promote_size(Size(TT), Size(x))
S == Size(TT) ||
S = promote_space(Space(TT), Space(x))
S == Space(TT) ||
return :(throw(ArgumentError("Cannot `convert` an object of type $(typeof(x)) to an object of type $TT")))
exps = [getindex_expr(:x, x, i) for i in indices(S)]
quote
Expand All @@ -167,7 +167,7 @@ end
# promotion
@inline convert_eltype(::Type{T}, x::Real) where {T <: Real} = T(x)
@generated function convert_eltype(::Type{T}, x::Tensor) where {T <: Real}
S = Size(x)
S = Space(x)
TT = tensortype(S)
quote
@_inline_meta
Expand Down
6 changes: 3 additions & 3 deletions src/Tensorial.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import LinearAlgebra: dot, norm, tr, adjoint, det, cross, eigen, eigvals, eigvec
import Statistics: mean

export
# Symmetry/Size
# Symmetry/Space
Symmetry,
@Symmetry,
Size,
Space,
# AbstractTensor
AbstractTensor,
AbstractSecondOrderTensor,
Expand Down Expand Up @@ -59,7 +59,7 @@ export

include("utils.jl")
include("Symmetry.jl")
include("Size.jl")
include("Space.jl")
include("indexing.jl")
include("einsum.jl")
include("AbstractTensor.jl")
Expand Down
4 changes: 2 additions & 2 deletions src/ad.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ end
@inline extract_gradient(v::RealOrTensor, ::Real) = zero(v)
@inline extract_gradient(v::Real, x::Tensor{S}) where {S} = zero(Tensor{S, typeof(v)})
@generated function extract_gradient(v::Tensor, x::Tensor)
S = otimes(Size(v), Size(x))
S = otimes(Space(v), Space(x))
TT = tensortype(S)
quote
@_inline_meta
Expand All @@ -46,7 +46,7 @@ end
@inline extract_gradient(v::Dual, ::Real) = partials(v, 1)
@inline extract_gradient(v::Dual, x::Tensor{S}) where {S} = Tensor{S}(partials(v).values)
@generated function extract_gradient(v::Tensor{<: Tuple, <: Dual}, x::Tensor)
S = otimes(Size(v), Size(x))
S = otimes(Space(v), Space(x))
TT = tensortype(S)
exps = [:(partials(Tuple(v)[$i], $j)) for i in 1:ncomponents(v), j in 1:ncomponents(x)]
return quote
Expand Down
2 changes: 1 addition & 1 deletion src/indexing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function _duplicates(inds::TensorIndices)
end

for func in (:independent_indices, :indices, :duplicates)
@eval @generated function $func(::Size{S}) where {S}
@eval @generated function $func(::Space{S}) where {S}
arr = $(Symbol(:_, func))(TensorIndices(S))
quote
SArray{Tuple{$(size(arr)...)}, Int}($arr)
Expand Down
14 changes: 7 additions & 7 deletions src/ops.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@generated function _map(f, xs::Vararg{AbstractTensor, N}) where {N}
S = promote_size(map(Size, xs)...)
S = promote_space(map(Space, xs)...)
exps = map(indices(S)) do i
vals = [:(xs[$j][$i]) for j in 1:N]
:(f($(vals...)))
Expand All @@ -20,7 +20,7 @@ end
@inline Base.:-(x::AbstractTensor) = _map(-, x)

@generated function _add_uniform(x::AbstractSquareTensor{dim}, λ::Real) where {dim}
S = promote_size(Size(x), Size(Symmetry(dim, dim)))
S = promote_space(Space(x), Space(Symmetry(dim, dim)))
tocartesian = CartesianIndices(S)
exps = map(indices(S)) do i
i, j = Tuple(tocartesian[i])
Expand Down Expand Up @@ -49,7 +49,7 @@ Base.:*(::AbstractTensor, ::AbstractTensor) = error_multiply()
Base.:*(::AbstractTensor, ::UniformScaling) = error_multiply()
Base.:*(::UniformScaling, ::AbstractTensor) = error_multiply()

function contraction_exprs(S1::Size, S2::Size, ::Val{N}) where {N}
function contraction_exprs(S1::Space, S2::Space, ::Val{N}) where {N}
S = contraction(S1, S2, Val(N))
s1 = map(i -> EinsumIndex(:(Tuple(x)), i), independent_indices(S1))
s2 = map(i -> EinsumIndex(:(Tuple(y)), i), independent_indices(S2))
Expand Down Expand Up @@ -89,8 +89,8 @@ Following symbols are also available for specific contractions:
- `x ⊡ y` (where `⊡` can be typed by `\\boxdot<tab>`): `contraction(x, y, Val(2))`
"""
@generated function contraction(x::AbstractTensor, y::AbstractTensor, ::Val{N}) where {N}
S = contraction(Size(x), Size(y), Val(N))
exps = contraction_exprs(Size(x), Size(y), Val(N))
S = contraction(Space(x), Space(y), Val(N))
exps = contraction_exprs(Space(x), Space(y), Val(N))
T = promote_type(eltype(x), eltype(y))
if length(S) == 0
TT = T
Expand Down Expand Up @@ -439,8 +439,8 @@ end
## helper functions
@inline _powdot(x::AbstractSecondOrderTensor, y::AbstractSecondOrderTensor) = dot(x, y)
@generated function _powdot(x::AbstractSymmetricSecondOrderTensor{dim}, y::AbstractSymmetricSecondOrderTensor{dim}) where {dim}
S = Size(x)
exps = contraction_exprs(Size(x), Size(y), Val(1))
S = Space(x)
exps = contraction_exprs(Space(x), Space(y), Val(1))
quote
@_inline_meta
@inbounds SymmetricSecondOrderTensor{dim}($(exps[indices(S)]...))
Expand Down
Loading