Skip to content
Open
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: 2 additions & 0 deletions src/common.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ function depcheck(fname::Symbol, varname::Symbol, b::Union{Bool, Nothing})
b
end
end

_add((x1, x2)::Tuple{<:Real,<:Real}, (y1, y2)::Tuple{<:Real,<:Real}) = (x1 + y1, x2 + y2)
88 changes: 46 additions & 42 deletions src/deviation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Count the number of indices at which the elements of the arrays
"""
function counteq(a::AbstractArray, b::AbstractArray)
n = length(a)
length(b) == n || throw(DimensionMismatch("Inconsistent lengths."))
length(b) == n || throw(DimensionMismatch("Inconsistent array lengths."))
c = 0
for i in eachindex(a, b)
if a[i] == b[i]
Expand All @@ -29,7 +29,7 @@ Count the number of indices at which the elements of the arrays
"""
function countne(a::AbstractArray, b::AbstractArray)
n = length(a)
length(b) == n || throw(DimensionMismatch("Inconsistent lengths."))
length(b) == n || throw(DimensionMismatch("Inconsistent array lengths."))
c = 0
for i in eachindex(a, b)
if a[i] != b[i]
Expand All @@ -46,12 +46,14 @@ end
Compute the squared L2 distance between two arrays: ``\\sum_{i=1}^n |a_i - b_i|^2``.
Efficient equivalent of `sum(abs2, a - b)`.
"""
function sqL2dist(a::AbstractArray{T}, b::AbstractArray{T}) where T<:Number
function sqL2dist(a::AbstractArray{<:Number}, b::AbstractArray{<:Number})
n = length(a)
length(b) == n || throw(DimensionMismatch("Input dimension mismatch"))
r = 0.0
for i in eachindex(a, b)
r += abs2(a[i] - b[i])
length(b) == n || throw(DimensionMismatch("Inconsistent array lengths."))
if iszero(n)
r = zero(abs2(zero(eltype(a)) - zero(eltype(b))))
else
broadcasted = Broadcast.broadcasted((ai, bi) -> abs2(ai - bi), vec(a), vec(b))
r = sum(Broadcast.instantiate(broadcasted))
end
return r
end
Expand All @@ -64,7 +66,7 @@ end
Compute the L2 distance between two arrays: ``\\sqrt{\\sum_{i=1}^n |a_i - b_i|^2}``.
Efficient equivalent of `sqrt(sum(abs2, a - b))`.
"""
L2dist(a::AbstractArray{T}, b::AbstractArray{T}) where {T<:Number} = sqrt(sqL2dist(a, b))
L2dist(a::AbstractArray{<:Number}, b::AbstractArray{<:Number}) = sqrt(sqL2dist(a, b))


