From 67da3c23594a0bfb4268892b9e190c026ff2b1e1 Mon Sep 17 00:00:00 2001
From: Mingchung Xia <mingchung.xia@gmail.com>
Date: Sat, 16 Mar 2024 16:59:52 -0400
Subject: [PATCH] Added basic linux support for similarity metrics

---
 .../HNSW/CartesianDistanceMetric.swift        | 19 ++++++++++++++++++
 .../HNSW/CosineSimilarityMetric.swift         | 20 +++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/Sources/SwiftNLP/1. Data Collection/HNSW/CartesianDistanceMetric.swift b/Sources/SwiftNLP/1. Data Collection/HNSW/CartesianDistanceMetric.swift
index 3b2b7dc6..70678a58 100644
--- a/Sources/SwiftNLP/1. Data Collection/HNSW/CartesianDistanceMetric.swift	
+++ b/Sources/SwiftNLP/1. Data Collection/HNSW/CartesianDistanceMetric.swift	
@@ -26,6 +26,10 @@
 
 import Foundation
 import SimilarityMetric
+
+#if canImport(Surge) && canImport(Accelerate) && os(macOS)
+
+import Accelerate
 import Surge
 
 public struct CartesianDistanceMetric<Vector: Collection & Codable>: SimilarityMetric where Vector.Element: BinaryFloatingPoint {
@@ -33,3 +37,18 @@ public struct CartesianDistanceMetric<Vector: Collection & Codable>: SimilarityM
         return Vector.Element(Surge.distSq(someItem as! [Double], otherItem as! [Double]))
     }
 }
+
+#else
+
+// This may be less efficient on Linux
+
+public struct CartesianDistanceMetric<Vector: Collection & Codable>: SimilarityMetric where Vector.Element: BinaryFloatingPoint {
+    public func similarity(between someItem: Vector, _ otherItem: Vector) -> Vector.Element {
+        return someItem.enumerated().reduce(0) { result, item in
+            let diff = item.element - otherItem[item.offset]
+            return result + diff * diff
+        }
+    }
+}
+
+#endif
diff --git a/Sources/SwiftNLP/1. Data Collection/HNSW/CosineSimilarityMetric.swift b/Sources/SwiftNLP/1. Data Collection/HNSW/CosineSimilarityMetric.swift
index 54d10b68..66b2f389 100644
--- a/Sources/SwiftNLP/1. Data Collection/HNSW/CosineSimilarityMetric.swift	
+++ b/Sources/SwiftNLP/1. Data Collection/HNSW/CosineSimilarityMetric.swift	
@@ -5,6 +5,8 @@
 //  Created by Mingchung Xia on 2024-03-14.
 //
 
+#if canImport(Surge) && canImport(Accelerate) && os(macOS)
+
 import Foundation
 import Accelerate
 import SimilarityMetric
@@ -33,3 +35,21 @@ public struct CosineSimilarityMetric<Vector: Collection & Codable>: SimilarityMe
         return Vector.Element(cosineSimilarity)
     }
 }
+
+#else
+
+// This may be less efficient on Linux
+
+public struct CosineSimilarityMetric<Vector: Collection & Codable>: SimilarityMetric where Vector.Element: BinaryFloatingPoint {
+    public func similarity(between someItem: Vector, _ otherItem: Vector) -> Vector.Element {
+        let dotProduct = zip(someItem, otherItem).reduce(0) { $0 + $1.0 * $1.1 }
+        let magnitudeSomeItem = sqrt(someItem.reduce(0) { $0 + $1 * $1 })
+        let magnitudeOtherItem = sqrt(otherItem.reduce(0) { $0 + $1 * $1 })
+        
+        let cosineSimilarity = dotProduct / (magnitudeSomeItem * magnitudeOtherItem)
+        
+        return cosineSimilarity
+    }
+}
+
+#endif
-- 
GitLab