69 }
70
71 static int arraySizeFor(Class<?> type) {
72 assert type.isPrimitive();
73 return 4 * MAX_WIDTH / typeToWidth.get(type);
74 }
75
76 enum BufferKind {
77 HEAP,
78 HEAP_VIEW,
79 DIRECT;
80 }
81
82 static abstract class BufferType<T extends Buffer, E> {
83 final BufferKind k;
84 final Class<?> bufferType;
85 final Class<?> elementType;
86
87 final MethodHandle eq;
88 final MethodHandle cmp;
89
90 final MethodHandle getter;
91 final MethodHandle setter;
92
93 BufferType(BufferKind k, Class<T> bufferType, Class<?> elementType) {
94 this.k = k;
95 this.bufferType = bufferType;
96 this.elementType = elementType;
97
98 var lookup = MethodHandles.lookup();
99 try {
100 eq = lookup.findVirtual(bufferType, "equals", MethodType.methodType(boolean.class, Object.class));
101 cmp = lookup.findVirtual(bufferType, "compareTo", MethodType.methodType(int.class, bufferType));
102
103 getter = lookup.findVirtual(bufferType, "get", MethodType.methodType(elementType, int.class));
104 setter = lookup.findVirtual(bufferType, "put", MethodType.methodType(bufferType, int.class, elementType));
105 }
106 catch (Exception e) {
107 throw new AssertionError(e);
108 }
109 }
110
111 @Override
112 public String toString() {
113 return bufferType.getName() + " " + k;
114 }
115
116 T construct(int length) {
117 return construct(length, ByteOrder.BIG_ENDIAN);
118 }
119
120 abstract T construct(int length, ByteOrder bo);
121
169 return (int) cmp.invoke(a, b);
170 }
171 catch (RuntimeException | Error e) {
172 throw e;
173 }
174 catch (Throwable t) {
175 throw new Error(t);
176 }
177 }
178
179 boolean pairWiseEquals(T a, T b) {
180 if (a.remaining() != b.remaining())
181 return false;
182 int p = a.position();
183 for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--)
184 if (!get(a, i).equals(get(b, j)))
185 return false;
186 return true;
187 }
188
189 static class Bytes extends BufferType<ByteBuffer, Byte> {
190 Bytes(BufferKind k) {
191 super(k, ByteBuffer.class, byte.class);
192 }
193
194 @Override
195 ByteBuffer construct(int length, ByteOrder bo) {
196 switch (k) {
197 case DIRECT:
198 return ByteBuffer.allocateDirect(length).order(bo);
199 default:
200 case HEAP_VIEW:
201 case HEAP:
202 return ByteBuffer.allocate(length).order(bo);
203 }
204 }
205
206 @Override
207 Object convert(Object o) {
208 return o instanceof Integer
406 ? ((Integer) o).doubleValue()
407 : o;
408 }
409
410 @Override
411 boolean pairWiseEquals(DoubleBuffer a, DoubleBuffer b) {
412 if (a.remaining() != b.remaining())
413 return false;
414 int p = a.position();
415 for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--) {
416 double av = a.get(i);
417 double bv = b.get(j);
418 if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv)))
419 return false;
420 }
421 return true;
422 }
423 }
424 }
425
426
427 static Object[][] bufferTypes;
428
429 @DataProvider
430 public static Object[][] bufferTypesProvider() {
431 if (bufferTypes == null) {
432 bufferTypes = new Object[][]{
433 {new BufferType.Bytes(BufferKind.HEAP)},
434 {new BufferType.Bytes(BufferKind.DIRECT)},
435 {new BufferType.Chars(BufferKind.HEAP)},
436 {new BufferType.Chars(BufferKind.HEAP_VIEW)},
437 {new BufferType.Chars(BufferKind.DIRECT)},
438 {new BufferType.Shorts(BufferKind.HEAP)},
439 {new BufferType.Shorts(BufferKind.HEAP_VIEW)},
440 {new BufferType.Shorts(BufferKind.DIRECT)},
441 {new BufferType.Ints(BufferKind.HEAP)},
442 {new BufferType.Ints(BufferKind.HEAP_VIEW)},
443 {new BufferType.Ints(BufferKind.DIRECT)},
444 {new BufferType.Floats(BufferKind.HEAP)},
445 {new BufferType.Floats(BufferKind.HEAP_VIEW)},
446 {new BufferType.Floats(BufferKind.DIRECT)},
618 int aLength = aTo - aFrom;
619
620 B as = aLength != s
621 ? bt.slice(a, aFrom, aTo, dupOtherwiseSlice)
622 : a;
623
624 for (int bFrom : ranges(0, s)) {
625 for (int bTo : ranges(bFrom, s)) {
626 int bLength = bTo - bFrom;
627
628 B bs = bLength != s
629 ? bt.slice(b, bFrom, bTo, dupOtherwiseSlice)
630 : b;
631
632 boolean eq = bt.pairWiseEquals(as, bs);
633 Assert.assertEquals(bt.equals(as, bs), eq);
634 Assert.assertEquals(bt.equals(bs, as), eq);
635 if (eq) {
636 Assert.assertEquals(bt.compare(as, bs), 0);
637 Assert.assertEquals(bt.compare(bs, as), 0);
638 }
639 else {
640 int aCb = bt.compare(as, bs);
641 int bCa = bt.compare(bs, as);
642 int v = Integer.signum(aCb) * Integer.signum(bCa);
643 Assert.assertTrue(v == -1);
644 }
645 }
646 }
647
648 if (aLength > 0 && !a.isReadOnly()) {
649 for (int i = aFrom; i < aTo; i++) {
650 B c = aConstructor.apply(bt, a.capacity());
651 B cs = aLength != s
652 ? bt.slice(c, aFrom, aTo, dupOtherwiseSlice)
653 : c;
654
655 // Create common prefix with a length of i - aFrom
656 bt.set(c, i, -1);
657
658 Assert.assertFalse(bt.equals(c, a));
659
660 int cCa = bt.compare(cs, as);
661 int aCc = bt.compare(as, cs);
662 int v = Integer.signum(cCa) * Integer.signum(aCc);
663 Assert.assertTrue(v == -1);
664 }
665 }
666 }
667 }
668 }
669 }
670 }
671
672 static int[] ranges(int from, int to) {
673 int width = to - from;
674 switch (width) {
675 case 0:
676 return new int[]{};
677 case 1:
678 return new int[]{from, to};
679 case 2:
680 return new int[]{from, from + 1, to};
681 case 3:
682 return new int[]{from, from + 1, from + 2, to};
683 default:
|
69 }
70
71 static int arraySizeFor(Class<?> type) {
72 assert type.isPrimitive();
73 return 4 * MAX_WIDTH / typeToWidth.get(type);
74 }
75
76 enum BufferKind {
77 HEAP,
78 HEAP_VIEW,
79 DIRECT;
80 }
81
82 static abstract class BufferType<T extends Buffer, E> {
83 final BufferKind k;
84 final Class<?> bufferType;
85 final Class<?> elementType;
86
87 final MethodHandle eq;
88 final MethodHandle cmp;
89 final MethodHandle mismtch;
90
91 final MethodHandle getter;
92 final MethodHandle setter;
93
94 BufferType(BufferKind k, Class<T> bufferType, Class<?> elementType) {
95 this.k = k;
96 this.bufferType = bufferType;
97 this.elementType = elementType;
98
99 var lookup = MethodHandles.lookup();
100 try {
101 eq = lookup.findVirtual(bufferType, "equals", MethodType.methodType(boolean.class, Object.class));
102 cmp = lookup.findVirtual(bufferType, "compareTo", MethodType.methodType(int.class, bufferType));
103 mismtch = lookup.findVirtual(bufferType, "mismatch", MethodType.methodType(int.class, bufferType));
104
105 getter = lookup.findVirtual(bufferType, "get", MethodType.methodType(elementType, int.class));
106 setter = lookup.findVirtual(bufferType, "put", MethodType.methodType(bufferType, int.class, elementType));
107 }
108 catch (Exception e) {
109 throw new AssertionError(e);
110 }
111 }
112
113 @Override
114 public String toString() {
115 return bufferType.getName() + " " + k;
116 }
117
118 T construct(int length) {
119 return construct(length, ByteOrder.BIG_ENDIAN);
120 }
121
122 abstract T construct(int length, ByteOrder bo);
123
171 return (int) cmp.invoke(a, b);
172 }
173 catch (RuntimeException | Error e) {
174 throw e;
175 }
176 catch (Throwable t) {
177 throw new Error(t);
178 }
179 }
180
181 boolean pairWiseEquals(T a, T b) {
182 if (a.remaining() != b.remaining())
183 return false;
184 int p = a.position();
185 for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--)
186 if (!get(a, i).equals(get(b, j)))
187 return false;
188 return true;
189 }
190
191 int mismatch(T a, T b) {
192 try {
193 return (int) mismtch.invoke(a, b);
194 }
195 catch (RuntimeException | Error e) {
196 throw e;
197 }
198 catch (Throwable t) {
199 throw new Error(t);
200 }
201 }
202
203 static class Bytes extends BufferType<ByteBuffer, Byte> {
204 Bytes(BufferKind k) {
205 super(k, ByteBuffer.class, byte.class);
206 }
207
208 @Override
209 ByteBuffer construct(int length, ByteOrder bo) {
210 switch (k) {
211 case DIRECT:
212 return ByteBuffer.allocateDirect(length).order(bo);
213 default:
214 case HEAP_VIEW:
215 case HEAP:
216 return ByteBuffer.allocate(length).order(bo);
217 }
218 }
219
220 @Override
221 Object convert(Object o) {
222 return o instanceof Integer
420 ? ((Integer) o).doubleValue()
421 : o;
422 }
423
424 @Override
425 boolean pairWiseEquals(DoubleBuffer a, DoubleBuffer b) {
426 if (a.remaining() != b.remaining())
427 return false;
428 int p = a.position();
429 for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--) {
430 double av = a.get(i);
431 double bv = b.get(j);
432 if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv)))
433 return false;
434 }
435 return true;
436 }
437 }
438 }
439
440 static Object[][] bufferTypes;
441
442 @DataProvider
443 public static Object[][] bufferTypesProvider() {
444 if (bufferTypes == null) {
445 bufferTypes = new Object[][]{
446 {new BufferType.Bytes(BufferKind.HEAP)},
447 {new BufferType.Bytes(BufferKind.DIRECT)},
448 {new BufferType.Chars(BufferKind.HEAP)},
449 {new BufferType.Chars(BufferKind.HEAP_VIEW)},
450 {new BufferType.Chars(BufferKind.DIRECT)},
451 {new BufferType.Shorts(BufferKind.HEAP)},
452 {new BufferType.Shorts(BufferKind.HEAP_VIEW)},
453 {new BufferType.Shorts(BufferKind.DIRECT)},
454 {new BufferType.Ints(BufferKind.HEAP)},
455 {new BufferType.Ints(BufferKind.HEAP_VIEW)},
456 {new BufferType.Ints(BufferKind.DIRECT)},
457 {new BufferType.Floats(BufferKind.HEAP)},
458 {new BufferType.Floats(BufferKind.HEAP_VIEW)},
459 {new BufferType.Floats(BufferKind.DIRECT)},
631 int aLength = aTo - aFrom;
632
633 B as = aLength != s
634 ? bt.slice(a, aFrom, aTo, dupOtherwiseSlice)
635 : a;
636
637 for (int bFrom : ranges(0, s)) {
638 for (int bTo : ranges(bFrom, s)) {
639 int bLength = bTo - bFrom;
640
641 B bs = bLength != s
642 ? bt.slice(b, bFrom, bTo, dupOtherwiseSlice)
643 : b;
644
645 boolean eq = bt.pairWiseEquals(as, bs);
646 Assert.assertEquals(bt.equals(as, bs), eq);
647 Assert.assertEquals(bt.equals(bs, as), eq);
648 if (eq) {
649 Assert.assertEquals(bt.compare(as, bs), 0);
650 Assert.assertEquals(bt.compare(bs, as), 0);
651
652 // If buffers are equal, there shall be no mismatch
653 Assert.assertEquals(bt.mismatch(as, bs), -1);
654 Assert.assertEquals(bt.mismatch(bs, as), -1);
655 }
656 else {
657 int aCb = bt.compare(as, bs);
658 int bCa = bt.compare(bs, as);
659 int v = Integer.signum(aCb) * Integer.signum(bCa);
660 Assert.assertTrue(v == -1);
661
662 int aMs = bt.mismatch(as, bs);
663 int bMs = bt.mismatch(bs, as);
664 Assert.assertNotEquals(aMs, -1);
665 Assert.assertEquals(aMs, bMs);
666 }
667 }
668 }
669
670 if (aLength > 0 && !a.isReadOnly()) {
671 for (int i = aFrom; i < aTo; i++) {
672 B c = aConstructor.apply(bt, a.capacity());
673 B cs = aLength != s
674 ? bt.slice(c, aFrom, aTo, dupOtherwiseSlice)
675 : c;
676
677 // Create common prefix with a length of i - aFrom
678 bt.set(c, i, -1);
679
680 Assert.assertFalse(bt.equals(c, a));
681
682 int cCa = bt.compare(cs, as);
683 int aCc = bt.compare(as, cs);
684 int v = Integer.signum(cCa) * Integer.signum(aCc);
685 Assert.assertTrue(v == -1);
686
687 int cMa = bt.mismatch(cs, as);
688 int aMc = bt.mismatch(as, cs);
689 Assert.assertEquals(cMa, aMc);
690 Assert.assertEquals(cMa, i - aFrom);
691 }
692 }
693 }
694 }
695 }
696 }
697 }
698
699 static int[] ranges(int from, int to) {
700 int width = to - from;
701 switch (width) {
702 case 0:
703 return new int[]{};
704 case 1:
705 return new int[]{from, to};
706 case 2:
707 return new int[]{from, from + 1, to};
708 case 3:
709 return new int[]{from, from + 1, from + 2, to};
710 default:
|