# L1 distance
Expand All @@ -74,12 +76,14 @@ L2dist(a::AbstractArray{T}, b::AbstractArray{T}) where {T<:Number} = sqrt(sqL2di
Compute the L1 distance between two arrays: ``\\sum_{i=1}^n |a_i - b_i|``.
Efficient equivalent of `sum(abs, a - b)`.
"""
function L1dist(a::AbstractArray{T}, b::AbstractArray{T}) where T<:Number
function L1dist(a::AbstractArray{<:Number}, b::AbstractArray{<:Number})
n = length(a)
length(b) == n || throw(DimensionMismatch("Input dimension mismatch"))
r = 0.0
for i in eachindex(a, b)
r += abs(a[i] - b[i])
length(b) == n || throw(DimensionMismatch("Inconsistent array lengths."))
if iszero(n)
r = zero(abs(zero(eltype(a)) - zero(eltype(b))))
else
broadcasted = Broadcast.broadcasted((ai, bi) -> abs(ai - bi), vec(a), vec(b))
r = sum(Broadcast.instantiate(broadcasted))
end
return r
end
Expand All @@ -93,15 +97,14 @@ Compute the L∞ distance, also called the Chebyshev distance, between
two arrays: ``\\max_{1≤i≤n} |a_i - b_i|``.
Efficient equivalent of `maxabs(a - b)`.
"""
function Linfdist(a::AbstractArray{T}, b::AbstractArray{T}) where T<:Number
function Linfdist(a::AbstractArray{<:Number}, b::AbstractArray{<:Number})
n = length(a)
length(b) == n || throw(DimensionMismatch("Input dimension mismatch"))
r = 0.0
for i in eachindex(a, b)
v = abs(a[i] - b[i])
if r < v
r = v
end
length(b) == n || throw(DimensionMismatch("Inconsistent array lengths."))
if iszero(n)
r = zero(abs(zero(eltype(a)) - zero(eltype(b))))
else
broadcasted = Broadcast.broadcasted((ai, bi) -> abs(ai - bi), vec(a), vec(b))
r = maximum(Broadcast.instantiate(broadcasted))
end
return r
end
Expand All @@ -115,19 +118,20 @@ Compute the generalized Kullback-Leibler divergence between two arrays:
``\\sum_{i=1}^n (a_i \\log(a_i/b_i) - a_i + b_i)``.
Efficient equivalent of `sum(a*log(a/b)-a+b)`.
"""
function gkldiv(a::AbstractArray{T}, b::AbstractArray{T}) where T<:AbstractFloat
function gkldiv(a::AbstractArray{<:Real}, b::AbstractArray{<:Real})
n = length(a)
r = 0.0
for i in eachindex(a, b)
ai = a[i]
bi = b[i]
if ai > 0
r += (ai * log(ai / bi) - ai + bi)
else
r += bi
length(b) == n || throw(DimensionMismatch("Inconsistent array lengths."))
if iszero(n)
za = zero(eltype(a))
zb = zero(eltype(b))
r = zero(xlogy(za, za / zb) + (zb - za))
else
broadcasted = Broadcast.broadcasted(vec(a), vec(b)) do ai, bi
return xlogy(ai, ai / bi) + (bi - ai)
end
return sum(Broadcast.instantiate(broadcasted))
end
return r::Float64
return r
end


Expand All @@ -137,8 +141,7 @@ end

Return the mean absolute deviation between two arrays: `mean(abs, a - b)`.
"""
meanad(a::AbstractArray{T}, b::AbstractArray{T}) where {T<:Number} =
L1dist(a, b) / length(a)
meanad(a::AbstractArray{<:Number}, b::AbstractArray{<:Number}) = L1dist(a, b) / length(a)


# MaxAD: maximum absolute deviation
Expand All @@ -147,7 +150,7 @@ meanad(a::AbstractArray{T}, b::AbstractArray{T}) where {T<:Number} =

Return the maximum absolute deviation between two arrays: `maxabs(a - b)`.
"""
maxad(a::AbstractArray{T}, b::AbstractArray{T}) where {T<:Number} = Linfdist(a, b)
maxad(a::AbstractArray{<:Number}, b::AbstractArray{<:Number}) = Linfdist(a, b)


# MSD: mean squared deviation
Expand All @@ -156,8 +159,7 @@ maxad(a::AbstractArray{T}, b::AbstractArray{T}) where {T<:Number} = Linfdist(a,

Return the mean squared deviation between two arrays: `mean(abs2, a - b)`.
"""
msd(a::AbstractArray{T}, b::AbstractArray{T}) where {T<:Number} =
sqL2dist(a, b) / length(a)
msd(a::AbstractArray{<:Number}, b::AbstractArray{<:Number}) = sqL2dist(a, b) / length(a)


# RMSD: root mean squared deviation
Expand All @@ -168,13 +170,14 @@ Return the root mean squared deviation between two optionally
normalized arrays. The root mean squared deviation is computed
as `sqrt(msd(a, b))`.
"""
function rmsd(a::AbstractArray{T}, b::AbstractArray{T}; normalize::Bool=false) where T<:Number
function rmsd(a::AbstractArray{<:Number}, b::AbstractArray{<:Number}; normalize::Bool=false)
v = sqrt(msd(a, b))
if normalize
amin, amax = extrema(a)
v /= (amax - amin)
amin, amax = isempty(a) ? (zero(eltype(a)), zero(eltype(a))) : extrema(a)
return v / (amax - amin)
else
return v
end
return v
end


Expand All @@ -186,6 +189,7 @@ Compute the peak signal-to-noise ratio between two arrays `a` and `b`.
`maxv` is the maximum possible value either array can take. The PSNR
is computed as `10 * log10(maxv^2 / msd(a, b))`.
"""
function psnr(a::AbstractArray{T}, b::AbstractArray{T}, maxv::Real) where T<:Real
20. * log10(maxv) - 10. * log10(msd(a, b))
function psnr(a::AbstractArray{<:Real}, b::AbstractArray{<:Real}, maxv::Real)
msd_a_b, _maxv = promote(msd(a, b), maxv)
return 20 * log10(_maxv) - 10 * log10(msd_a_b)
end
Loading