diff --git a/source/net/yacy/kelondro/index/Row.java b/source/net/yacy/kelondro/index/Row.java index 133f6d0d9..0b7ab9413 100644 --- a/source/net/yacy/kelondro/index/Row.java +++ b/source/net/yacy/kelondro/index/Row.java @@ -346,7 +346,7 @@ public final class Row { // compares only the content of the primary key if (Row.this.objectOrder == null) throw new kelondroException("objects cannot be compared, no order given"); assert Row.this.primaryKeyLength == o.getPrimaryKeyLength(); - return Row.this.objectOrder.compare(bytes(), 0, o.bytes(), 0, Row.this.primaryKeyLength); + return Row.this.objectOrder.compare(bytes(), o.bytes(), Row.this.primaryKeyLength); } public int compare(final Entry o1, final Entry o2) { diff --git a/source/net/yacy/kelondro/order/Base64Order.java b/source/net/yacy/kelondro/order/Base64Order.java index 094f50675..b67f5b5d0 100644 --- a/source/net/yacy/kelondro/order/Base64Order.java +++ b/source/net/yacy/kelondro/order/Base64Order.java @@ -406,9 +406,9 @@ public class Base64Order extends AbstractOrder implements ByteOrder, Com public final int compare(final byte[] a, final byte[] b) { try { return (this.asc) ? - ((this.zero == null) ? compares(a, b) : compare0(a, 0, b, 0, a.length)) + ((this.zero == null) ? compares(a, b) : compare0(a, b, a.length)) : - ((this.zero == null) ? compares(b, a) : compare0(b, 0, a, 0, a.length)); + ((this.zero == null) ? compares(b, a) : compare0(b, a, a.length)); } catch (final Throwable e) { // if a or b is not well-formed, an ArrayIndexOutOfBoundsException may occur // in that case we don't want that the exception makes databse functions @@ -429,6 +429,27 @@ public class Base64Order extends AbstractOrder implements ByteOrder, Com } } + public final int compare(final byte[] a, final byte[] b, final int length) { + try { + return (this.asc) ? + compare0(a, b, length) + : + compare0(b, a, length); + } catch (final Throwable e) { + // same handling as in simple compare method above + final boolean wfa = wellformed(a, 0, length); + final boolean wfb = wellformed(b, 0, length); + if (wfa && wfb) { + // uh strange. throw the exception + if (e instanceof ArrayIndexOutOfBoundsException) throw (ArrayIndexOutOfBoundsException) e; + throw new RuntimeException(e.getMessage()); + } + if (wfa) return (this.asc) ? -1 : 1; + if (wfb) return (this.asc) ? 1 : -1; + return ((this.asc) ? 1 : -1) * NaturalOrder.naturalOrder.compare(a, b, length); + } + } + public final int compare(final byte[] a, final int aoffset, final byte[] b, final int boffset, final int length) { try { return (this.asc) ? @@ -450,33 +471,44 @@ public class Base64Order extends AbstractOrder implements ByteOrder, Com } } - private final int compare0(final byte[] a, final int aoffset, final byte[] b, final int boffset, final int length) { + private final int compare0(final byte[] a, final byte[] b, int length) { + if (this.zero == null) return compares(a, b, length); + + // we have an artificial start point. check all combinations + if (this.zero.length < length) length = this.zero.length; + final int az = compares(a, this.zero, length); // -1 if a < z; 0 if a == z; 1 if a > z + final int bz = compares(b, this.zero, length); // -1 if b < z; 0 if b == z; 1 if b > z + if (az == bz) return compares(a, b, length); + return sig(az - bz); + } + + private final int compare0(final byte[] a, final int aoffset, final byte[] b, final int boffset, int length) { if (this.zero == null) return compares(a, aoffset, b, boffset, length); // we have an artificial start point. check all combinations - final int az = compares(a, aoffset, this.zero, 0, Math.min(length, this.zero.length)); // -1 if a < z; 0 if a == z; 1 if a > z - final int bz = compares(b, boffset, this.zero, 0, Math.min(length, this.zero.length)); // -1 if b < z; 0 if b == z; 1 if b > z + if (this.zero.length < length) length = this.zero.length; + final int az = compares(a, aoffset, this.zero, 0, length); // -1 if a < z; 0 if a == z; 1 if a > z + final int bz = compares(b, boffset, this.zero, 0, length); // -1 if b < z; 0 if b == z; 1 if b > z if (az == bz) return compares(a, aoffset, b, boffset, length); return sig(az - bz); } private final int compares(final byte[] a, final byte[] b) { - assert (this.ahpla.length == 128); + //assert (this.ahpla.length == 128); short i = 0; final int al = a.length; final int bl = b.length; final short ml = (short) Math.min(al, bl); byte ac, bc; while (i < ml) { // trace point - assert (i < a.length) : "i = " + i + ", aoffset = " + 0 + ", a.length = " + a.length + ", a = " + NaturalOrder.arrayList(a, 0, al); - assert (i < b.length) : "i = " + i + ", boffset = " + 0 + ", b.length = " + b.length + ", b = " + NaturalOrder.arrayList(b, 0, al); + //assert (i < a.length) : "i = " + i + ", aoffset = " + 0 + ", a.length = " + a.length + ", a = " + NaturalOrder.arrayList(a, 0, al); + //assert (i < b.length) : "i = " + i + ", boffset = " + 0 + ", b.length = " + b.length + ", b = " + NaturalOrder.arrayList(b, 0, al); ac = a[i]; - assert (ac >= 0) && (ac < 128) : "ac = " + ac + ", a = " + NaturalOrder.arrayList(a, 0, al); + //assert (ac >= 0) && (ac < 128) : "ac = " + ac + ", a = " + NaturalOrder.arrayList(a, 0, al); bc = b[i]; - assert (bc >= 0) && (bc < 128) : "bc = " + bc + ", b = " + NaturalOrder.arrayList(b, 0, al); - assert ac != 0; - assert bc != 0; - //if ((ac == 0) && (bc == 0)) return 0; // zero-terminated length + //assert (bc >= 0) && (bc < 128) : "bc = " + bc + ", b = " + NaturalOrder.arrayList(b, 0, al); + //assert ac != 0; + //assert bc != 0; if (ac != bc) return this.ab[(ac << 7) | bc]; i++; } @@ -487,30 +519,45 @@ public class Base64Order extends AbstractOrder implements ByteOrder, Com return 0; } - private final int compares(final byte[] a, final int aoffset, final byte[] b, final int boffset, final int length) { - assert (aoffset + length <= a.length) : "a.length = " + a.length + ", aoffset = " + aoffset + ", alength = " + length; - assert (boffset + length <= b.length) : "b.length = " + b.length + ", boffset = " + boffset + ", blength = " + length; + private final int compares(final byte[] a, final byte[] b, final int length) { + assert (length <= a.length) : "a.length = " + a.length + ", alength = " + length; + assert (length <= b.length) : "b.length = " + b.length + ", blength = " + length; assert (this.ahpla.length == 128); short i = 0; byte ac, bc; - //byte acc, bcc; - //int c = 0; while (i < length) { - assert (i + aoffset < a.length) : "i = " + i + ", aoffset = " + aoffset + ", a.length = " + a.length + ", a = " + NaturalOrder.arrayList(a, aoffset, length); - assert (i + boffset < b.length) : "i = " + i + ", boffset = " + boffset + ", b.length = " + b.length + ", b = " + NaturalOrder.arrayList(b, boffset, length); - ac = a[aoffset + i]; - assert (ac >= 0) && (ac < 128) : "ac = " + ac + ", a = " + NaturalOrder.arrayList(a, aoffset, length); - bc = b[boffset + i]; - assert (bc >= 0) && (bc < 128) : "bc = " + bc + ", b = " + NaturalOrder.arrayList(b, boffset, length); + assert (i < a.length) : "i = " + i + ", a.length = " + a.length + ", a = " + NaturalOrder.arrayList(a, 0, length); + assert (i < b.length) : "i = " + i + ", b.length = " + b.length + ", b = " + NaturalOrder.arrayList(b, 0, length); + ac = a[i]; + assert (ac >= 0) && (ac < 128) : "ac = " + ac + ", a = " + NaturalOrder.arrayList(a, 0, length); + bc = b[i]; + assert (bc >= 0) && (bc < 128) : "bc = " + bc + ", b = " + NaturalOrder.arrayList(b, 0, length); assert ac != 0; assert bc != 0; - //if ((ac == 0) && (bc == 0)) return 0; // zero-terminated length - if (ac == bc) { - // shortcut in case of equality: we don't need to lookup the ahpla value - i++; - continue; - } - return this.ab[(ac << 7) | bc]; + if (ac != bc) return this.ab[(ac << 7) | bc]; + i++; + } + // they are equal + return 0; + } + + private final int compares(final byte[] a, final int aoffset, final byte[] b, final int boffset, final int length) { + //assert (aoffset + length <= a.length) : "a.length = " + a.length + ", aoffset = " + aoffset + ", alength = " + length; + //assert (boffset + length <= b.length) : "b.length = " + b.length + ", boffset = " + boffset + ", blength = " + length; + //assert (this.ahpla.length == 128); + short i = 0; + byte ac, bc; + while (i < length) { + //assert (i + aoffset < a.length) : "i = " + i + ", aoffset = " + aoffset + ", a.length = " + a.length + ", a = " + NaturalOrder.arrayList(a, aoffset, length); + //assert (i + boffset < b.length) : "i = " + i + ", boffset = " + boffset + ", b.length = " + b.length + ", b = " + NaturalOrder.arrayList(b, boffset, length); + ac = a[aoffset + i]; + //assert (ac >= 0) && (ac < 128) : "ac = " + ac + ", a = " + NaturalOrder.arrayList(a, aoffset, length); + bc = b[boffset + i]; + //assert (bc >= 0) && (bc < 128) : "bc = " + bc + ", b = " + NaturalOrder.arrayList(b, boffset, length); + //assert ac != 0; + //assert bc != 0; + if (ac != bc) return this.ab[(ac << 7) | bc]; + i++; } // they are equal return 0; diff --git a/source/net/yacy/kelondro/order/ByteOrder.java b/source/net/yacy/kelondro/order/ByteOrder.java index 972471560..6178fa73c 100644 --- a/source/net/yacy/kelondro/order/ByteOrder.java +++ b/source/net/yacy/kelondro/order/ByteOrder.java @@ -10,7 +10,7 @@ // $LastChangedBy$ // // LICENSE -// +// // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or @@ -35,19 +35,21 @@ import net.yacy.kelondro.index.RowSpaceExceededException; public interface ByteOrder extends Order { public boolean wellformed(byte[] a); - + public boolean wellformed(byte[] a, int start, int len); public int compare(byte[] a, byte[] b); - + + public int compare(byte[] a, byte[] b, int len); + public int compare(byte[] a, int astart, byte[] b, int bstart, int len); public boolean equal(final byte[] a, final byte[] b); - + public boolean equal(final byte[] a, int astart, final byte[] b, int bstart, int length); - + public long cardinal(final byte[] a, int off, int len); - + public HandleSet getHandleSet(final int keylength, final int space) throws RowSpaceExceededException; public byte[] smallest(byte[] a, byte[] b); diff --git a/source/net/yacy/kelondro/order/NaturalOrder.java b/source/net/yacy/kelondro/order/NaturalOrder.java index 9a76c682d..a27019f2d 100644 --- a/source/net/yacy/kelondro/order/NaturalOrder.java +++ b/source/net/yacy/kelondro/order/NaturalOrder.java @@ -35,32 +35,32 @@ import net.yacy.kelondro.index.HandleSet; import net.yacy.kelondro.index.RowSpaceExceededException; public final class NaturalOrder extends AbstractOrder implements ByteOrder, Comparator, Cloneable { - + public static final ByteOrder naturalOrder = new NaturalOrder(true); public static final Comparator naturalComparator = new StringOrder(naturalOrder); public NaturalOrder(final boolean ascending) { this.asc = ascending; this.zero = null; } - + public HandleSet getHandleSet(final int keylength, final int space) throws RowSpaceExceededException { return new HandleSet(keylength, this, space); } - + public boolean wellformed(final byte[] a) { return true; } - + public boolean wellformed(final byte[] a, final int astart, final int alength) { return true; } - + public final Order clone() { final NaturalOrder o = new NaturalOrder(this.asc); o.rotate(this.zero); return o; } - + public static ByteOrder orderBySignature(final String signature) { ByteOrder oo = null; if (oo == null) oo = NaturalOrder.bySignature(signature); @@ -68,30 +68,30 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd if (oo == null) oo = new NaturalOrder(true); return oo; } - + public final static ByteOrder bySignature(final String signature) { if (signature.equals("nd")) return new NaturalOrder(false); if (signature.equals("nu")) return new NaturalOrder(true); return null; } - + public final String signature() { - if (!asc) return "nd"; - if ( asc) return "nu"; + if (!this.asc) return "nd"; + if ( this.asc) return "nu"; return null; } - - private final static long cardinalI(final byte[] key, int off, int len) { + + private final static long cardinalI(final byte[] key, int off, final int len) { // returns a cardinal number in the range of 0 .. Long.MAX_VALUE long c = 0; - int lim = off + Math.min(8, len); - int lim8 = off + 8; + final int lim = off + Math.min(8, len); + final int lim8 = off + 8; while (off < lim) c = (c << 8) | ((long) key[off++] & 0xFF); while (off++ < lim8) c = (c << 8); c = c >>> 1; return c; } - + public final long cardinal(final byte[] key) { if (this.zero == null) return cardinalI(key, 0, key.length); final long zeroCardinal = cardinalI(this.zero, 0, this.zero.length); @@ -99,15 +99,15 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd if (keyCardinal > zeroCardinal) return keyCardinal - zeroCardinal; return Long.MAX_VALUE - keyCardinal + zeroCardinal; } - - public long cardinal(final byte[] key, int off, int len) { + + public long cardinal(final byte[] key, final int off, final int len) { if (this.zero == null) return cardinalI(key, off, len); final long zeroCardinal = cardinalI(this.zero, 0, this.zero.length); final long keyCardinal = cardinalI(key, off, len); if (keyCardinal > zeroCardinal) return keyCardinal - zeroCardinal; return Long.MAX_VALUE - keyCardinal + zeroCardinal; } - + public final static byte[] encodeLong(long c, int length) { final byte[] b = new byte[length]; while (length > 0) { @@ -132,7 +132,7 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd while (p < s.length) c = (c << 8) | ((long) s[p++] & 0xFF); return c; } - + public final static long decodeLong(final byte[] s, int offset, final int length) { if (s == null) return 0; long c = 0; @@ -144,7 +144,7 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd private static final int sig(final int x) { return (x > 0) ? 1 : (x < 0) ? -1 : 0; } - + // Compares its two arguments for order. // Returns -1, 0, or 1 as the first argument // is less than, equal to, or greater than the second. @@ -152,29 +152,43 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd // with filled-up char(0)-values public final int compare(final byte[] a, final byte[] b) { if (a.length == b.length) { - return (asc) ? compare0(a, 0, b, 0, a.length) : compare0(b, 0, a, 0, a.length); + return (this.asc) ? compare0(a, 0, b, 0, a.length) : compare0(b, 0, a, 0, a.length); } - int length = Math.min(a.length, b.length); - if (asc) { - int c = compare0(a, 0, b, 0, length); + final int length = Math.min(a.length, b.length); + if (this.asc) { + final int c = compare0(a, 0, b, 0, length); if (c != 0) return c; return (a.length > b.length) ? 1 : -1; } - int c = compare0(b, 0, a, 0, length); + final int c = compare0(b, 0, a, 0, length); if (c != 0) return c; return (a.length > b.length) ? -1 : 1; } + public final int compare(final byte[] a, final byte[] b, final int length) { + return (this.asc) ? compare0(a, b, length) : compare0(b, a, length); + } + public final int compare(final byte[] a, final int aoffset, final byte[] b, final int boffset, final int length) { - return (asc) ? compare0(a, aoffset, b, boffset, length) : compare0(b, boffset, a, aoffset, length); + return (this.asc) ? compare0(a, aoffset, b, boffset, length) : compare0(b, boffset, a, aoffset, length); } - public final int compare0(final byte[] a, final int aoffset, final byte[] b, final int boffset, final int length) { - if (zero == null) return compares(a, aoffset, b, boffset, length); + private final int compare0(final byte[] a, final byte[] b, final int length) { + if (this.zero == null) return compares(a, b, length); // we have an artificial start point. check all combinations - assert length == zero.length; - final int az = compares(a, aoffset, zero, 0, length); // -1 if a < z; 0 if a == z; 1 if a > z - final int bz = compares(b, boffset, zero, 0, length); // -1 if b < z; 0 if b == z; 1 if b > z + assert length == this.zero.length; + final int az = compares(a, this.zero, length); // -1 if a < z; 0 if a == z; 1 if a > z + final int bz = compares(b, this.zero, length); // -1 if b < z; 0 if b == z; 1 if b > z + if (az == bz) return compares(a, b, length); + return sig(az - bz); + } + + private final int compare0(final byte[] a, final int aoffset, final byte[] b, final int boffset, final int length) { + if (this.zero == null) return compares(a, aoffset, b, boffset, length); + // we have an artificial start point. check all combinations + assert length == this.zero.length; + final int az = compares(a, aoffset, this.zero, 0, length); // -1 if a < z; 0 if a == z; 1 if a > z + final int bz = compares(b, boffset, this.zero, 0, length); // -1 if b < z; 0 if b == z; 1 if b > z if (az == bz) return compares(a, aoffset, b, boffset, length); return sig(az - bz); } @@ -191,7 +205,7 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd } return true; } - + public final boolean equal(final byte[] a, int astart, final byte[] b, int bstart, int length) { if ((a == null) && (b == null)) return true; if ((a == null) || (b == null)) return false; @@ -200,8 +214,23 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd } return true; } - - public static final int compares(final byte[] a, final int aoffset, final byte[] b, final int boffset, final int length) { + + private static final int compares(final byte[] a, final byte[] b, final int length) { + int i = 0; + int aa, bb; + while (i < length) { + aa = 0xff & a[i]; + bb = 0xff & b[i]; + if (aa > bb) return 1; + if (aa < bb) return -1; + // else the bytes are equal and it may go on yet undecided + i++; + } + // they are equal + return 0; + } + + private static final int compares(final byte[] a, final int aoffset, final byte[] b, final int boffset, final int length) { int i = 0; int aa, bb; while (i < length) { @@ -226,7 +255,7 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd sb.append(']'); return sb.toString(); } - + public static final String table(final byte[] b, final int linewidth) { if (b == null) return "NULL"; if (b.length == 0) return "[]"; @@ -242,25 +271,25 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd sb.append('\n'); return sb.toString(); } - - public static Iterator LongIterator(Iterator b256Iterator) { + + public static Iterator LongIterator(final Iterator b256Iterator) { return new LongIter(b256Iterator); } - + public static class LongIter implements Iterator { private final Iterator b256Iterator; - - public LongIter(Iterator b256Iterator) { + + public LongIter(final Iterator b256Iterator) { this.b256Iterator = b256Iterator; } - + public boolean hasNext() { return this.b256Iterator.hasNext(); } public Long next() { - byte[] b = this.b256Iterator.next(); + final byte[] b = this.b256Iterator.next(); assert (b != null); if (b == null) return null; return Long.valueOf(decodeLong(b)); @@ -269,9 +298,9 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd public void remove() { this.b256Iterator.remove(); } - + } - + public static void main(final String[] args) { final byte[] t = new byte[12]; for (int i = 0; i < 12; i++) t[i] = (byte) 255; @@ -279,5 +308,5 @@ public final class NaturalOrder extends AbstractOrder implements ByteOrd final Order o = new NaturalOrder(true); System.out.println(o.partition(t, 16)); } - + }