
| Current Path : /home/cgabriel/20_dev/10_dev2017/1310__algorithms/Julia/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //home/cgabriel/20_dev/10_dev2017/1310__algorithms/Julia/distancefuncs.jl |
# generic concepts for distances
abstract PreMetric
abstract SemiMetric <: PreMetric
abstract Metric <: SemiMetric
type Euclidean <: Metric end
result_type(::PreMetric, T1::Type, T2::Type) = fptype(promote_type(T1, T2))
function colwise!(r::AbstractArray, metric::PreMetric, a::AbstractVector, b::AbstractMatrix)
n = size(b, 2)
length(r) == n || throw(DimensionMismatch("Incorrect size of r."))
for j = 1 : n
@inbounds r[j] = evaluate(metric, a, unsafe_view(b, :, j))
end
r
end
function colwise!(r::AbstractArray, metric::PreMetric, a::AbstractMatrix, b::AbstractVector)
n = size(a, 2)
length(r) == n || throw(DimensionMismatch("Incorrect size of r."))
for j = 1 : n
@inbounds r[j] = evaluate(metric, unsafe_view(a, :, j), b)
end
r
end
function colwise!(r::AbstractArray, metric::PreMetric, a::AbstractMatrix, b::AbstractMatrix)
n = get_common_ncols(a, b)
length(r) == n || throw(DimensionMismatch("Incorrect size of r."))
for j = 1 : n
@inbounds r[j] = evaluate(metric, unsafe_view(a, :, j), unsafe_view(b, :, j))
end
r
end
function colwise!(r::AbstractArray, metric::SemiMetric, a::AbstractMatrix, b::AbstractVector)
colwise!(r, metric, b, a)
end
function colwise(metric::PreMetric, a::AbstractMatrix, b::AbstractMatrix)
n = get_common_ncols(a, b)
r = Array(result_type(metric, eltype(a), eltype(b)), n)
colwise!(r, metric, a, b)
end
function colwise(metric::PreMetric, a::AbstractVector, b::AbstractMatrix)
n = size(b, 2)
r = Array(result_type(metric, eltype(a), eltype(b)), n)
colwise!(r, metric, a, b)
end
function colwise(metric::PreMetric, a::AbstractMatrix, b::AbstractVector)
n = size(a, 2)
r = Array(result_type(metric, eltype(a), eltype(b)), n)
colwise!(r, metric, a, b)
end
# Generic pairwise evaluation
function pairwise!(r::AbstractMatrix, metric::PreMetric, a::AbstractMatrix, b::AbstractMatrix)
na = size(a, 2)
nb = size(b, 2)
size(r) == (na, nb) || throw(DimensionMismatch("Incorrect size of r."))
for j = 1 : size(b, 2)
bj = unsafe_view(b,:,j)
for i = 1 : size(a, 2)
@inbounds r[i,j] = evaluate(metric, unsafe_view(a,:,i), bj)
end
end
r
end
function pairwise!(r::AbstractMatrix, metric::PreMetric, a::AbstractMatrix)
pairwise!(r, metric, a, a)
end
function pairwise!(r::AbstractMatrix, metric::SemiMetric, a::AbstractMatrix)
n = size(a, 2)
size(r) == (n, n) || throw(DimensionMismatch("Incorrect size of r."))
for j = 1 : n
aj = unsafe_view(a,:,j)
for i = j+1 : n
@inbounds r[i,j] = evaluate(metric, unsafe_view(a,:,i), aj)
end
@inbounds r[j,j] = 0
for i = 1 : j-1
@inbounds r[i,j] = r[j,i] # leveraging the symmetry of SemiMetric
end
end
r
end
function pairwise(metric::PreMetric, a::AbstractMatrix, b::AbstractMatrix)
m = size(a, 2)
n = size(b, 2)
r = Array(result_type(metric, eltype(a), eltype(b)), (m, n))
pairwise!(r, metric, a, b)
end
function pairwise(metric::PreMetric, a::AbstractMatrix)
n = size(a, 2)
r = Array(result_type(metric, eltype(a), eltype(a)), (n, n))
pairwise!(r, metric, a)
end
function pairwise(metric::SemiMetric, a::AbstractMatrix)
n = size(a, 2)
r = Array(result_type(metric, eltype(a), eltype(a)), (n, n))
pairwise!(r, metric, a)
end
evaluate(dist::Euclidean, a::AbstractVector, b::AbstractVector) = sqrt(sumsqdiff(a,b))
euclidean(a::AbstractVector, b::AbstractVector) = evaluate(Euclidean(), a, b)
function pairwise!(r::AbstractMatrix, dist::Euclidean, a::AbstractMatrix, b::AbstractMatrix)
m::Int, na::Int, nb::Int = get_pairwise_dims(r, a, b)
At_mul_B!(r, a, b)
sa2 = sumsq(a, 1)
sb2 = sumsq(b, 1)
for j = 1 : nb
for i = 1 : na
@inbounds v = sa2[i] + sb2[j] - 2 * r[i,j]
@inbounds r[i,j] = isnan(v) ? NaN : sqrt(max(v, 0.))
end
end
r
end
function pairwise!(r::AbstractMatrix, dist::Euclidean, a::AbstractMatrix)
m::Int, n::Int = get_pairwise_dims(r, a)
At_mul_B!(r, a, a)
sa2 = sumsq(a, 1)
for j = 1 : n
for i = 1 : j-1
@inbounds r[i,j] = r[j,i]
end
@inbounds r[j,j] = 0
for i = j+1 : n
@inbounds v = sa2[i] + sa2[j] - 2 * r[i,j]
@inbounds r[i,j] = isnan(v) ? NaN : sqrt(max(v, 0.))
end
end
r
end
type WeightedEuclidean{T<:FloatingPoint} <: Metric
weights::Vector{T}
end
type WeightedSqEuclidean{T<:FloatingPoint} <: SemiMetric
weights::Vector{T}
end
result_type{T}(::WeightedEuclidean{T}, T1::Type, T2::Type) = T
result_type{T}(::WeightedSqEuclidean{T}, T1::Type, T2::Type) = T
evaluate{T<:FloatingPoint}(dist::WeightedSqEuclidean{T}, a::AbstractVector, b::AbstractVector) = wsumsqdiff(dist.weights, a, b)
wsqeuclidean(a::AbstractVector, b::AbstractVector, w::AbstractVector) = evaluate(WeightedSqEuclidean(w), a, b)
function pairwise!{T<:FloatingPoint}(r::AbstractMatrix, dist::WeightedSqEuclidean{T}, a::AbstractMatrix, b::AbstractMatrix)
w = dist.weights
m::Int, na::Int, nb::Int = get_pairwise_dims(length(w), r, a, b)
sa2 = wsumsq(w, a, 1)
sb2 = wsumsq(w, b, 1)
wB = bmultiply(b, w, 1)
At_mul_B!(r, a, wB)
for j = 1 : nb
for i = 1 : na
@inbounds r[i,j] = sa2[i] + sb2[j] - 2 * r[i,j]
end
end
r
end
function pairwise!{T<:FloatingPoint}(r::AbstractMatrix, dist::WeightedSqEuclidean{T}, a::AbstractMatrix)
w = dist.weights
m::Int, n::Int = get_pairwise_dims(length(w), r, a)
sa2 = wsumsq(w, a, 1)
wA = bmultiply(a, w, 1)
At_mul_B!(r, a, wA)
for j = 1 : n
for i = 1 : j-1
@inbounds r[i,j] = r[j,i]
end
@inbounds r[j,j] = 0
for i = j+1 : n
@inbounds r[i,j] = sa2[i] + sa2[j] - 2 * r[i,j]
end
end
r
end
function evaluate{T<:FloatingPoint}(dist::WeightedEuclidean{T}, a::AbstractVector, b::AbstractVector)
sqrt(evaluate(WeightedSqEuclidean(dist.weights), a, b))
end
weuclidean(a::AbstractVector, b::AbstractVector, w::AbstractVector) = evaluate(WeightedEuclidean(w), a, b)
function colwise!{T<:FloatingPoint}(r::AbstractArray, dist::WeightedEuclidean{T}, a::AbstractMatrix, b::AbstractMatrix)
sqrt!(colwise!(r, WeightedSqEuclidean(dist.weights), a, b))
end
function colwise!{T<:FloatingPoint}(r::AbstractArray, dist::WeightedEuclidean{T}, a::AbstractVector, b::AbstractMatrix)
sqrt!(colwise!(r, WeightedSqEuclidean(dist.weights), a, b))
end
function pairwise!{T<:FloatingPoint}(r::AbstractMatrix, dist::WeightedEuclidean{T}, a::AbstractMatrix, b::AbstractMatrix)
sqrt!(pairwise!(r, WeightedSqEuclidean(dist.weights), a, b))
end
function pairwise!{T<:FloatingPoint}(r::AbstractMatrix, dist::WeightedEuclidean{T}, a::AbstractMatrix)
sqrt!(pairwise!(r, WeightedSqEuclidean(dist.weights), a))
end