                     sumx = s_X[threadIdx.x];
                     sumy = s_Y[threadIdx.x];
                 }
+                d = abs(__float2int_rn(s_angle[threadIdx.x + 32]) - dir);
+                if (d < ORI_WIN / 2 || d > 360 - ORI_WIN / 2)
+                {
+                    sumx += s_X[threadIdx.x + 32];
+                    sumy += s_Y[threadIdx.x + 32];
+                }
                 d = abs(__float2int_rn(s_angle[threadIdx.x + 64]) - dir);
                 if (d < ORI_WIN / 2 || d > 360 - ORI_WIN / 2)
                 {
                     sumx += s_X[threadIdx.x + 64];
                     sumy += s_Y[threadIdx.x + 64];
                 }
-
-                float* s_sumx_row = s_sumx + threadIdx.y * 64;
-                float* s_sumy_row = s_sumy + threadIdx.y * 64;
-
-                s_sumx_row[threadIdx.x] = sumx;
-                s_sumy_row[threadIdx.x] = sumy;
-                __syncthreads();
-
-                if (threadIdx.x < 32)
+                d = abs(__float2int_rn(s_angle[threadIdx.x + 96]) - dir);
+                if (d < ORI_WIN / 2 || d > 360 - ORI_WIN / 2)
                 {
-                    volatile float* v_sumx_row = s_sumx_row;
-                    volatile float* v_sumy_row = s_sumy_row;
-
-                    v_sumx_row[threadIdx.x] = sumx += v_sumx_row[threadIdx.x + 32];
-                    v_sumy_row[threadIdx.x] = sumy += v_sumy_row[threadIdx.x + 32];
-
-                    v_sumx_row[threadIdx.x] = sumx += v_sumx_row[threadIdx.x + 16];
-                    v_sumy_row[threadIdx.x] = sumy += v_sumy_row[threadIdx.x + 16];
-
-                    v_sumx_row[threadIdx.x] = sumx += v_sumx_row[threadIdx.x + 8];
-                    v_sumy_row[threadIdx.x] = sumy += v_sumy_row[threadIdx.x + 8];
-
-                    v_sumx_row[threadIdx.x] = sumx += v_sumx_row[threadIdx.x + 4];
-                    v_sumy_row[threadIdx.x] = sumy += v_sumy_row[threadIdx.x + 4];
-
-                    v_sumx_row[threadIdx.x] = sumx += v_sumx_row[threadIdx.x + 2];
-                    v_sumy_row[threadIdx.x] = sumy += v_sumy_row[threadIdx.x + 2];
-
-                    v_sumx_row[threadIdx.x] = sumx += v_sumx_row[threadIdx.x + 1];
-                    v_sumy_row[threadIdx.x] = sumy += v_sumy_row[threadIdx.x + 1];
+                    sumx += s_X[threadIdx.x + 96];
+                    sumy += s_Y[threadIdx.x + 96];
                 }
+
+                float* s_sum_row = s_sum + threadIdx.y * 32;
+
+                reduceSum32(s_sum_row, sumx);
+                reduceSum32(s_sum_row, sumy);
 
                 const float temp_mod = sumx * sumx + sumy * sumy;
                 if (temp_mod > best_mod)

        __shared__ float s_Y[128];
        __shared__ float s_angle[128];

        __shared__ float s_sumx[64 * 4];
        __shared__ float s_sumy[64 * 4];

        /* The sampling intervals and wavelet sized for selecting an orientation
         and building the keypoint descriptor are defined relative to 's' */

    }  

    __device__ void calc_dx_dy(float s_dx_bin[25], float s_dy_bin[25], 
        const float* featureX, const float* featureY, const float* featureSize, const float* featureDir)
    {
        __shared__ float s_PATCH[6][6];

