title: Mat matrix in OpenCV and 16-byte alignment for SSE
body: <p>I like to test the enhancement of <code>SSE/SSE2</code> for processing <code>OpenCV's Mat</code>. Since <code>SSE's</code> performance enhancement is obvious only for 16-byte alignment data, (1)what do I need to modify the Mat matrix to use with <code>SSE</code> registers? What I did was as follow and (2)is that a right way to do it? </p>
  
  <pre><code> void test(Mat flowxy, Mat flowresult)
      {
           __m128 x, y, xsquare, ysquare, ybyx, xRecip , sum, r, theta ;//gen is for general purpose
          float *input = (float*)(flowxy.data);
          for(int i = 0; i  &lt; flowxy.rows; i++)
              {
                  for(int j = 0; j + SSE_INCREMENT &lt; flowxy.cols; j = j + SSE_INCREMENT)
                  {
  
                      x = _mm_set_ps(input[flowxy.step * (j+6) + i ], input[flowxy.step * (j+4) + i ], input[flowxy.step * (j+2) + i ], input[flowxy.step * (j) + i ]);
                      y = _mm_set_ps(input[flowxy.step * (j+7) + i ], input[flowxy.step * (j+5) + i ], input[flowxy.step * (j+3) + i ], input[flowxy.step * (j+1) + i ]);
                      xRecip  = _mm_rcp_ps(x);
                      xsquare = _mm_mul_ps(x, x);
                      ysquare = _mm_mul_ps(y, y);             
                      ybyx = _mm_mul_ps(xRecip , y);
                      sum = _mm_add_ps(xsquare, ysquare);
                      r = _mm_sqrt_ps(sum);
                      theta = taninverse(ybyx);
                  }
  
  
              }
  
      }
  </code></pre>
  
  <p>I reverse the order in setting <code>_mm_set_ps</code> according to the discussion <a href="http://supercomputingblog.com/optimization/getting-started-with-sse-programming/" rel="nofollow">here</a>.</p>
  
  <p>EDIT 1:</p>
  
  <pre><code>void CObjectDetection_TrackingDlg::flow_XY_RTHETA(Mat flowxy, vector&lt;Mat&gt; &amp;flowrtheta)
  {
      clock_t start;   
      clock_t finish;  
      start = clock();
      flowrtheta.resize(2);
      if(flowrtheta[0].empty() &amp;&amp; flowrtheta[1].empty()){
          flowrtheta[0].create(cvSize(flowxy.rows, flowxy.cols), CV_32FC1);
          flowrtheta[1].create(cvSize(flowxy.rows, flowxy.cols), CV_32FC1);
      }
      vector&lt;Mat&gt; flowxy_S;
      split(flowxy, flowxy_S);
      printMatGrayDatainfloat(flowxy_S[0]);
      printMatGrayDatainfloat(flowxy_S[1]);
      //check SSE2 available
      bool useSIMD = checkHardwareSupport(CV_CPU_SSE);
      if( useSIMD )
      {
          __m128 x, y, xsquare, ysquare, ybyx, xRecip , sum, r, theta ;//gen is for general purpose       
          __declspec(align(16)) struct { int i, j; } sub;
          for(sub.i = 0; sub.i  &lt; flowxy.rows; sub.i++)
          {
              const float *input_x = flowxy_S[0].ptr&lt;float&gt;(sub.i);
              const float *input_y = flowxy_S[1].ptr&lt;float&gt;(sub.i);
              float *output_r = flowrtheta[0].ptr&lt;float&gt;(sub.i);
              float *output_t = flowrtheta[1].ptr&lt;float&gt;(sub.i);
              for(sub.j = 0; sub.j + 4 &lt; flowxy.cols; sub.j = sub.j + 4)
              {
  
                  x = _mm_loadu_ps(&amp;input_x[sub.j]);
                  y = _mm_loadu_ps(&amp;input_y[sub.j]);
                  xRecip  = _mm_rcp_ps(x);
                  xsquare = _mm_mul_ps(x, x);
                  ysquare = _mm_mul_ps(y, y);             
                  ybyx = _mm_mul_ps(xRecip , y);
                  sum = _mm_add_ps(xsquare, ysquare);
                  r = _mm_sqrt_ps(sum);
                  theta = taninverse(ybyx);
                  _mm_storeu_ps(&amp;output_r[sub.j], r);
                  _mm_storeu_ps(&amp;output_t[sub.j], theta);
  
              }
  
  
          }
  
      }
      else
      {
          for(int i = 0; i  &lt; flowxy.rows; i++)
          {
              const float *input_x = flowxy_S[0].ptr&lt;float&gt;(i);
              const float *input_y = flowxy_S[1].ptr&lt;float&gt;(i);
              float *output_r = flowrtheta[0].ptr&lt;float&gt;(i);
              float *output_t = flowrtheta[1].ptr&lt;float&gt;(i);
              for(int j = 0; j  &lt; flowxy.cols; j++)
              {
                  double x_sq = input_x[j] * input_x[j];
                  double y_sq = input_y[j] * input_y[j];
                  double y_by_x =  input_y[j] / input_x[j];
                  output_r[j] = sqrt(x_sq + y_sq);
                  output_t[j] = atan(y_by_x);
              }
  
  
          }
  
  
      }
      flowxy_S[0].release();
      flowxy_S[1].release();
      finish = clock() - start;
      double interval = finish / (double)CLOCKS_PER_SEC;
      //printMatGrayDatainfloat(flowrtheta[0]);
      //printMatGrayDatainfloat(flowrtheta[1]);
      return;
  }
  </code></pre>