diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java index 795075d28..a1c485aa0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java @@ -49,6 +49,7 @@ import java.util.List; import org.eclipse.jgit.util.IntList; +import org.eclipse.jgit.util.LongList; public class MyersDiff { protected EditList edits; @@ -202,7 +203,7 @@ Edit calculate(int beginA, int endA, int beginB, int endB) { abstract class EditPaths { private IntList x = new IntList(); - private IntList snake = new IntList(); + private LongList snake = new LongList(); int beginK, endK, middleK; int prevBeginK, prevEndK; /* if we hit one end early, no need to look further */ @@ -222,7 +223,7 @@ final int getX(int d, int k) { return x.get(getIndex(d, k)); } - final int getSnake(int d, int k) { + final long getSnake(int d, int k) { // TODO: remove if (k < beginK || k > endK) throw new RuntimeException("k " + k + " not in " + beginK + " - " + endK); @@ -253,22 +254,23 @@ void initialize(int k, int x, int minK, int maxK) { abstract int getRight(int x); abstract boolean isBetter(int left, int right); abstract void adjustMinMaxK(final int k, final int x); - abstract boolean meets(int d, int k, int x, int snake); + abstract boolean meets(int d, int k, int x, long snake); - final int newSnake(int k, int x) { - int y = k + x; - return x + (endA + 1) * y; + final long newSnake(int k, int x) { + long y = k + x; + long ret = ((long) x) << 32; + return ret | y; } - final int snake2x(int snake) { - return snake % (endA + 1); + final int snake2x(long snake) { + return (int) (snake >>> 32); } - final int snake2y(int snake) { - return snake / (endA + 1); + final int snake2y(long snake) { + return (int) snake; } - final boolean makeEdit(int snake1, int snake2) { + final boolean makeEdit(long snake1, long snake2) { int x1 = snake2x(snake1), x2 = snake2x(snake2); int y1 = snake2y(snake1), y2 = snake2y(snake2); /* @@ -301,7 +303,7 @@ boolean calculate(int d) { // go backwards so that we can avoid temp vars for (int k = endK; k >= beginK; k -= 2) { int left = -1, right = -1; - int leftSnake = -1, rightSnake = -1; + long leftSnake = -1L, rightSnake = -1L; // TODO: refactor into its own function if (k > prevBeginK) { int i = getIndex(d - 1, k - 1); @@ -325,7 +327,8 @@ boolean calculate(int d) { return true; right = getRight(end); } - int newX, newSnake; + int newX; + long newSnake; if (k >= prevEndK || (k > prevBeginK && isBetter(left, right))) { @@ -376,7 +379,7 @@ final void adjustMinMaxK(final int k, final int x) { } } - final boolean meets(int d, int k, int x, int snake) { + final boolean meets(int d, int k, int x, long snake) { if (k < backward.beginK || k > backward.endK) return false; // TODO: move out of loop @@ -418,7 +421,7 @@ final void adjustMinMaxK(final int k, final int x) { } } - final boolean meets(int d, int k, int x, int snake) { + final boolean meets(int d, int k, int x, long snake) { if (k < forward.beginK || k > forward.endK) return false; // TODO: move out of loop @@ -466,4 +469,4 @@ public static void main(String[] args) { e.printStackTrace(); } } -} +} \ No newline at end of file diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/LongList.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/LongList.java new file mode 100644 index 000000000..26608bb2a --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/LongList.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2009, Christian Halstrick + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +/** A more efficient List using a primitive long array. */ +public class LongList { + private long[] entries; + + private int count; + + /** Create an empty list with a default capacity. */ + public LongList() { + this(10); + } + + /** + * Create an empty list with the specified capacity. + * + * @param capacity + * number of entries the list can initially hold. + */ + public LongList(final int capacity) { + entries = new long[capacity]; + } + + /** @return number of entries in this list */ + public int size() { + return count; + } + + /** + * @param i + * index to read, must be in the range [0, {@link #size()}). + * @return the number at the specified index + * @throws ArrayIndexOutOfBoundsException + * the index outside the valid range + */ + public long get(final int i) { + if (count <= i) + throw new ArrayIndexOutOfBoundsException(i); + return entries[i]; + } + + /** Empty this list */ + public void clear() { + count = 0; + } + + /** + * Add an entry to the end of the list. + * + * @param n + * the number to add. + */ + public void add(final long n) { + if (count == entries.length) + grow(); + entries[count++] = n; + } + + /** + * Assign an entry in the list. + * + * @param index + * index to set, must be in the range [0, {@link #size()}). + * @param n + * value to store at the position. + */ + public void set(final int index, final long n) { + if (count < index) + throw new ArrayIndexOutOfBoundsException(index); + else if (count == index) + add(n); + else + entries[index] = n; + } + + /** + * Pad the list with entries. + * + * @param toIndex + * index position to stop filling at. 0 inserts no filler. 1 + * ensures the list has a size of 1, adding val if + * the list is currently empty. + * @param val + * value to insert into padded positions. + */ + public void fillTo(int toIndex, final long val) { + while (count < toIndex) + add(val); + } + + private void grow() { + final long[] n = new long[(entries.length + 16) * 3 / 2]; + System.arraycopy(entries, 0, n, 0, count); + entries = n; + } + + public String toString() { + final StringBuilder r = new StringBuilder(); + r.append('['); + for (int i = 0; i < count; i++) { + if (i > 0) + r.append(", "); + r.append(entries[i]); + } + r.append(']'); + return r.toString(); + } +}