changeset 72:c3c50d5e05b7 refactors

Pull up Matcher set/get to public API, use only public API in Finder
author Chris Cannam
date Wed, 19 Nov 2014 10:18:19 +0000
parents cba231851957
children 7e3c1bc0984a
files src/Finder.cpp src/Finder.h src/MatchFeatureFeeder.cpp src/MatchFeeder.cpp src/Matcher.cpp src/Matcher.h
diffstat 6 files changed, 299 insertions(+), 326 deletions(-) [+]
line wrap: on
line diff
--- a/src/Finder.cpp	Wed Nov 19 09:17:58 2014 +0000
+++ b/src/Finder.cpp	Wed Nov 19 10:18:19 2014 +0000
@@ -20,61 +20,26 @@
 
 #include <algorithm>
 
+using namespace std;
 
-Finder::Finder(Matcher *p1, Matcher *p2)
+Finder::Finder(Matcher *pm)
 {
-    if (!p1->m_firstPM)
-        std::cerr << "Warning: wrong args in Finder()" << std::endl;
-    pm1 = p1;
-    pm2 = p2;
-    index1 = 0;
-    index2 = 0;
-    rowRange = new int[2];
-    colRange = new int[2];
-    duration1 = -1;
-    duration2 = -1;
+    m_m = pm;
+    m_duration1 = -1;
+    m_duration2 = -1;
 } // constructor
 
 Finder::~Finder()
 {
-    delete[] rowRange;
-    delete[] colRange;
 }
 
 void
 Finder::setDurations(int d1, int d2)
 {
-    duration1 = d1;
-    duration2 = d2;
+    m_duration1 = d1;
+    m_duration2 = d2;
 }
 
