I'm trying to implement Meijster distance transform algorithm in Halide. I've already rewritten this code to C++ (using openCV) and it's working fine. The paper about this algorithm is here. Right now my halide code is 50% complete - first phase is working fine, now i've got problem with phase 2 (scan 3 in the linked code) which (simplified) look like this:
//g is 2 dimensional cv::Mat (something like array) - result of previous stage
// m is g.width and n is g.height
int(*functionF)(int x, int i, int g_i) = EDT_f;
int(*functionSep)(int i, int u, int g_i, int g_u, int max_value) = EDT_Sep;
cv::Mat dt = cv::Mat(n, m, CV_32SC1);
int* s = new int[m];
int* t = new int[m];
int q = 0, w;
for (int y = 0; y<n; y++)
{
q = 0;
s[0] = 0;
t[0] = 0;
// Scan 3
for (int u = 1; u<m; u++)
{
//how can i replace this loop:
while (q >= 0 && functionF(t[q], s[q], g.at<int>(y, s[q])) > functionF(t[q], u, g.at<int>(y, u)))
q--;
//some operations which might change value of q, s[] and t[]
}
// Scan 4 - not important here
}
Is there any halide-friendly way to replace this while loop? Right now the only solution i've come so far is smething like this (not tested yet):
Expr calculateQ(Expr currentQValue, Expr y, Func t, Func s, Func g)
{
//while (q >= 0 && functionF(t[q], s[q], g.at<int>(y, s[q])) > functionF(t[q], u, g.at<int>(y, u)))
//q--;
return select(currentQValue >= 0 && functionF(t[q], s[q], g[s[q], y]) > functionF(t[q], u, g[u, y]), calculateQ(currentQValue - 1, y, t, s, g), currentQValue);
}
but even if this will work, most likely halide will try to evaluate both values of select before checking the condition and recursion will make it very slow.
If there is no way to implement while loop in Halide is there any way to just use some part of your code inside Halide? Any other ideas?