private int convertFromSlave(int value, boolean approximate, int index) {
      if (index < 0) {
        return convertRaw(false, value, approximate);
      }

      CorrectedChange change = myChanges.get(index);
      int shift = change.newLength - change.oldLength;

      if (!change.synchronous) { // ?u' -> ?o'
        int converted = convertFromSlave(value, approximate, index - 1);
        if (converted < change.startMaster) { // Su' -> So'
          // Su' == Su; So' == So
          // value == Su'; converted == So
          return converted;
        }
        if (converted >= change.startMaster + change.oldLength) { // Eu' -> Eo'
          // Eo' == Eo + shift; Eu' == Eu
          // value == Eu'; converted == Eo
          return converted + shift;
        }

        // Mu' -> Mo'
        if (!approximate) return -1;
        // We can't convert Mo into Mo'
        // converted == Mo
        return append(converted, Math.min(change.newLength, converted - change.startMaster));
      }
      else { // ?m '-> ?o'
        if (value < change.startSlave) { // Sm' -> So'
          return convertFromSlave(value, approximate, index - 1);
        }
        if (value >= change.startSlave + change.newLength) { // Em' -> Eo'
          // Em' == Em + shift; Eo' == Eo + shift
          // value == Em'; converted == Eo
          int converted = convertFromSlave(value - shift, approximate, index - 1);
          return append(converted, shift);
        }

        // Mm' -> Mo'
        // Ao == Ao'; Am == Am'; Mo' - Ao' == Mm' - Am'
        // convertedStart == Ao; value - change.startMaster == Mm' - Am'
        int convertedStart = convertFromSlave(change.startSlave, approximate, index - 1);
        return append(convertedStart, value - change.startSlave);
      }
    }
private int convertFromSlave(int value, boolean approximate, int index)