private void execute(int oldStart, int oldEnd, int newStart, int newEnd, int differenceEstimate,
                       boolean throwException) throws FilesTooBigForDiffException {
    assert oldStart <= oldEnd && newStart <= newEnd;
    if (oldStart < oldEnd && newStart < newEnd) {
      final int oldLength = oldEnd - oldStart;
      final int newLength = newEnd - newStart;
      VForward[newLength + 1] = 0;
      VBackward[newLength + 1] = 0;
      final int halfD = (differenceEstimate + 1) / 2;
      int xx, kk, td;
      xx = kk = td = -1;

      loop:
      for (int d = 0; d <= halfD; ++d) {
        final int L = newLength + Math.max(-d, -newLength + ((d ^ newLength) & 1));
        final int R = newLength + Math.min(d, oldLength - ((d ^ oldLength) & 1));
        for (int k = L; k <= R; k += 2) {
          int x = k == L || k != R && VForward[k - 1] < VForward[k + 1] ? VForward[k + 1] : VForward[k - 1] + 1;
          int y = x - k + newLength;
          x += commonSubsequenceLengthForward(oldStart + x, newStart + y,
                                              Math.min(oldEnd - oldStart - x, newEnd - newStart - y));
          VForward[k] = x;
        }

        if ((oldLength - newLength) % 2 != 0) {
          for (int k = L; k <= R; k += 2) {
            if (oldLength - (d - 1) <= k && k <= oldLength + (d - 1)) {
              if (VForward[k] + VBackward[newLength + oldLength - k] >= oldLength) {
                xx = VForward[k];
                kk = k;
                td = 2 * d - 1;
                break loop;
              }
            }
          }
        }

        for (int k = L; k <= R; k += 2) {
          int x = k == L || k != R && VBackward[k - 1] < VBackward[k + 1] ? VBackward[k + 1] : VBackward[k - 1] + 1;
          int y = x - k + newLength;
          x += commonSubsequenceLengthBackward(oldEnd - 1 - x, newEnd - 1 - y,
                                               Math.min(oldEnd - oldStart - x, newEnd - newStart - y));
          VBackward[k] = x;
        }

        if ((oldLength - newLength) % 2 == 0) {
          for (int k = L; k <= R; k += 2) {
            if (oldLength - d <= k && k <= oldLength + d) {
              if (VForward[oldLength + newLength - k] + VBackward[k] >= oldLength) {
                xx = oldLength - VBackward[k];
                kk = oldLength + newLength - k;
                td = 2 * d;
                break loop;
              }
            }
          }
        }
      }

      if (td > 1) {
        final int yy = xx - kk + newLength;
        final int oldDiff = (td + 1) / 2;
        if (0 < xx && 0 < yy) execute(oldStart, oldStart + xx, newStart, newStart + yy, oldDiff, throwException);
        if (oldStart + xx < oldEnd && newStart + yy < newEnd) execute(oldStart + xx, oldEnd, newStart + yy, newEnd, td - oldDiff, throwException);
      }
      else if (td >= 0) {
        int x = oldStart;
        int y = newStart;
        while (x < oldEnd && y < newEnd) {
          final int commonLength = commonSubsequenceLengthForward(x, y, Math.min(oldEnd - x, newEnd - y));
          if (commonLength > 0) {
            addUnchanged(x, y, commonLength);
            x += commonLength;
            y += commonLength;
          }
          else if (oldEnd - oldStart > newEnd - newStart) {
            ++x;
          }
          else {
            ++y;
          }
        }
      }
      else {
        //The difference is more than the given estimate
        if (throwException) throw new FilesTooBigForDiffException();
      }
    }
  }
private void execute(int oldStart, int oldEnd, int newStart, int newEnd, int differenceEstimate,
                       boolean throwException)