Skip to content

Commit

Permalink
type stable similar_from_indices
Browse files Browse the repository at this point in the history
  • Loading branch information
Jutho committed Nov 24, 2016
1 parent 82d4d00 commit 48b61c1
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/auxiliary/meta.jl
Expand Up @@ -15,7 +15,7 @@ _memjumps{N}(dims::NTuple{N,Int},strides::NTuple{N,Int}) = __memjumps((), dims,
@inline __memjumps{N}(jumps::NTuple{N}, dims::NTuple{N}, strides::NTuple{N}) = jumps
@inline __memjumps{N}(jumps::NTuple{N}, dims::Tuple, strides::Tuple) = @inbounds return __memjumps(tuple(jumps...,(dims[N+1]-1)*strides[N+1]), dims, strides)

_select(src::Tuple, sel::Tuple{Vararg{Int}}) = __select(dst, src, sel)
_select(src::Tuple, sel::Tuple{Vararg{Int}}) = __select((), src, sel)
@inline __select{N}(dst::NTuple{N}, src, sel::NTuple{N}) = dst
@inline __select{N}(dst::NTuple{N}, src, sel) = @inbounds return __select(tuple(dst...,src[sel[N+1]]), src, sel)

Expand Down
19 changes: 9 additions & 10 deletions src/auxiliary/stridedarray.jl
Expand Up @@ -2,34 +2,33 @@
#
# Simple auxiliary methods to interface with StridedArray from Julia Base.


"""`numind(A)`
Returns the number of indices of a tensor-like object `A`, i.e. for a multidimensional array (`<:AbstractArray`) we have `numind(A) = ndims(A)`. Also works in type domain.
"""
numind(A::AbstractArray) = ndims(A)
numind{T<:AbstractArray}(::Type{T}) = ndims(T)

"""`similar_from_indices(T, indices, A, conjA=Val{:N})`
"""`similar_from_indices(A, inds, T=eltype(A), conjA=Val{:N})`
Returns an object similar to `A` which has an `eltype` given by `T` and dimensions/sizes corresponding to a selection of those of `op(A)`, where the selection is specified by `indices` (which contains integer between `1` and `numind(A)`) and `op` is `conj` if `conjA=Val{:C}` or does nothing if `conjA=Val{:N}` (default).
"""
function similar_from_indices{T,CA}(::Type{T}, indices, A::StridedArray, ::Type{Val{CA}}=Val{:N})
dims = size(A)
return similar(A,T,dims[indices])
function similar_from_indices{T,CA}(A::AbstractArray, inds::Tuple, ::Type{T}=eltype(A), ::Type{Val{CA}}=Val{:N})
newinds = _select(Base.indices(A), inds)
return similar(A, T, newinds)
end

"""`similar_from_indices(T, indices, A, B, conjA=Val{:N}, conjB={:N})`
"""`similar_from_indices(A, B, indices, T=promote_type(eltype(A),eltype(B)) conjA=Val{:N}, conjB={:N})`
Returns an object similar to `A` which has an `eltype` given by `T` and dimensions/sizes corresponding to a selection of those of `op(A)` and `op(B)` concatenated, where the selection is specified by `indices` (which contains integers between `1` and `numind(A)+numind(B)` and `op` is `conj` if `conjA` or `conjB` equal `Val{:C}` or does nothing if `conjA` or `conjB` equal `Val{:N}` (default).
"""
function similar_from_indices{T,CA,CB}(::Type{T}, indices, A::StridedArray, B::StridedArray, ::Type{Val{CA}}=Val{:N}, ::Type{Val{CB}}=Val{:N})
dims = tuple(size(A)...,size(B)...)
return similar(A,T,dims[indices])
function similar_from_indices{T,CA,CB}(A::AbstractArray, B::AbstractArray, inds::Tuple, ::Type{T}=promote_type(eltype(A),eltype(B)), ::Type{Val{CA}}=Val{:N}, ::Type{Val{CB}}=Val{:N})
newinds = _select(tuple(Base.indices(A)...,Base.indices(B)...), inds)
return similar(A,T,newinds)
end

"""`scalar(C)`
Returns the single element of a tensor-like object with zero dimensions, i.e. if `numind(C)==0`.
"""
scalar(C::StridedArray) = numind(C)==0 ? C[1] : throw(DimensionMismatch())
scalar(C::AbstractArray) = numind(C)==0 ? C[1] : throw(DimensionMismatch())
2 changes: 1 addition & 1 deletion src/auxiliary/strideddata.jl
Expand Up @@ -14,7 +14,7 @@ typealias ConjugatedStridedData{N,T} StridedData{N,T,:C}

typealias StridedSubArray{T,N,A<:Array,I<:Tuple{Vararg{Union{Colon,Range{Int64},Int64}}},LD} SubArray{T,N,A,I,LD}

StridedData{N,T,C}(a::Array{T}, strides::NTuple{N,Int} = _strides(a), ::Type{Val{C}} = Val{:N}) =
StridedData{N,T,C}(a::Array{T}, strides::NTuple{N,Int} = strides(a), ::Type{Val{C}} = Val{:N}) =
StridedData{N,T,C}(vec(a), strides, 1)
StridedData{N,T,C}(a::StridedSubArray{T}, strides::NTuple{N,Int} = _strides(a), ::Type{Val{C}} = Val{:N}) =
StridedData{N,T,C}(vec(a.parent), strides, Base.first_index(a))
Expand Down
13 changes: 6 additions & 7 deletions src/functions/simple.jl
Expand Up @@ -13,7 +13,7 @@ function tensorcopy(A, IA, IC=IA)

checkindices(A, IA)
indCinA = add_indices(IA, IC)
C = similar_from_indices(eltype(A), indCinA, A)
C = similar_from_indices(A, tuple(indCinA...))
add!(1, A, Val{:N}, 0, C, indCinA)
end

Expand All @@ -32,11 +32,11 @@ function tensoradd(A, IA, B, IB, IC=IA)
checkindices(B, IB)
T = promote_type(eltype(A), eltype(B))
if IA == IC
C = similar_from_indices(T, 1:numind(A), A)
C = similar_from_indices(A, (1:numind(A)...), T)
copy!(C,A)
else
indCinA = add_indices(IA, IC)
C = similar_from_indices(T, indCinA, A)
C = similar_from_indices(A, tuple(indCinA...), T)
add_native!(1, A, Val{:N}, 0, C, indCinA)
end
indCinB = add_indices(IB, IC)
Expand All @@ -50,7 +50,7 @@ Trace or contract pairs of indices of array `A`, by assigning them an identical
function tensortrace(A, IA, IC = unique2(IA))
checkindices(A, IA)
indCinA, cindA1, cindA2 = trace_indices(IA,IC)
C = similar_from_indices(eltype(A), indCinA, A)
C = similar_from_indices(A, tuple(indCinA...))
trace!(1, A, Val{:N}, 0, C, indCinA, cindA1, cindA2)
end

Expand All @@ -67,9 +67,8 @@ function tensorcontract(A, IA, B, IB, IC = symdiff(IA,IB); method::Symbol = :BLA
oindA, cindA, oindB, cindB, indCinoAB = contract_indices(IA, IB, IC)
indCinAB = vcat(oindA,length(IA)+oindB)[indCinoAB]

T = promote_type(eltype(A), eltype(B))
C = similar_from_indices(T, indCinAB, A, B)

C = similar_from_indices(A, B, tuple(indCinAB...))

if method == :BLAS
contract!(1, A, Val{:N}, B, Val{:N}, 0, C, oindA, cindA, oindB, cindB, indCinoAB,Val{:BLAS})
elseif method == :native
Expand Down
9 changes: 5 additions & 4 deletions src/indexnotation/indexedobject.jl
Expand Up @@ -10,7 +10,7 @@ immutable Indices{I}
end

abstract AbstractIndexedObject
indices(a::AbstractIndexedObject) = indices(typeof(a))
indexlabels(a::AbstractIndexedObject) = indexlabels(typeof(a))

immutable IndexedObject{I,C,A,T} <: AbstractIndexedObject
object::A
Expand All @@ -32,7 +32,7 @@ Base.eltype{I,C, A, T}(::Type{IndexedObject{I,C, A, T}}) = promote_type(eltype(A
*::Number, a::IndexedObject) = *(a, β)
-(a::IndexedObject) = *(a, -1)

@generated function indices{I,C,A,T}(::Type{IndexedObject{I,C,A,T}})
@generated function indexlabels{I,C,A,T}(::Type{IndexedObject{I,C,A,T}})
J = tuple(unique2(I)...)
meta = Expr(:meta, :inline)
Expr(:block, meta, :($J))
Expand All @@ -46,10 +46,11 @@ deindexify{I}(A::IndexedObject{I,:C}, ::Indices{I}) = A.α == 1 ? conj(A.object)
@generated function deindexify{I,C,J}(A::IndexedObject{I,C}, ::Indices{J}, T::Type = eltype(A))
meta = Expr(:meta, :inline)
indCinA, = trace_indices(I,J)
conj = Val{C}
indCinA = tuple(indCinA...)
conj = Val{:C}
quote
$meta
deindexify!(similar_from_indices(T, $indCinA, A.object, $conj), A, Indices{$J}())
deindexify!(similar_from_indices(A.object, $indCinA, T, $conj), A, Indices{$J}())
end
end

Expand Down
10 changes: 5 additions & 5 deletions src/indexnotation/product.jl
Expand Up @@ -16,16 +16,16 @@ Base.eltype(P::ProductOfIndexedObjects) = promote_type(eltype(P.A),eltype(P.B))
*::Number, P::ProductOfIndexedObjects) = *(P,β)
-(P::ProductOfIndexedObjects) = *(-1, P)

@generated function indices{IA,IB,CA,CB,OA,OB,TA,TB}(::Type{ProductOfIndexedObjects{IA,IB,CA,CB,OA,OB,TA,TB}})
@generated function indexlabels{IA,IB,CA,CB,OA,OB,TA,TB}(::Type{ProductOfIndexedObjects{IA,IB,CA,CB,OA,OB,TA,TB}})
J = unique2([IA...,IB...])
J = tuple(J...)
meta = Expr(:meta, :inline)
Expr(:block, meta, :($J))
end

@generated function *(A::AbstractIndexedObject,B::AbstractIndexedObject)
IA = indices(A)
IB = indices(B)
IA = indexlabels(A)
IB = indexlabels(B)
IC = symdiff(IA,IB)
oindA, cindA, oindB, cindB, = contract_indices(IA,IB,IC)
meta = Expr(:meta,:inline)
Expand All @@ -52,12 +52,12 @@ end
@generated function deindexify{IA,IB,CA,CB,IC}(P::ProductOfIndexedObjects{IA,IB,CA,CB}, I::Indices{IC}, T::Type = eltype(P))
meta = Expr(:meta, :inline)
oindA, cindA, oindB, cindB, indCinoAB = contract_indices(IA, IB, IC)
indCinAB = vcat(oindA,length(IA)+oindB)[indCinoAB]
indCinAB = tuple(vcat(oindA,length(IA)+oindB)[indCinoAB]...)
conjA = Val{CA}
conjB = Val{CB}
quote
$meta
deindexify!(similar_from_indices(T, $indCinAB, P.A.object, P.B.object, $conjA, $conjB), P, I)
deindexify!(similar_from_indices(P.A.object, P.B.object, $indCinAB, T, $conjA, $conjB), P, I)
end
end

Expand Down
8 changes: 4 additions & 4 deletions src/indexnotation/sum.jl
Expand Up @@ -22,22 +22,22 @@ Base.eltype(A::SumOfIndexedObjects) = _eltypetuple(A.objects)
*::Number, A::SumOfIndexedObjects) = SumOfIndexedObjects(_multuple(β, A.objects))
-(A::SumOfIndexedObjects) = *(-1, A)

indices{Os}(A::SumOfIndexedObjects{Os}) = indices(Os.parameters[1])
indexlabels{Os}(A::SumOfIndexedObjects{Os}) = indexlabels(Os.parameters[1])

function +(A::SumOfIndexedObjects, B::SumOfIndexedObjects)
add_indices(indices(A), indices(B)) # performs index check
SumOfIndexedObjects(tuple(A.objects..., B.objects...))
end
function +(A::SumOfIndexedObjects, b::AbstractIndexedObject)
add_indices(indices(A), indices(b)) # performs index check
add_indices(indexlabels(A), indexlabels(b)) # performs index check
SumOfIndexedObjects(tuple(A.objects..., b))
end
function +(a::AbstractIndexedObject, B::SumOfIndexedObjects)
add_indices(indices(a), indices(B)) # performs index check
add_indices(indexlabels(a), indexlabels(B)) # performs index check
SumOfIndexedObjects(tuple(a, B.objects...))
end
function +(a::AbstractIndexedObject, b::AbstractIndexedObject)
add_indices(indices(a), indices(b)) # performs index check
add_indices(indexlabels(a), indexlabels(b)) # performs index check
SumOfIndexedObjects(tuple(a, b))
end

Expand Down

0 comments on commit 48b61c1

Please sign in to comment.