/*
   * compute cornerness
   */
  bool harrisCorners::getCornerness(const channel& fxx,
                                    const channel& fxy,
                                    const channel& fyy,
                                    const float scale,
                                    channel& cornerness,
                                    float& maxCornerness) const {
    // we can assume that all channels are connected, but try it out if not
    if ((fxx.getMode() != channel::Connected) ||
        (fxy.getMode() != channel::Connected) ||
        (fyy.getMode() != channel::Connected)) {
      setStatusString("Channels not contigous in getCornerness");
      return false;
    }
    
    if (fxx.empty() || fxy.empty() || fyy.empty()) {
      cornerness.clear();
      maxCornerness = 0.0f;
      return false;
    }
    
    int i;
    const int end = fxx.rows()*fxx.columns();
    const float *const pfxx = &fxx.at(0);
    const float *const pfxy = &fxy.at(0);
    const float *const pfyy = &fyy.at(0);

    cornerness.resize(fxx.size(),0,false,false);
    float* pcor = &cornerness.at(0);

    float det,trace,txx,txy,tyy,c;
    float maxc = 0.0f;

    for (i=0;i<end;++i) {
      txx=pfxx[i];
      txy=pfxy[i];
      tyy=pfyy[i];
      det=txx*tyy - txy*txy;
      trace=txx+tyy;
      c = det-scale*trace*trace;
      pcor[i]=c;
      if (c>maxc) {
        maxc=c;
      }
    }

    maxCornerness = maxc;
    return true;
  }
  bool hessianFunctor::classicXY(const channel& src, channel& xy) const {

    if (src.columns() < 3) {
      setStatusString("width less than 3");
      xy.clear();
      return false;
    }
    if (src.rows() < 3) {
      setStatusString("height less than 3");
      xy.clear();
      return false;
    }

    if (src.getMode()!=channel::Connected) {
      setStatusString("src must be Connected");
      xy.clear();
      return false;
    }

    const int width  = src.columns();
    const int height = src.rows();

    xy.resize(height,width,0.f,false,false);
    
    float* fpxy = &xy.at(0,0);

    const float* fpSrc = &src.at(0,0);
    const float* rowy;
    const float* colx;

    float* pidxy;

    const int w1 = width-1;
    const int w2 = width-2;
    const int last = (height-1)*width; // index of begin of last row
    const int lastRow = -w1;           // offset from actual column pointer to
                                       // last row
    const int nextRow = width+1;       // offset from actual column pointer to
                                       // next row
    const int nextRow2 = width+2;      // offset from actual column pointer to
                                       // next row + 1

    // top-left corner
    fpxy[0]=(fpSrc[0]-fpSrc[1]-fpSrc[width]+fpSrc[nextRow]);

    // top
    pidxy = &fpxy[1];

    for (colx=&fpSrc[0],rowy=&fpSrc[w1];
         colx<rowy;
         ++colx,++pidxy) {
      *pidxy=(*colx - colx[2] - colx[width] + colx[nextRow2]);
    }

    // top-right corner
    fpxy[w1]=(fpSrc[w2]-fpSrc[w1]-fpSrc[w2+width]+fpSrc[w1+width]);

    // main loop (begin at coordinates (1,0)
    pidxy = &fpxy[width];

    const float *const rowEnd = &fpSrc[last];

    for (rowy=&fpSrc[width];
         rowy<rowEnd;
         rowy+=width) {

      // left side
      *pidxy=(rowy[-width] - rowy[lastRow] - rowy[width] + rowy[nextRow]);

      ++pidxy;

      // middle
      const float *const colEnd = &rowy[w2];
      for (colx=rowy;
           colx<colEnd;
           ++colx,++pidxy) {
        *pidxy=(colx[-width] - colx[-w2] - colx[width] + colx[nextRow2]);
      }

      // right side
      *pidxy=(colx[-width] - colx[lastRow] - colx[width] + colx[nextRow]);

      ++pidxy;
    }

    // bottom-left corner
    fpxy[last]=(fpSrc[last+1]-fpSrc[last]);

    // bottom
    pidxy = &fpxy[last+1];

    const float *const colEnd = &rowEnd[w2];
    for (colx=rowEnd;
         colx<colEnd;
         ++colx,++pidxy) {
      *pidxy=(colx[-width] - colx[-w2] - *colx + colx[2]);
    }

    // bottom-right corner
    fpxy[last+w1]=(fpSrc[last-2]-fpSrc[last-1]-fpSrc[last+w2]+fpSrc[last+w1]);

    return true;
  };