Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/nio/Buffer/EqualsCompareTest.java
41149 views
1
/*
2
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import org.testng.Assert;
25
import org.testng.annotations.DataProvider;
26
import org.testng.annotations.Test;
27
28
import java.lang.invoke.MethodHandle;
29
import java.lang.invoke.MethodHandles;
30
import java.lang.invoke.MethodType;
31
import java.nio.Buffer;
32
import java.nio.ByteBuffer;
33
import java.nio.ByteOrder;
34
import java.nio.CharBuffer;
35
import java.nio.DoubleBuffer;
36
import java.nio.FloatBuffer;
37
import java.nio.IntBuffer;
38
import java.nio.LongBuffer;
39
import java.nio.ShortBuffer;
40
import java.util.HashMap;
41
import java.util.Map;
42
import java.util.function.BiFunction;
43
import java.util.function.LongFunction;
44
import java.util.stream.IntStream;
45
46
/*
47
* @test
48
* @bug 8193085 8199773
49
* @summary tests for buffer equals and compare
50
* @run testng EqualsCompareTest
51
*/
52
53
public class EqualsCompareTest {
54
55
// Maximum width in bits
56
static final int MAX_WIDTH = 512;
57
58
static final Map<Class, Integer> typeToWidth;
59
60
static {
61
typeToWidth = new HashMap<>();
62
typeToWidth.put(byte.class, Byte.SIZE);
63
typeToWidth.put(short.class, Short.SIZE);
64
typeToWidth.put(char.class, Character.SIZE);
65
typeToWidth.put(int.class, Integer.SIZE);
66
typeToWidth.put(long.class, Long.SIZE);
67
typeToWidth.put(float.class, Float.SIZE);
68
typeToWidth.put(double.class, Double.SIZE);
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
124
@SuppressWarnings("unchecked")
125
T slice(T a, int from, int to, boolean dupOtherwiseSlice) {
126
a = (T) a.position(from).limit(to);
127
return (T) (dupOtherwiseSlice ? a.duplicate() : a.slice());
128
}
129
130
@SuppressWarnings("unchecked")
131
E get(T a, int i) {
132
try {
133
return (E) getter.invoke(a, i);
134
}
135
catch (RuntimeException | Error e) {
136
throw e;
137
}
138
catch (Throwable t) {
139
throw new Error(t);
140
}
141
}
142
143
void set(T a, int i, Object v) {
144
try {
145
setter.invoke(a, i, convert(v));
146
}
147
catch (RuntimeException | Error e) {
148
throw e;
149
}
150
catch (Throwable t) {
151
throw new Error(t);
152
}
153
}
154
155
abstract Object convert(Object o);
156
157
boolean equals(T a, T b) {
158
try {
159
return (boolean) eq.invoke(a, b);
160
}
161
catch (RuntimeException | Error e) {
162
throw e;
163
}
164
catch (Throwable t) {
165
throw new Error(t);
166
}
167
}
168
169
int compare(T a, T b) {
170
try {
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
223
? ((Integer) o).byteValue()
224
: o;
225
}
226
}
227
228
static class Chars extends BufferType<CharBuffer, Character> {
229
Chars(BufferKind k) {
230
super(k, CharBuffer.class, char.class);
231
}
232
233
@Override
234
CharBuffer construct(int length, ByteOrder bo) {
235
switch (k) {
236
case DIRECT:
237
return ByteBuffer.allocateDirect(length * Character.BYTES).
238
order(bo).
239
asCharBuffer();
240
case HEAP_VIEW:
241
return ByteBuffer.allocate(length * Character.BYTES).
242
order(bo).
243
asCharBuffer();
244
default:
245
case HEAP:
246
return CharBuffer.allocate(length);
247
}
248
}
249
250
@Override
251
Object convert(Object o) {
252
return o instanceof Integer
253
? (char) ((Integer) o).intValue()
254
: o;
255
}
256
257
CharBuffer transformToStringBuffer(CharBuffer c) {
258
char[] chars = new char[c.remaining()];
259
c.get(chars);
260
return CharBuffer.wrap(new String(chars));
261
}
262
}
263
264
static class Shorts extends BufferType<ShortBuffer, Short> {
265
Shorts(BufferKind k) {
266
super(k, ShortBuffer.class, short.class);
267
}
268
269
@Override
270
ShortBuffer construct(int length, ByteOrder bo) {
271
switch (k) {
272
case DIRECT:
273
return ByteBuffer.allocateDirect(length * Short.BYTES).
274
order(bo).
275
asShortBuffer();
276
case HEAP_VIEW:
277
return ByteBuffer.allocate(length * Short.BYTES).
278
order(bo).
279
asShortBuffer();
280
default:
281
case HEAP:
282
return ShortBuffer.allocate(length);
283
}
284
}
285
286
@Override
287
Object convert(Object o) {
288
return o instanceof Integer
289
? ((Integer) o).shortValue()
290
: o;
291
}
292
}
293
294
static class Ints extends BufferType<IntBuffer, Integer> {
295
Ints(BufferKind k) {
296
super(k, IntBuffer.class, int.class);
297
}
298
299
@Override
300
IntBuffer construct(int length, ByteOrder bo) {
301
switch (k) {
302
case DIRECT:
303
return ByteBuffer.allocateDirect(length * Integer.BYTES).
304
order(bo).
305
asIntBuffer();
306
case HEAP_VIEW:
307
return ByteBuffer.allocate(length * Integer.BYTES).
308
order(bo).
309
asIntBuffer();
310
default:
311
case HEAP:
312
return IntBuffer.allocate(length);
313
}
314
}
315
316
Object convert(Object o) {
317
return o;
318
}
319
}
320
321
static class Floats extends BufferType<FloatBuffer, Float> {
322
Floats(BufferKind k) {
323
super(k, FloatBuffer.class, float.class);
324
}
325
326
@Override
327
FloatBuffer construct(int length, ByteOrder bo) {
328
switch (k) {
329
case DIRECT:
330
return ByteBuffer.allocateDirect(length * Float.BYTES).
331
order(bo).
332
asFloatBuffer();
333
case HEAP_VIEW:
334
return ByteBuffer.allocate(length * Float.BYTES).
335
order(bo).
336
asFloatBuffer();
337
default:
338
case HEAP:
339
return FloatBuffer.allocate(length);
340
}
341
}
342
343
@Override
344
Object convert(Object o) {
345
return o instanceof Integer
346
? ((Integer) o).floatValue()
347
: o;
348
}
349
350
@Override
351
boolean pairWiseEquals(FloatBuffer a, FloatBuffer b) {
352
if (a.remaining() != b.remaining())
353
return false;
354
int p = a.position();
355
for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--) {
356
float av = a.get(i);
357
float bv = b.get(j);
358
if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv)))
359
return false;
360
}
361
return true;
362
}
363
}
364
365
static class Longs extends BufferType<LongBuffer, Long> {
366
Longs(BufferKind k) {
367
super(k, LongBuffer.class, long.class);
368
}
369
370
@Override
371
LongBuffer construct(int length, ByteOrder bo) {
372
switch (k) {
373
case DIRECT:
374
return ByteBuffer.allocateDirect(length * Long.BYTES).
375
order(bo).
376
asLongBuffer();
377
case HEAP_VIEW:
378
return ByteBuffer.allocate(length * Long.BYTES).
379
order(bo).
380
asLongBuffer();
381
default:
382
case HEAP:
383
return LongBuffer.allocate(length);
384
}
385
}
386
387
@Override
388
Object convert(Object o) {
389
return o instanceof Integer
390
? ((Integer) o).longValue()
391
: o;
392
}
393
}
394
395
static class Doubles extends BufferType<DoubleBuffer, Double> {
396
Doubles(BufferKind k) {
397
super(k, DoubleBuffer.class, double.class);
398
}
399
400
@Override
401
DoubleBuffer construct(int length, ByteOrder bo) {
402
switch (k) {
403
case DIRECT:
404
return ByteBuffer.allocateDirect(length * Double.BYTES).
405
order(bo).
406
asDoubleBuffer();
407
case HEAP_VIEW:
408
return ByteBuffer.allocate(length * Double.BYTES).
409
order(bo).
410
asDoubleBuffer();
411
default:
412
case HEAP:
413
return DoubleBuffer.allocate(length);
414
}
415
}
416
417
@Override
418
Object convert(Object o) {
419
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)},
460
{new BufferType.Longs(BufferKind.HEAP)},
461
{new BufferType.Longs(BufferKind.HEAP_VIEW)},
462
{new BufferType.Longs(BufferKind.DIRECT)},
463
{new BufferType.Doubles(BufferKind.HEAP)},
464
{new BufferType.Doubles(BufferKind.HEAP_VIEW)},
465
{new BufferType.Doubles(BufferKind.DIRECT)},
466
};
467
}
468
return bufferTypes;
469
}
470
471
472
static Object[][] floatbufferTypes;
473
474
@DataProvider
475
public static Object[][] floatBufferTypesProvider() {
476
if (floatbufferTypes == null) {
477
LongFunction<Object> bTof = rb -> Float.intBitsToFloat((int) rb);
478
LongFunction<Object> bToD = Double::longBitsToDouble;
479
480
floatbufferTypes = new Object[][]{
481
// canonical and non-canonical NaNs
482
// If conversion is a signalling NaN it may be subject to conversion to a
483
// quiet NaN on some processors, even if a copy is performed
484
// The tests assume that if conversion occurs it does not convert to the
485
// canonical NaN
486
new Object[]{new BufferType.Floats(BufferKind.HEAP), 0x7fc00000L, 0x7f800001L, bTof},
487
new Object[]{new BufferType.Floats(BufferKind.HEAP_VIEW), 0x7fc00000L, 0x7f800001L, bTof},
488
new Object[]{new BufferType.Floats(BufferKind.DIRECT), 0x7fc00000L, 0x7f800001L, bTof},
489
new Object[]{new BufferType.Doubles(BufferKind.HEAP), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD},
490
new Object[]{new BufferType.Doubles(BufferKind.HEAP_VIEW), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD},
491
new Object[]{new BufferType.Doubles(BufferKind.DIRECT), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD},
492
493
// +0.0 and -0.0
494
new Object[]{new BufferType.Floats(BufferKind.HEAP), 0x0L, 0x80000000L, bTof},
495
new Object[]{new BufferType.Floats(BufferKind.HEAP_VIEW), 0x0L, 0x80000000L, bTof},
496
new Object[]{new BufferType.Floats(BufferKind.DIRECT), 0x0L, 0x80000000L, bTof},
497
new Object[]{new BufferType.Doubles(BufferKind.HEAP), 0x0L, 0x8000000000000000L, bToD},
498
new Object[]{new BufferType.Doubles(BufferKind.HEAP_VIEW), 0x0L, 0x8000000000000000L, bToD},
499
new Object[]{new BufferType.Doubles(BufferKind.DIRECT), 0x0L, 0x8000000000000000L, bToD},
500
};
501
}
502
return floatbufferTypes;
503
}
504
505
506
static Object[][] charBufferTypes;
507
508
@DataProvider
509
public static Object[][] charBufferTypesProvider() {
510
if (charBufferTypes == null) {
511
charBufferTypes = new Object[][]{
512
{new BufferType.Chars(BufferKind.HEAP)},
513
{new BufferType.Chars(BufferKind.HEAP_VIEW)},
514
{new BufferType.Chars(BufferKind.DIRECT)},
515
};
516
}
517
return charBufferTypes;
518
}
519
520
521
// Tests all primitive buffers
522
@Test(dataProvider = "bufferTypesProvider")
523
<E>
524
void testBuffers(BufferType<Buffer, E> bufferType) {
525
// Test with buffers of the same byte order (BE)
526
BiFunction<BufferType<Buffer, E>, Integer, Buffer> constructor = (at, s) -> {
527
Buffer a = at.construct(s);
528
for (int x = 0; x < s; x++) {
529
at.set(a, x, x % 8);
530
}
531
return a;
532
};
533
534
testBufferType(bufferType, constructor, constructor);
535
536
// Test with buffers of different byte order
537
if (bufferType.elementType != byte.class &&
538
(bufferType.k == BufferKind.HEAP_VIEW ||
539
bufferType.k == BufferKind.DIRECT)) {
540
541
BiFunction<BufferType<Buffer, E>, Integer, Buffer> leConstructor = (at, s) -> {
542
Buffer a = at.construct(s, ByteOrder.LITTLE_ENDIAN);
543
for (int x = 0; x < s; x++) {
544
at.set(a, x, x % 8);
545
}
546
return a;
547
};
548
testBufferType(bufferType, constructor, leConstructor);
549
}
550
}
551
552
// Tests float and double buffers with edge-case values (NaN, -0.0, +0.0)
553
@Test(dataProvider = "floatBufferTypesProvider")
554
public void testFloatBuffers(
555
BufferType<Buffer, Float> bufferType,
556
long rawBitsA, long rawBitsB,
557
LongFunction<Object> bitsToFloat) {
558
Object av = bitsToFloat.apply(rawBitsA);
559
Object bv = bitsToFloat.apply(rawBitsB);
560
561
BiFunction<BufferType<Buffer, Float>, Integer, Buffer> allAs = (at, s) -> {
562
Buffer b = at.construct(s);
563
for (int x = 0; x < s; x++) {
564
at.set(b, x, av);
565
}
566
return b;
567
};
568
569
BiFunction<BufferType<Buffer, Float>, Integer, Buffer> allBs = (at, s) -> {
570
Buffer b = at.construct(s);
571
for (int x = 0; x < s; x++) {
572
at.set(b, x, bv);
573
}
574
return b;
575
};
576
577
BiFunction<BufferType<Buffer, Float>, Integer, Buffer> halfBs = (at, s) -> {
578
Buffer b = at.construct(s);
579
for (int x = 0; x < s / 2; x++) {
580
at.set(b, x, bv);
581
}
582
for (int x = s / 2; x < s; x++) {
583
at.set(b, x, 1);
584
}
585
return b;
586
};
587
588
// Sanity check
589
int size = arraySizeFor(bufferType.elementType);
590
Assert.assertTrue(bufferType.pairWiseEquals(allAs.apply(bufferType, size),
591
allBs.apply(bufferType, size)));
592
Assert.assertTrue(bufferType.equals(allAs.apply(bufferType, size),
593
allBs.apply(bufferType, size)));
594
595
testBufferType(bufferType, allAs, allBs);
596
testBufferType(bufferType, allAs, halfBs);
597
}
598
599
// Tests CharBuffer for region sources and CharSequence sources
600
@Test(dataProvider = "charBufferTypesProvider")
601
public void testCharBuffers(BufferType.Chars charBufferType) {
602
603
BiFunction<BufferType.Chars, Integer, CharBuffer> constructor = (at, s) -> {
604
CharBuffer a = at.construct(s);
605
for (int x = 0; x < s; x++) {
606
at.set(a, x, x % 8);
607
}
608
return a;
609
};
610
611
BiFunction<BufferType.Chars, Integer, CharBuffer> constructorX = constructor.
612
andThen(charBufferType::transformToStringBuffer);
613
614
testBufferType(charBufferType, constructor, constructorX);
615
}
616
617
618
<B extends Buffer, E, BT extends BufferType<B, E>>
619
void testBufferType(BT bt,
620
BiFunction<BT, Integer, B> aConstructor,
621
BiFunction<BT, Integer, B> bConstructor) {
622
int n = arraySizeFor(bt.elementType);
623
624
for (boolean dupOtherwiseSlice : new boolean[]{ false, true }) {
625
for (int s : ranges(0, n)) {
626
B a = aConstructor.apply(bt, s);
627
B b = bConstructor.apply(bt, s);
628
629
for (int aFrom : ranges(0, s)) {
630
for (int aTo : ranges(aFrom, s)) {
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:
711
return IntStream.of(from, from + 1, from + 2, to / 2 - 1, to / 2, to / 2 + 1, to - 2, to - 1, to)
712
.filter(i -> i >= from && i <= to)
713
.distinct().toArray();
714
}
715
}
716
}
717
718