Move SSD detector IoU helper to typed Kotlin

ober

68f262b222a0c114be1ea9e767d7f579de79ebf3

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index c0d1cac..7aa6aba 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -32,7 +32,7 @@
                 SsdCell-h SsdCell-h-set!
                 SsdCell-detector
                 ssdCellCx ssdCellCy ssdCellRect
-                rectOverlapArea rectCenterInside)
+                rectOverlapArea rectCenterInside iou)
         (type Float32)
         (type FloatArray)
         (type Int32)
@@ -93,7 +93,15 @@
             (and (>= cx (float-array-ref area (int32 0)))
                  (<= cx (float-array-ref area (int32 2)))
                  (>= cy (float-array-ref area (int32 1)))
-                 (<= cy (float-array-ref area (int32 3))))))))
+                 (<= cy (float-array-ref area (int32 3))))))
+        (def (iou (a : SsdCell) (b : SsdCell)) : Float32
+          (let ((overlap (rectOverlapArea (ssdCellRect a) (ssdCellRect b))))
+            (if (<= overlap (float32 0.0))
+              (float32 0.0)
+              (/ overlap
+                 (- (+ (* (SsdCell-w a) (SsdCell-h a))
+                       (* (SsdCell-w b) (SsdCell-h b)))
+                    overlap)))))))
 
     (typed-kotlin-file "com/sfb/ssdreview/Component.kt"
       (typed-library (com sfb ssdreview)
@@ -3052,12 +3060,6 @@
        "        return horizontal || vertical"
        "    }"
        ""
-       "    private fun iou(a: SsdCell, b: SsdCell): Float {"
-       "        val overlap = rectOverlapArea(ssdCellRect(a), ssdCellRect(b))"
-       "        if (overlap <= 0f) return 0f"
-       "        return overlap / (a.w * a.h + b.w * b.h - overlap)"
-       "    }"
-       ""
        "    private fun grayscale(pixels: IntArray): IntArray = IntArray(pixels.size) { index ->"
        "        val pixel = pixels[index]"
        "        val r = (pixel shr 16) and 0xff"