From 0e42d4c622b7b4cd629990a7dd6bceddcf46b19b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20B=C3=A9renger?= Date: Thu, 23 Apr 2026 17:43:03 +0100 Subject: [PATCH] faster tanimoto implementation Hi Jean-Christophe, This implementation should be faster (two pop calls instead of three) and more robust (no div by 0). Results should be unchanged. Thanks to @rogersayle from the excellent https://nextmovesoftware.com/ for the heads up. Regards, Francois. --- bitv.ml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bitv.ml b/bitv.ml index 3130d83..64701d1 100644 --- a/bitv.ml +++ b/bitv.ml @@ -565,12 +565,13 @@ module L = S(struct let least_first = true end) module M = S(struct let least_first = false end) let tanimoto v1 v2 = - let l = v1.length in - if l <> v2.length then invalid_arg "Bitv.tanimoto"; - let a = pop v1 in - let b = pop v2 in - let c = pop (bw_and v1 v2) in - (float c) /. (float (a + b - c)) + if v1.length <> v2.length then invalid_arg "Bitv.tanimoto"; + let u_card = pop (bw_or v1 v2) in + if u_card = 0 then + 0.0 + else + (* |A n B| / |A u B| *) + (float (pop (bw_and v1 v2))) /. (float u_card) (* Input/output in a machine-independent format. *)