diff --git a/.gitignore b/.gitignore index 58549d0..807b272 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ *.jl.*.cov *.jl.mem *.ji +.vscode/ benchmark/params.json Manifest.toml \ No newline at end of file diff --git a/src/metrics.jl b/src/metrics.jl index ec4de63..4cd0920 100644 --- a/src/metrics.jl +++ b/src/metrics.jl @@ -394,6 +394,24 @@ weuclidean(a, b, w) = WeightedEuclidean(w)(a, b) s3 = min(s2, p - s2) abs2(s3) end + +function _evaluate(dist::PeriodicEuclidean, a::AbstractVector, b::AbstractVector, p::AbstractMatrix) + ndim = LinearAlgebra.checksquare(p) + @boundscheck if length(a) != length(b) + throw(DimensionMismatch("first array has length $(length(a)) which does not match the length of the second, $(length(b)).")) + end + @boundscheck if length(a) != ndim + throw(DimensionMismatch("arrays have length $(length(a)) but basis vectors have length $ndim.")) + end + s = p \ (a - b) # decompose to p-basis, a - b = sx x⃗ + sy y⃗ + ... + mindistance = Inf + s = mod.(s, 1) # move to first "quadrant" + @inbounds for k = 0:1<view(p,:,i) .* (k>>(i-1) & 1 == 0 ? s[i] : s[i]-1), 1:ndim) + mindistance = min(norm(loc), mindistance) + end + return mindistance +end eval_end(::PeriodicEuclidean, s) = sqrt(s) peuclidean(a, b, p) = PeriodicEuclidean(p)(a, b) diff --git a/test/test_dists.jl b/test/test_dists.jl index dfe66d2..4139830 100644 --- a/test/test_dists.jl +++ b/test/test_dists.jl @@ -982,3 +982,11 @@ end end end =# + +@testset "periodic - non-rectangular" begin + # basis vectors: [10, 10], [0, 10] + p = PeriodicEuclidean([10 0.0; 10.0 10.0]) # each column is a basis vector. + @test p([10.1, 10.2], [-10.0, 0.0]) ≈ sqrt(0.1^2 + 0.2^2) + @test p([9.9, 10.2], [-10.0, 0.0]) ≈ sqrt(0.1^2 + 0.2^2) + @test p([9.9, 9.8], [-10.0, 0.0]) ≈ sqrt(0.1^2 + 0.2^2) +end \ No newline at end of file