-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathUtils.java
More file actions
144 lines (126 loc) · 4.76 KB
/
Copy pathUtils.java
File metadata and controls
144 lines (126 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package dev.zarr.zarrjava.utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Iterator;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class Utils {
public static ByteBuffer allocateNative(int capacity) {
return ByteBuffer.allocate(capacity)
.order(ByteOrder.nativeOrder());
}
public static ByteBuffer makeByteBuffer(int capacity, Function<ByteBuffer, ByteBuffer> func) {
ByteBuffer buf = ByteBuffer.allocate(capacity)
.order(ByteOrder.LITTLE_ENDIAN);
buf = func.apply(buf);
buf.rewind();
return buf;
}
public static ByteBuffer asByteBuffer(InputStream inputStream) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return ByteBuffer.wrap(buffer.toByteArray());
}
public static long[] toLongArray(int[] array) {
return Arrays.stream(array)
.mapToLong(i -> (long) i)
.toArray();
}
public static int[] toIntArray(long[] array) {
return Arrays.stream(array)
.mapToInt(Math::toIntExact)
.toArray();
}
public static byte[] toArray(ByteBuffer buffer) {
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
return bytes;
}
public static <T> Stream<T> asStream(Iterator<T> sourceIterator) {
Iterable<T> iterable = () -> sourceIterator;
return StreamSupport.stream(iterable.spliterator(), false);
}
public static <T> T[] concatArrays(T[] array1, T[]... arrays) {
if (arrays.length == 0) {
return array1;
}
T[] result = Arrays.copyOf(array1, array1.length + Arrays.stream(arrays)
.mapToInt(a -> a.length)
.sum());
int offset = array1.length;
for (T[] array2 : arrays) {
System.arraycopy(array2, 0, result, offset, array2.length);
offset += array2.length;
}
return result;
}
public static void copyStream(InputStream inputStream, OutputStream outputStream) throws IOException {
byte[] buffer = new byte[4096];
int len;
while ((len = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, len);
}
}
public static boolean isPermutation(int[] array) {
if (array.length == 0) {
return false;
}
int[] arange = new int[array.length];
Arrays.setAll(arange, i -> i);
int[] orderSorted = array.clone();
Arrays.sort(orderSorted);
return Arrays.equals(orderSorted, arange);
}
public static int[] inversePermutation(int[] origin) {
assert isPermutation(origin);
int[] inverse = new int[origin.length];
for (int i = 0; i < origin.length; i++) {
inverse[origin[i]] = i;
}
return inverse;
}
/**
* Calculate default chunk shape when not specified.
* This implements JZarr's ArrayParams.build() logic, targeting chunks of approximately 512 elements.
*
* The algorithm divides each dimension by 512 to determine the number of ~512-sized chunks,
* then calculates chunk sizes that will cover the dimension. Note that the total coverage
* may slightly exceed the dimension size (e.g., for shape=1024, chunks=342 results in
* 3 chunks covering 1026 elements). This is intentional and matches JZarr behavior -
* Zarr handles out-of-bounds gracefully, and the goal is approximate chunk sizes rather
* than perfect tiling.
*
* @param shape the shape of the array
* @return the calculated default chunk shape
*/
public static int[] calculateDefaultChunks(long[] shape) {
int[] chunks = new int[shape.length];
for (int i = 0; i < shape.length; i++) {
long shapeDim = shape[i];
int numChunks = (int) (shapeDim / 512);
if (numChunks > 0) {
int chunkDim = (int) (shapeDim / (numChunks + 1));
if (shapeDim % chunkDim == 0) {
chunks[i] = chunkDim;
} else {
chunks[i] = chunkDim + 1;
}
} else {
// If dimension is smaller than 512, use the full dimension
chunks[i] = (int) shapeDim;
}
}
return chunks;
}
}