-bool
-Finder::find(int i1, int i2)
-{
-    if ((i1 >= 0) && (i1 < (int)pm1->m_first.size()) &&
-        (i2 >= pm1->m_first[i1]) && (i2 < pm1->m_last[i1])) {
-        index1 = i1;
-        index2 = i2 - pm1->m_first[i1];
-        return true;
-    } else {
-        return false;
-    }
-} // find()
-
-void
-Finder::getColRange(int row, int *range)
-{
-    range[0] = pm1->m_first[row];
-    range[1] = pm1->m_last[row];
-} // getColRange()
-
-void
-Finder::getRowRange(int col, int *range)
-{
-    range[0] = pm2->m_first[col];
-    range[1] = pm2->m_last[col];
-} // getRowRange()
-
 Matcher::Advance
 Finder::getExpandDirection(int row, int col)
 {
@@ -84,32 +49,39 @@
 Matcher::Advance
 Finder::getExpandDirection(int row, int col, bool check)
 {
-    double min = getPathCost(row, col);
-    bestRow = row;
-    bestCol = col;
-    getRowRange(col, rowRange);
-    if (rowRange[1] > row+1)
-        rowRange[1] = row+1;	// don't cheat by looking at future :)
-    for (int index = rowRange[0]; index < rowRange[1]; index++) {
-        double tmp = getPathCost(index, col);
+    double min = m_m->getPathCost(row, col);
+    
+    int bestRow = row;
+    int bestCol = col;
+
+    pair<int, int> rowRange = m_m->getRowRange(col);
+    if (rowRange.second > row+1) {
+        rowRange.second = row+1;	// don't cheat by looking at future :)
+    }
+    for (int index = rowRange.first; index < rowRange.second; index++) {
+        double tmp = m_m->getPathCost(index, col);
         if (tmp < min) {
             min = tmp;
             bestRow = index;
         }
     }
-    getColRange(row, colRange);
-    if (colRange[1] > col+1)
-        colRange[1] = col+1;	// don't cheat by looking at future :)
-    for (int index = colRange[0]; index < colRange[1]; index++) {
-        double tmp = getPathCost(row, index);
+
+    pair<int, int> colRange = m_m->getColRange(row);
+    if (colRange.second > col+1) {
+        colRange.second = col+1;	// don't cheat by looking at future :)
+    }
+    for (int index = colRange.first; index < colRange.second; index++) {
+        double tmp = m_m->getPathCost(row, index);
         if (tmp < min) {
             min = tmp;
             bestCol = index;
             bestRow = row;
         }
     }
+
     //	System.err.print("  BEST: " + bestRow + " " + bestCol + " " + check);
     //	System.err.println(" " + pm1->frameCount + " " + pm2->frameCount);
+    /*
     if (check) {
         //		System.err.println(find(row+1, col) + " " + find(row, col+1));
         if (!find(row, col+1)) {
@@ -118,6 +90,7 @@
             return Matcher::AdvanceOther;
         }
     }
+    */
 
     if (bestRow == row) {
         if (bestCol == col) {
@@ -132,151 +105,61 @@
     }
 
 } // getExpandDirection()
-	
-float
-Finder::getDistance(int row, int col) 
-{
-    if (find(row, col)) {
-        return pm1->m_distance[row][col - pm1->m_first[row]];
-    }
-    std::cerr << "getDistance(" << row << "," << col << "): out of bounds" << std::endl;
-    throw "getDistance index out of bounds";
-} // getDistance()/2
-
-void
-Finder::setDistance(int row, int col, float b)
-{
-    if (find(row, col)) {
-        pm1->m_distance[row][col - pm1->m_first[row]] = b;
-        return;
-    }
-    std::cerr << "setDistance(" << row << "," << col << "," << b << "): out of bounds" << std::endl;
-    throw "setDistance index out of bounds";
-} // setDistance()
-
-double
-Finder::getPathCost(int row, int col)
-{
-    if (find(row, col)) // "1" avoids div by 0 below
-        return pm1->m_bestPathCost[row][col - pm1->m_first[row]] / float(1+row+col);
-    std::cerr << "getPathCost(" << row << "," << col << "): out of bounds" << std::endl;
-    throw "getPathCost index out of bounds";
-} // getPathCost()
-	
-double
-Finder::getRawPathCost(int row, int col)
-{
-    if (find(row, col))
-        return pm1->m_bestPathCost[row][col - pm1->m_first[row]];
-    std::cerr << "getRawPathCost(" << row << "," << col << "): out of bounds" << std::endl;
-    throw "getRawPathCost index out of bounds";
-} // getRawPathCost()
-
-void
-Finder::setPathCost(int row, int col, double cost)
-{
-    if (find(row, col)) {
-         pm1->m_bestPathCost[row][col - pm1->m_first[row]] = cost;
-         return;
-    }
-    std::cerr << "setPathCost(" << row << "," << col << "," << cost << "): out of bounds" << std::endl;
-    throw "setPathCost index out of bounds";
-} // setPathCost()
-
-Matcher::Advance
-Finder::getAdvance()
-{
-    return pm1->m_advance[index1][index2];
-}
-
-void
-Finder::setAdvance(Matcher::Advance a)
-{
-    pm1->m_advance[index1][index2] = a;
-}
-
-float
-Finder::getDistance() 
-{
-    return pm1->m_distance[index1][index2];
-} // getDistance()/0
-
-void
-Finder::setDistance(float b)
-{
-    pm1->m_distance[index1][index2] = b;
-} // setDistance()
-
-double
-Finder::getPathCost()
-{
-    return pm1->m_bestPathCost[index1][index2];
-} // getPathCost()
-
-void
-Finder::setPathCost(double cost)
-{
-    pm1->m_bestPathCost[index1][index2] = cost;
-} // setPathCost()
 
 void
 Finder::recalculatePathCostMatrix(int r1, int c1, int r2, int c2) 
 {
-    if (!find(r1,c1)) {
-        std::cerr << "recalculatePathCostMatrix(" << r1 << "," << c1 << "): out of bounds" << std::endl;
-        throw "recalculatePathCostMatrix index out of bounds";
+    int prevRowStart = 0, prevRowStop = 0;
+
+    for (int r = r1; r <= r2; r++) {
+
+        pair<int, int> colRange = m_m->getColRange(r);
+
+        int rowStart = max(c1, colRange.first);
+        int rowStop = min(c2 + 1, colRange.second);
+        
+        for (int c = rowStart; c < rowStop; c++) {
+
+            float newCost = m_m->getDistance(r, c);
+            Matcher::Advance dir = Matcher::AdvanceNone;
+
+            if (r > r1) {	// not first row
+                double min = -1;
+                if ((c > prevRowStart) && (c <= prevRowStop)) {
+                    // diagonal from (r-1,c-1)
+                    min = m_m->getPathCost(r-1, c-1) + newCost * 2;
+                    dir = Matcher::AdvanceBoth;
+                }
+                if ((c >= prevRowStart) && (c < prevRowStop)) {
+                    // vertical from (r-1,c)
+                    double cost = m_m->getPathCost(r-1, c) + newCost;
+                    if ((min < 0) || (cost < min)) {
+                        min = cost;
+                        dir = Matcher::AdvanceThis;
+                    }
+                }
+                if (c > rowStart) {
+                    // horizontal from (r,c-1)
+                    double cost = m_m->getPathCost(r, c-1) + newCost;
+                    if ((min < 0) || (cost < min)) {
+                        min = cost;
+                        dir = Matcher::AdvanceOther;
+                    }
+                }
+                
+                m_m->setPathCost(r, c, dir, min);
+
+            } else if (c > rowStart) {	// first row
+                // horizontal from (r,c-1)
+                m_m->setPathCost(r, c, Matcher::AdvanceOther,
+                                   m_m->getPathCost(r, c-1) + newCost);
+            }
+        }
+
+        prevRowStart = rowStart;
+        prevRowStop = rowStop;
     }
-    int thisRowStart, c;
-    int prevRowStart = 0, prevRowStop = 0;
-    for (int r = r1; r <= r2; r++) {
-        thisRowStart = pm1->m_first[r];
-        if (thisRowStart < c1)
-            thisRowStart = c1;
-        for (c = thisRowStart; c <= c2; c++) {
-            if (find(r,c)) {
-                int i2 = index2;
-                float newCost = pm1->m_distance[r][i2];
-                Matcher::Advance dir = Matcher::AdvanceNone;
-                if (r > r1) {	// not first row
-                    double min = -1;
-                    if ((c > prevRowStart) && (c <= prevRowStop)) {
-                        // diagonal from (r-1,c-1)
-                        min = pm1->m_bestPathCost[r-1][c-pm1->m_first[r-1]-1] +
-                            newCost * 2;
-                        dir = Matcher::AdvanceBoth;
-                    }
-                    if ((c >= prevRowStart) && (c < prevRowStop)) {
-                        // vertical from (r-1,c)
-                        double cost = pm1->m_bestPathCost[r-1][c-pm1->m_first[r-1]] +
-                            newCost;
-                        if ((min < 0) || (cost < min)) {
-                            min = cost;
-                            dir = Matcher::AdvanceThis;
-                        }
-                    }
-                    if (c > thisRowStart) {
-                        // horizontal from (r,c-1)
-                        double cost = pm1->m_bestPathCost[r][i2-1]+newCost;
-                        if ((min < 0) || (cost < min)) {
-                            min = cost;
-                            dir = Matcher::AdvanceOther;
-                        }
-                    }
-                    pm1->m_bestPathCost[r][i2] = min;
-                } else if (c > thisRowStart) {	// first row
-                    // horizontal from (r,c-1)
-                    pm1->m_bestPathCost[r][i2] = pm1->m_bestPathCost[r][i2-1] +
-                        newCost;
-                    dir = Matcher::AdvanceOther;
-                }
-                pm1->m_advance[r][i2] = dir;
-            } else
-                break;	// end of row
-        }
-        prevRowStart = thisRowStart;
-        prevRowStop = c;
-    }
-} // recalculatePathCostMatrix()
+} 
 
 int
 Finder::retrievePath(bool smooth, vector<int> &pathx, vector<int> &pathy)
@@ -284,8 +167,8 @@
     pathx.clear();
     pathy.clear();
 
-    int ex = pm2->getFrameCount() - 1;
-    int ey = pm1->getFrameCount() - 1;
+    int ex = m_m->getOtherFrameCount() - 1;
+    int ey = m_m->getFrameCount() - 1;
 
     if (ex < 0 || ey < 0) {
         return 0;
@@ -296,14 +179,14 @@
     
 //    cerr << "before: x = " << x << ", y = " << y << endl;
 
-    if (duration2 > 0 && duration2 < pm2->getFrameCount()) {
-        x = duration2 - 1;
+    if (m_duration2 > 0 && m_duration2 < m_m->getOtherFrameCount()) {
+        x = m_duration2 - 1;
     }
-    if (duration1 > 0 && duration1 < pm1->getFrameCount()) {
-        y = duration1 - 1;
+    if (m_duration1 > 0 && m_duration1 < m_m->getFrameCount()) {
+        y = m_duration1 - 1;
     }
 
-    if (!find(y, x)) {
+    if (!m_m->isAvailable(y, x)) {
         // Path did not pass through the expected end point --
         // probably means the pieces are substantially different in
         // the later bits. Reset the expected end point to the end of
@@ -317,14 +200,14 @@
 
 //    cerr << "start: x = " << x << ", y = " << y << endl;
     
-    while (find(y, x) && ((x > 0) || (y > 0))) {
+    while (m_m->isAvailable(y, x) && (x > 0 || y > 0)) {
 
 //        cerr << "x = " << x << ", y = " << y;
         
         pathx.push_back(x);
         pathy.push_back(y);
 
-        switch (getAdvance()) {
+        switch (m_m->getAdvance(y, x)) {
         case Matcher::AdvanceThis:
 //            cerr << ", going down (dist = " << getDistance() << ")" << endl;
             y--;
@@ -349,8 +232,13 @@
         }
     }
 
-    std::reverse(pathx.begin(), pathx.end());
-    std::reverse(pathy.begin(), pathy.end());
+    if (x > 0 || y > 0) {
+        cerr << "WARNING: Ran out of available path at (" << y << "," << x
+             << ")!" << endl;
+    }
+    
+    reverse(pathx.begin(), pathx.end());
+    reverse(pathy.begin(), pathy.end());
 
     if (smooth) {
         int smoothedLen = Path().smooth(pathx, pathy, pathx.size());
--- a/src/Finder.h	Wed Nov 19 09:17:58 2014 +0000
+++ b/src/Finder.h	Wed Nov 19 10:18:19 2014 +0000
@@ -22,22 +22,10 @@
 
 #include "Matcher.h"
 
-/** Maps cost matrix coordinates into an efficient
- *  (linear instead of quadratic space) representation.
- *  Stores result of most recent mapping for fast
- *  sequential access.
- */
-class Finder {
-
-protected:
-    Matcher *pm1, *pm2;
-    int index1, index2, bestRow, bestCol;
-    int *rowRange;
-    int *colRange;
-    int duration1, duration2;
-
+class Finder
+{
 public:
-    Finder(Matcher *p1, Matcher *p2);
+    Finder(Matcher *pm);
 
     ~Finder();
 
@@ -50,42 +38,9 @@
      */
     void setDurations(int d1, int d2);
     
-    /** Sets up the instance variables to point to the given
-     *  coordinate in the distance matrix.
-     *
-     *  @param i1 frameNumber in the first Matcher
-     *  @param i2 frameNumber in the second Matcher
-     *  @return true iff the point (i2,i1) is represented in the distance matrix
-     */
-    bool find(int i1, int i2);
-
-    /** Returns the range [lo,hi) of legal column indices for the
-     *  given row. */
-    void getColRange(int row, int *range);
-
-    /** Returns the range [lo,hi) of legal row indices for the given
-     *  column. */
-    void getRowRange(int col, int *range);
-
     Matcher::Advance getExpandDirection(int row, int col);
     Matcher::Advance getExpandDirection(int row, int col, bool check);
-	
-    float getDistance(int row, int col);
-    void setDistance(int row, int col, float b);
-
-    double getPathCost(int row, int col);
-    double getRawPathCost(int row, int col); //!!!???
-    void setPathCost(int row, int col, double i);
-
-    Matcher::Advance getAdvance();
-    void setAdvance(Matcher::Advance a);
     
-    float getDistance();
-    void setDistance(float b);
-
-    double getPathCost();
-    void setPathCost(double i);
-
     /** Calculates a rectangle of the path cost matrix so that the
      *  minimum cost path between the bottom left and top right
      *  corners can be computed.  Caches previous values to avoid
@@ -110,7 +65,11 @@
      * @param smooth whether to smooth the path before returning it
      */
     int retrievePath(bool smooth, std::vector<int> &pathx, std::vector<int> &pathy);
-    
+
+protected:
+    Matcher *m_m;
+    int m_duration1;
+    int m_duration2;
 }; // class Finder
 
 #endif
--- a/src/MatchFeatureFeeder.cpp	Wed Nov 19 09:17:58 2014 +0000
+++ b/src/MatchFeatureFeeder.cpp	Wed Nov 19 10:18:19 2014 +0000
@@ -21,7 +21,7 @@
 MatchFeatureFeeder::MatchFeatureFeeder(Matcher *m1, Matcher *m2) :
     pm1(m1), pm2(m2)
 {
-    finder = new Finder(m1, m2);
+    finder = new Finder(m1);
 }
 
 MatchFeatureFeeder::~MatchFeatureFeeder()
--- a/src/MatchFeeder.cpp	Wed Nov 19 09:17:58 2014 +0000
+++ b/src/MatchFeeder.cpp	Wed Nov 19 10:18:19 2014 +0000
@@ -22,7 +22,7 @@
     pm1(m1), pm2(m2), n(0), lastIn1(0), lastIn2(0)
 {
     fftSize = m1->m_params.fftSize;
-    finder = new Finder(m1, m2);
+    finder = new Finder(m1);
     reBuffer = new double[fftSize/2+1];
     imBuffer = new double[fftSize/2+1];
 }
@@ -138,29 +138,35 @@
     vector<double> f1, f2;
 
     if (q1.empty()) {
+        cerr << "feedBlock: q1 empty, feeding 2" << endl;
         f2 = feed2();
     } else if (q2.empty()) {
+        cerr << "feedBlock: q2 empty, feeding 1" << endl;
         f1 = feed1();
     } else if (pm1->m_frameCount < pm1->m_blockSize) {		// fill initial block
-//        std::cerr << "feeding initial block" << std::endl;
+        std::cerr << "feeding initial block" << std::endl;
         f1 = feed1();
         f2 = feed2();
     } else if (pm1->m_runCount >= pm1->m_params.maxRunCount) {  // slope constraints
-//        std::cerr << "pm1 too slopey" << std::endl;
+        std::cerr << "pm1 too slopey" << std::endl;
         f2 = feed2();
     } else if (pm2->m_runCount >= pm2->m_params.maxRunCount) {
-//        std::cerr << "pm2 too slopey" << std::endl;
+        std::cerr << "pm2 too slopey" << std::endl;
         f1 = feed1();
     } else {
+//        cerr << "run counts: " << pm1->m_runCount << ", " << pm2->m_runCount << endl;
         switch (finder->getExpandDirection
                 (pm1->m_frameCount-1, pm2->m_frameCount-1)) {
         case Matcher::AdvanceThis:
+//            cerr << "feeding 1" << endl;
             f1 = feed1();
             break;
         case Matcher::AdvanceOther:
+//            cerr << "feeding 2" << endl;
             f2 = feed2();
             break;
         case Matcher::AdvanceBoth:
+//            cerr << "feeding 1 and 2" << endl;
             f1 = feed1();
             f2 = feed2();
             break;
--- a/src/Matcher.cpp	Wed Nov 19 09:17:58 2014 +0000
+++ b/src/Matcher.cpp	Wed Nov 19 10:18:19 2014 +0000
@@ -21,6 +21,8 @@
 #include <cstdlib>
 #include <cassert>
 
+using namespace std;
+
 //#define DEBUG_MATCHER 1
 
 Matcher::Matcher(Parameters parameters,
@@ -125,7 +127,7 @@
 }
 
 void
-Matcher::consumeFeatureVector(std::vector<double> feature)
+Matcher::consumeFeatureVector(vector<double> feature)
 {
     if (!m_initialised) init();
     int frameIndex = m_frameCount % m_blockSize; 
@@ -204,30 +206,30 @@
             updateValue(0, 0, AdvanceNone, 0, dMN);
         else if (m_frameCount == 0)                 // first row
             updateValue(0, index, AdvanceOther,
-                        getValue(0, index-1), dMN);
+                        getPathCost(0, index-1), dMN);
         else if (index == 0)                      // first column
             updateValue(m_frameCount, index, AdvanceThis,
-                        getValue(m_frameCount - 1, 0), dMN);
+                        getPathCost(m_frameCount - 1, 0), dMN);
         else if (index == m_otherMatcher->m_frameCount - m_blockSize) {
             // missing value(s) due to cutoff
             //  - no previous value in current row (resp. column)
             //  - no diagonal value if prev. dir. == curr. dirn
-            double min2 = getValue(m_frameCount - 1, index);
+            double min2 = getPathCost(m_frameCount - 1, index);
             //	if ((m_firstPM && (first[m_frameCount - 1] == index)) ||
             //			(!m_firstPM && (m_last[index-1] < m_frameCount)))
             if (m_first[m_frameCount - 1] == index)
                 updateValue(m_frameCount, index, AdvanceThis, min2, dMN);
             else {
-                double min1 = getValue(m_frameCount - 1, index - 1);
+                double min1 = getPathCost(m_frameCount - 1, index - 1);
                 if (min1 + dMN <= min2)
                     updateValue(m_frameCount, index, AdvanceBoth, min1,dMN);
                 else
                     updateValue(m_frameCount, index, AdvanceThis, min2,dMN);
             }
         } else {
-            double min1 = getValue(m_frameCount, index-1);
-            double min2 = getValue(m_frameCount - 1, index);
-            double min3 = getValue(m_frameCount - 1, index-1);
+            double min1 = getPathCost(m_frameCount, index-1);
+            double min2 = getPathCost(m_frameCount - 1, index);
+            double min3 = getPathCost(m_frameCount - 1, index-1);
             if (min1 <= min2) {
                 if (min3 + dMN <= min1)
                     updateValue(m_frameCount, index, AdvanceBoth, min3,dMN);
@@ -276,41 +278,104 @@
     }
 }
 
+pair<int, int>
+Matcher::getColRange(int i)
+{
+    if (i < 0 || i >= int(m_first.size())) {
+        cerr << "ERROR: Matcher::getColRange(" << i << "): Index out of range"
+             << endl;
+        throw "Index out of range";
+    } else {
+        return pair<int, int>(m_first[i], m_last[i]);
+    }
+}
+
+pair<int, int>
+Matcher::getRowRange(int i)
+{
+    return m_otherMatcher->getColRange(i);
+}
+
+float
+Matcher::getDistance(int i, int j)
+{
+    if (m_firstPM) {
+        if (!isInRange(i, j)) {
+            cerr << "ERROR: Matcher::getDistance(" << i << ", " << j << "): "
+                 << "Location is not in range" << endl;
+            throw "Distance not available";
+        }
+        float dist = m_distance[i][j - m_first[i]];
+        if (dist < 0) {
+            cerr << "ERROR: Matcher::getDistance(" << i << ", " << j << "): "
+                 << "Location is in range, but distance ("
+                 << dist << ") is invalid or has not been set" << endl;
+            throw "Distance not available";
+        }
+        return dist;
+    } else {
+        return m_otherMatcher->getDistance(j, i);
+    }
+}
+                
+void
+Matcher::setDistance(int i, int j, float distance)
+{
+    if (m_firstPM) {
+        if (!isInRange(i, j)) {
+            cerr << "ERROR: Matcher::setDistance(" << i << ", " << j << ", "
+                 << distance << "): Location is out of range" << endl;
+            throw "Indices out of range";
+        }
+        m_distance[i][j - m_first[i]] = distance;
+    } else {
+        m_otherMatcher->setDistance(j, i, distance);
+    }
+}
+
 double
-Matcher::getValue(int i, int j)
+Matcher::getPathCost(int i, int j)
 {
     if (m_firstPM) {
         if (!isAvailable(i, j)) {
             if (!isInRange(i, j)) {
-                cerr << "ERROR: Matcher::getValue(" << i << ", " << j << "): "
+                cerr << "ERROR: Matcher::getPathCost(" << i << ", " << j << "): "
                      << "Location is not in range" << endl;
             } else {
-                cerr << "ERROR: Matcher::getValue(" << i << ", " << j << "): "
-                     << "Location is in range, but value ("
+                cerr << "ERROR: Matcher::getPathCost(" << i << ", " << j << "): "
+                     << "Location is in range, but pathCost ("
                      << m_bestPathCost[i][j - m_first[i]]
                      << ") is invalid or has not been set" << endl;
             }
-            throw "Value not available";
+            throw "Path cost not available";
         }
         return m_bestPathCost[i][j - m_first[i]];
     } else {
-        return m_otherMatcher->getValue(j, i);
+        return m_otherMatcher->getPathCost(j, i);
     }
 }
                 
 void
-Matcher::setValue(int i, int j, double value)
+Matcher::setPathCost(int i, int j, Advance dir, double pathCost)
 {
     if (m_firstPM) {
         if (!isInRange(i, j)) {
-            cerr << "ERROR: Matcher::setValue(" << i << ", " << j << ", "
-                 << value << "): Location is out of range" << endl;
+            cerr << "ERROR: Matcher::setPathCost(" << i << ", " << j << ", "
+                 << dir << ", " << pathCost
+                 << "): Location is out of range" << endl;
             throw "Indices out of range";
         }
-        m_bestPathCost[i][j - m_first[i]] = value;
+        m_advance[i][j - m_first[i]] = dir;
+        m_bestPathCost[i][j - m_first[i]] = pathCost;
     } else {
-        m_otherMatcher->setValue(j, i, value);
+        if (dir == AdvanceThis) {
+            dir = AdvanceOther;
+        } else if (dir == AdvanceOther) {
+            dir = AdvanceThis;
+        }
+        m_otherMatcher->setPathCost(j, i, dir, pathCost);
     }
+
 }
 
 void
@@ -318,34 +383,39 @@
 {
     if (m_firstPM) {
 
-        int jdx = j - m_first[i];
-        m_distance[i][jdx] = dMN;
-        m_advance[i][jdx] = dir;
-        setValue(i, j, value + (dir == AdvanceBoth ? dMN*2: dMN));
+        m_distance[i][j - m_first[i]] = dMN;
+        setPathCost(i, j, dir, value + (dir == AdvanceBoth ? dMN*2: dMN));
 
     } else {
 
-        if (dir == AdvanceThis) {
-            dir = AdvanceOther;
-        } else if (dir == AdvanceOther) {
-            dir = AdvanceThis;
-        }
-
         int idx = i - m_otherMatcher->m_first[j];
         
         if (idx == (int)m_otherMatcher->m_distance[j].size()) {
             // This should never happen, but if we allow arbitrary
             // pauses in either direction, and arbitrary lengths at
             // end, it is better than a segmentation fault.
-            std::cerr << "Emergency resize: " << idx << " -> " << idx * 2 << std::endl;
+            cerr << "Emergency resize: " << idx << " -> " << idx * 2 << endl;
             m_otherMatcher->m_bestPathCost[j].resize(idx * 2, -1);
             m_otherMatcher->m_distance[j].resize(idx * 2, -1);
             m_otherMatcher->m_advance[j].resize(idx * 2, AdvanceNone);
         }
 
         m_otherMatcher->m_distance[j][idx] = dMN;
-        m_otherMatcher->m_advance[j][idx] = dir;
-        m_otherMatcher->setValue(j, i, value + (dir == AdvanceBoth ? dMN*2: dMN));
+        m_otherMatcher->setPathCost(j, i, dir, value + (dir == AdvanceBoth ? dMN*2: dMN));
     }
 }
 
+Matcher::Advance
+Matcher::getAdvance(int i, int j)
+{
+    if (m_firstPM) {
+        if (!isInRange(i, j)) {
+            cerr << "ERROR: Matcher::getAdvance(" << i << ", " << j << "): "
+                 << "Location is not in range" << endl;
+            throw "Advance not available";
+        }
+        return m_advance[i][j - m_first[i]];
+    } else {
+        return m_otherMatcher->getAdvance(j, i);
+    }
+}
--- a/src/Matcher.h	Wed Nov 19 09:17:58 2014 +0000
+++ b/src/Matcher.h	Wed Nov 19 10:18:19 2014 +0000
@@ -127,6 +127,89 @@
         return m_frameCount;
     }
 
+    int getOtherFrameCount() {
+        return m_otherMatcher->getFrameCount();
+    }
+    
+    /** Tests whether a location is in range in the minimum cost matrix.
+     *
+     *  @param i the frame number of this Matcher
+     *  @param j the frame number of the other Matcher
+     *  @return true if the location is in range
+     */
+    bool isInRange(int i, int j);
+    
+    /** Tests whether a location is available in the minimum cost matrix.
+     *
+     *  @param i the frame number of this Matcher
+     *  @param j the frame number of the other Matcher
+     *  @return true if the location is in range and contains a valid cost
+     */
+    bool isAvailable(int i, int j);
+
+    /** Returns the valid range of frames in the other Matcher for the
+     *  given frame in this Matcher's minimum cost matrix.
+     *
+     *  @param i the frame number of this Matcher
+     *  @return the first, last pair of frame numbers for the other
+     *  Matcher. Note that the last frame is exclusive (last valid
+     *  frame + 1).
+     */
+    std::pair<int, int> getColRange(int i);
+
+    /** Returns the valid range of frames in this Matcher for the
+     *  given frame in the other Matcher's minimum cost matrix.
+     *
+     *  @param i the frame number of the other Matcher
+     *  @return the first, last pair of frame numbers for this
+     *  Matcher. Note that the last frame is exclusive (last valid
+     *  frame + 1).
+     */
+    std::pair<int, int> getRowRange(int i);
+    
+    /** Retrieves a value from the distance matrix.
+     *
+     *  @param i the frame number of this Matcher
+     *  @param j the frame number of the other Matcher
+     *  @return the distance metric at this location
+     */
+    float getDistance(int i, int j);
+
+    /** Sets a value to the distance matrix.
+     *
+     *  @param i the frame number of this Matcher
+     *  @param j the frame number of the other Matcher
+     *  @param value the distance metric to set for this location
+     */
+    void setDistance(int i, int j, float value);
+    
+    /** Retrieves a value from the minimum cost matrix.
+     *
+     *  @param i the frame number of this Matcher
+     *  @param j the frame number of the other Matcher
+     *  @return the cost of the minimum cost path to this location
+     */
+    double getPathCost(int i, int j);
+
+    /** Sets a value and an advance direction to the minimum cost matrix.
+     *
+     *  @param i the frame number of this Matcher
+     *  @param j the frame number of the other Matcher
+     *  @param dir the direction from which this position is reached with
+     *  minimum cost
+     *  @param value the cost of the minimum cost path to set for this location
+     */
+    void setPathCost(int i, int j, Advance dir, double value);
+
+    /** Retrieves an advance direction from the matrix.
+     * 
+     *  @param i the frame number of this Matcher
+     *  @param j the frame number of the other Matcher
+     *  @return the direction from which this position is reached with
+     *  minimum cost
+     */
+    Advance getAdvance(int i, int j);
+    
 protected:
     /** Create internal structures and reset. */
     void init();
@@ -162,38 +245,6 @@
      */
     void consumeFeatureVector(std::vector<double> feature);
 
-    /** Tests whether a location is in range in the minimum cost matrix.
-     *
-     *  @param i the frame number of this Matcher
-     *  @param j the frame number of the other Matcher
-     *  @return true if the location is in range
-     */
-    bool isInRange(int i, int j);
-    
-    /** Tests whether a location is available in the minimum cost matrix.
-     *
-     *  @param i the frame number of this Matcher
-     *  @param j the frame number of the other Matcher
-     *  @return true if the location is in range and contains a valid cost
-     */
-    bool isAvailable(int i, int j);
-    
-    /** Retrieves a value from the minimum cost matrix.
-     *
-     *  @param i the frame number of this Matcher
-     *  @param j the frame number of the other Matcher
-     *  @return the cost of the minimum cost path to this location
-     */
-    double getValue(int i, int j);
-
-    /** Sets a value to the minimum cost matrix.
-     *
-     *  @param i the frame number of this Matcher
-     *  @param j the frame number of the other Matcher
-     *  @param value the cost of the minimum cost path to set for this location
-     */
-    void setValue(int i, int j, double value);
-
     /** Updates an entry in the distance matrix and the optimal path matrix.
      *
      *  @param i the frame number of this Matcher
@@ -269,8 +320,7 @@
     
     friend class MatchFeeder;
     friend class MatchFeatureFeeder;
-    friend class Finder;
-
+    
 }; // class Matcher
 
 #endif