 /*************************************************************
  * V1: device side
  *************************************************************/
+
+__device__
+inline float compute_angle( int bin, float hc, float hn, float hp )
+{
+    /* interpolate */
+    float di = bin + 0.5f * (hn - hp) / (hc+hc-hn-hp);
+
+    /* clamp */
+    di = (di < 0) ? 
+            (di + NBINS_V1) : 
+            ((di >= NBINS_V1) ? (di - NBINS_V1) : (di));
+
+    float th = ((M_PI2 * di) / NBINS_V1) - M_PI;
+    // float th = ((M_PI2 * di) / NBINS_V1);
+    return th;
+}
 
 /*
  * Compute the keypoint orientations for each extremum


    /* find histogram maximum */
    float maxh = NINF;
    for (int bin = 0; bin < NBINS_V1; bin++) {
        maxh = fmaxf(maxh, hist[bin]);
    }

    /* find other peaks, boundary of 80% of max */
    int nangles = 0;
    for (int bin = 0; bin < NBINS_V1; bin++) {
        float hc = hist[bin];
        float hn = hist[((bin+1+NBINS_V1)%NBINS_V1)];
        float hp = hist[((bin-1+NBINS_V1)%NBINS_V1)];

        /* find if a peak */
        if (hc >= (0.8f * maxh) && hc > hn && hc > hp) {
    
            /* interpolate */
            float di = bin + 0.5f * (hn - hp) / (hc+hc-hn-hp);
            
            /* clamp */
            di = (di < 0) ? 
                (di + NBINS_V1) : 
                ((di >= NBINS_V1) ? (di - NBINS_V1) : (di));
            
            double th = ((M_PI2 * di) / NBINS_V1) - M_PI;
            ang[nangles++] = th;
            if(nangles >= 2) break;
        }
    }

    if( nangles < 1 ) return;

    // ext->xpos             = x;
    // ext->ypos             = y;
    // ext->sigma            = sig;
    ext->angle_from_bemap = ang[0];

    for( int bin=1; bin<nangles; bin++ ) {
        int idx = atomicAdd( &mgmt->counter, 1 );
        if( idx < mgmt->max2 ) {
            ext = &extremum[idx];
            ext->xpos             = x;
            ext->ypos             = y;
            ext->sigma            = sig;
            ext->angle_from_bemap = ang[bin];
        }
    }
}

/*************************************************************


    ExtremaMgmt* mgmt = &mgmt_array[mgmt_level];

    // if( threadIdx.y >= mgmt->counter ) return;

    ExtremumCandidate* ext = &extremum[blockIdx.x];

    float hist[NBINS_V1];
    for (int i = 0; i < NBINS_V1; i++) hist[i] = 0.0f;
