@@ -892,6 +892,87 @@ opnorm(v::TransposeAbsVec) = norm(v.parent)
892892
893893norm (v:: AdjOrTrans , p:: Real ) = norm (v. parent, p)
894894
895+ """
896+ lpdist(x::T, y::T, p::Int) where {T <: AbstractVector}
897+ lpdist(x::T, y::T, p::Real) where {T <: AbstractVector}
898+
899+ Computes the Lₚ distance between two vectors `x` and `y`, defined as:
900+ for 0 < p < Inf: Lₚ dist = ᵖ√(Σ|xᵢ - yᵢ|ᵖ)
901+ for p = 0: count of mismatches for p = 0
902+ for p + Inf: L_∞ = maxᵢ(abs(xᵢ - yᵢ))
903+ """
904+
905+ function _lpunnorm (x:: T , y:: T , fn) where {T}
906+ r = 0.0
907+ for i in eachindex (x,y)
908+ @inbounds r += fn (x[i] - y[i])
909+ end
910+ end
911+
912+
913+ function lpdist (x:: T , y:: T , p:: Int ) where {T <: AbstractVector }
914+ p < 0 && throw (DomainError (" p must be non-negative" ))
915+ length (x) == length (y) || throw (DimensionMismatch (" x and y have different lenghts" ))
916+ if p == 0
917+ @warn (" Technically not a distance metric for p = 0" )
918+ fn = ! iszero # simply count number of nonzeros
919+ elseif p == 1
920+ fn = abs
921+ elseif p == 2
922+ fn = abs2
923+ else
924+ fn = x -> abs (u)^ p
925+ end
926+ r = _lpunnorm (x, y, fn)
927+
928+ p <= 1 && return r
929+ p == 2 && return √ r
930+
931+ return r^ (1 / p)
932+ end
933+
934+ function lpdist (x:: T , y:: T , p:: Real ) where {T <: AbstractVector }
935+ length (x) == length (y) || throw (DimensionMismatch (" x and y have different lenghts" ))
936+ p < 0 && throw (DomainError (" p must be non-negative" ))
937+ p < 1 || @warn (" Technically not a distance metric for 0 < p < 1" )
938+
939+ # handle inf norm separatey
940+ if p == Inf
941+ r = 0.0
942+ for i in eachindex (x,y)
943+ @inbounds r = max (x[i] - y[i], r)
944+ end
945+ return r
946+ elseif iszero (p)
947+ return lpdist (x, y, 0 )
948+ else
949+ fn = u -> abs (u)^ p
950+ end
951+ r = _lpunnorm (x, y, fn)
952+
953+ return r^ (1 / p)
954+ end
955+
956+ """
957+ euclidean(x::T, y::T)
958+ l2dist(x::T, y::T)
959+
960+ Compute the L₂ distance between vectors x and y.
961+ Basically just aliases for lpdist(x, y, 2)
962+ """
963+ euclidean (x:: T , y:: T ) where {T <: AbstractVector } = lpdist (x, y, 2 )
964+ l2dist (x:: T , y:: T ) where {T <: AbstractVector } = lpdist (x, y, 2 )
965+
966+ """
967+ l1dist(x::T, y::T)
968+
969+ Compute the L₁ distance between vectors x and y.
970+ Basically just an alias for lpdist(x, y, 1)
971+ """
972+ l1dist (x:: T , y:: T ) where {T <: AbstractVector } = lpdist (x, y, 1 )
973+
974+
975+ # # dot products
895976"""
896977 dot(x, y)
897978 x ⋅ y
0 commit comments