diff --git a/src/annoygomodule.h b/src/annoygomodule.h index fdcc10c3..80d03131 100644 --- a/src/annoygomodule.h +++ b/src/annoygomodule.h @@ -73,6 +73,14 @@ class AnnoyIndexEuclidean : public AnnoyIndex { } }; +class AnnoyIndexChamming : public AnnoyIndex { + public: + AnnoyIndexChamming(int f) { + ptr = new ::AnnoyIndex(f); + this->f = f; + } +}; + class AnnoyIndexManhattan : public AnnoyIndex { public: AnnoyIndexManhattan(int f) { diff --git a/src/annoygomodule.i b/src/annoygomodule.i index 9882cbeb..5b9d3466 100644 --- a/src/annoygomodule.i +++ b/src/annoygomodule.i @@ -90,6 +90,7 @@ %feature("notabstract") GoAnnoyIndexAngular; %feature("notabstract") GoAnnoyIndexEuclidean; +%feature("notabstract") GoAnnoyIndexChamming; %feature("notabstract") GoAnnoyIndexManhattan; diff --git a/src/annoylib.h b/src/annoylib.h index 9928c996..bfd73f8b 100644 --- a/src/annoylib.h +++ b/src/annoylib.h @@ -365,6 +365,35 @@ struct Euclidean : Minkowski{ } }; +struct Chamming : Minkowski{ + template + static inline T distance(const T* x, const T* y, int f) { + T d = 0.0; + for (int i = 0; i < f; i++, x++, y++) + d += ((*x) != (*y)); + return d; + } + template + static inline void create_split(const vector*>& nodes, int f, Random& random, Node* n) { + vector best_iv(f, 0), best_jv(f, 0); + two_means >(nodes, f, random, false, &best_iv[0], &best_jv[0]); + + for (int z = 0; z < f; z++) + n->v[z] = best_iv[z] - best_jv[z]; + normalize(n->v, f); + n->a = 0.0; + for (int z = 0; z < f; z++) + n->a += -n->v[z] * (best_iv[z] + best_jv[z]) / 2; + } + template + static inline T normalized_distance(T distance) { + return std::max(distance, T(0)); + } + static const char* name() { + return "chamming"; + } +}; + struct Manhattan : Minkowski{ template static inline T distance(const T* x, const T* y, int f) { diff --git a/src/annoyluamodule.cc b/src/annoyluamodule.cc index ad10a2b3..d01cb73f 100644 --- a/src/annoyluamodule.cc +++ b/src/annoyluamodule.cc @@ -275,6 +275,9 @@ static int lua_an_make(lua_State* L) { } else if (strcmp(metric, "euclidean") == 0) { LuaAnnoy::createNew(L, f); return 1; + } else if (strcmp(metric, "chamming") == 0) { + LuaAnnoy::createNew(L, f); + return 1; } else if (strcmp(metric, "manhattan") == 0) { LuaAnnoy::createNew(L, f); return 1; diff --git a/src/annoymodule.cc b/src/annoymodule.cc index ac465f48..28f9cb89 100644 --- a/src/annoymodule.cc +++ b/src/annoymodule.cc @@ -125,6 +125,8 @@ py_an_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { self->ptr = new AnnoyIndex(self->f); } else if (!strcmp(metric, "euclidean")) { self->ptr = new AnnoyIndex(self->f); + } else if (!strcmp(metric, "chamming")) { + self->ptr = new AnnoyIndex(self->f); } else if (!strcmp(metric, "manhattan")) { self->ptr = new AnnoyIndex(self->f); } else if (!strcmp(metric, "hamming")) {