99@ AllArgsConstructor (access = AccessLevel .PRIVATE )
1010public class RangeSlice implements Slice {
1111 private final int startIndexInclusive ;
12- private final int endIndexExclusive ;
12+ private final Integer endIndexExclusive ;
1313 private final int step ;
1414
15- public static RangeSlice of (final int startIndexInclusive , final int endIndexExclusive , final int step ) {
16- if (startIndexInclusive < 0 ) {
17- throw new IllegalArgumentException ("Cannot slice at start index < 0" );
18- }
19-
20- if (endIndexExclusive < 0 ) {
21- throw new IllegalArgumentException ("Cannot slice at end index < 0" );
22- }
23-
15+ public static RangeSlice of (final int startIndexInclusive , final Integer endIndexExclusive , final int step ) {
2416 if (step < 1 ) {
2517 throw new IllegalArgumentException ("Cannot slice with step < 1" );
2618 }
2719
28- if (startIndexInclusive > endIndexExclusive ) {
29- throw new IllegalArgumentException ("Cannot slice with start index > end index" );
30- }
31-
32- if (endIndexExclusive == startIndexInclusive ) {
33- throw new IllegalArgumentException ("Empty slice" );
34- }
35-
3620 return new RangeSlice (startIndexInclusive , endIndexExclusive , step );
3721 }
3822
39- public static RangeSlice of (final int startIndexInclusive , final int endIndexExclusive ) {
23+ public static RangeSlice of (final int startIndexInclusive , final Integer endIndexExclusive ) {
4024 return of (startIndexInclusive , endIndexExclusive , 1 );
4125 }
4226
4327 @ Override
4428 public void validate (final int originalLength ) {
45- if (startIndexInclusive >= originalLength || endIndexExclusive > originalLength ) {
29+ final int resolvedStartIndexInclusive = resolveIndex (originalLength , startIndexInclusive );
30+ final int resolvedEndIndexInclusive = resolveIndex (originalLength , endIndexExclusive );
31+
32+ if (resolvedStartIndexInclusive < 0 || resolvedStartIndexInclusive >= originalLength || resolvedEndIndexInclusive < 0 || resolvedEndIndexInclusive > originalLength ) {
4633 throw new IllegalArgumentException (
4734 String .format (
4835 "%s out of range for dimension of length %d" ,
@@ -51,20 +38,42 @@ public void validate(final int originalLength) {
5138 )
5239 );
5340 }
41+
42+ if (resolvedEndIndexInclusive <= resolvedStartIndexInclusive ) {
43+ throw new IllegalArgumentException (
44+ String .format (
45+ "%s is empty interval for dimension of length %d" ,
46+ this ,
47+ originalLength
48+ )
49+ );
50+ }
5451 }
5552
5653 @ Override
57- public int computeNewOffset (final int originalOffset , final int originalStride ) {
58- return originalOffset + startIndexInclusive * originalStride ;
54+ public int computeNewOffset (final int originalLength , final int originalOffset , final int originalStride ) {
55+ return originalOffset + resolveIndex ( originalLength , startIndexInclusive ) * originalStride ;
5956 }
6057
6158 @ Override
6259 public int computeNewLength (final int originalLength ) {
63- return (endIndexExclusive - startIndexInclusive ) / step ;
60+ return (resolveIndex ( originalLength , endIndexExclusive ) - resolveIndex ( originalLength , startIndexInclusive ) ) / step ;
6461 }
6562
6663 @ Override
6764 public int computeNewStride (final int originalStride ) {
6865 return originalStride * step ;
6966 }
67+
68+ private int resolveIndex (final int length , final Integer index ) {
69+ if (index == null ) {
70+ return length ;
71+ }
72+
73+ if (index >= 0 ) {
74+ return index ;
75+ }
76+
77+ return length + index ;
78+ }
7079}
0 commit comments