11package com .scalableminds .zarrjava .indexing ;
22
3+ import com .scalableminds .zarrjava .v3 .Utils ;
4+ import ucar .ma2 .Array ;
5+ import ucar .ma2 .IndexIterator ;
6+ import ucar .ma2 .InvalidRangeException ;
7+ import ucar .ma2 .Range ;
8+
9+ import java .util .ArrayList ;
310import java .util .Arrays ;
411
512public class Indexer {
6- public static long [][] computeChunkCoords (long [] shape , int [] chunkShape , int [] bufferShape , long [] offset ) {
7- final int depth = shape .length ;
8- long [] start = new long [depth ];
9- long [] end = new long [depth ];
13+
14+ public static long [][] computeChunkCoords (long [] arrayShape , int [] chunkShape ) {
15+ return computeChunkCoords (arrayShape , chunkShape , new long [arrayShape .length ], Utils .toIntArray (arrayShape ));
16+ }
17+
18+ public static long [][] computeChunkCoords (int [] arrayShape , int [] chunkShape ) {
19+ return computeChunkCoords (Utils .toLongArray (arrayShape ), chunkShape );
20+ }
21+
22+ public static long [][] computeChunkCoords (long [] arrayShape , int [] chunkShape , long [] selOffset , int [] selShape ) {
23+ final int ndim = arrayShape .length ;
24+ long [] start = new long [ndim ];
25+ long [] end = new long [ndim ];
1026 int numChunks = 1 ;
11- for (int i = 0 ; i < depth ; i ++) {
12- final int staIdx = (int )( offset [ i ] / chunkShape [i ]);
13- final int endIdx = (int )(( offset [ i ] + bufferShape [ i ] - 1 ) / chunkShape [i ]);
27+ for (int dimIdx = 0 ; dimIdx < ndim ; dimIdx ++) {
28+ final int staIdx = (int ) ( selOffset [ dimIdx ] / chunkShape [dimIdx ]);
29+ final int endIdx = (int ) (( selOffset [ dimIdx ] + selShape [ dimIdx ] - 1 ) / chunkShape [dimIdx ]);
1430 numChunks *= (endIdx - staIdx + 1 );
15- start [i ] = staIdx ;
16- end [i ] = endIdx ;
31+ start [dimIdx ] = staIdx ;
32+ end [dimIdx ] = endIdx ;
1733 }
1834
19- final long [][] chunkIndices = new long [numChunks ][];
35+ final long [][] chunkCoords = new long [numChunks ][];
2036
21- final long [] currentIdx = Arrays .copyOf (start , depth );
22- for (int i = 0 ; i < chunkIndices .length ; i ++) {
23- chunkIndices [i ] = Arrays .copyOf (currentIdx , depth );
24- int depthIdx = depth - 1 ;
25- while (depthIdx >= 0 ) {
26- if (currentIdx [depthIdx ] >= end [depthIdx ]) {
27- currentIdx [depthIdx ] = start [depthIdx ];
28- depthIdx --;
37+ final long [] currentIdx = Arrays .copyOf (start , ndim );
38+ for (int i = 0 ; i < chunkCoords .length ; i ++) {
39+ chunkCoords [i ] = Arrays .copyOf (currentIdx , ndim );
40+ int dimIdx = ndim - 1 ;
41+ while (dimIdx >= 0 ) {
42+ if (currentIdx [dimIdx ] >= end [dimIdx ]) {
43+ currentIdx [dimIdx ] = start [dimIdx ];
44+ dimIdx --;
2945 } else {
30- currentIdx [depthIdx ]++;
31- depthIdx = -1 ;
46+ currentIdx [dimIdx ]++;
47+ dimIdx = -1 ;
3248 }
3349 }
3450 }
35- return chunkIndices ;
51+ return chunkCoords ;
52+ }
53+
54+ public static ChunkProjection computeProjection (long [] chunkCoords , int [] arrayShape , int [] chunkShape ) {
55+ return computeProjection (chunkCoords , Utils .toLongArray (arrayShape ), chunkShape );
56+ }
57+
58+ public static ChunkProjection computeProjection (long [] chunkCoords , long [] arrayShape , int [] chunkShape ) {
59+ return computeProjection (chunkCoords , arrayShape , chunkShape , new long [chunkCoords .length ],
60+ Utils .toIntArray (arrayShape ));
61+ }
62+
63+ public static ChunkProjection computeProjection (long [] chunkCoords , long [] arrayShape , int [] chunkShape , long [] selOffset , int [] selShape ) {
64+ int ndim = chunkCoords .length ;
65+ int [] chunkOffset = new int [ndim ];
66+ int [] outOffset = new int [ndim ];
67+ int [] shape = new int [ndim ];
68+
69+ for (int dimIdx = 0 ; dimIdx < chunkCoords .length ; dimIdx ++) {
70+ // compute offsets for chunk within overall array
71+ long dimOffset = (long ) chunkShape [dimIdx ] * chunkCoords [dimIdx ];
72+ long dimLimit = Math .min (arrayShape [dimIdx ], (chunkCoords [dimIdx ] + 1 ) * (long ) chunkShape [dimIdx ]);
73+ // determine chunk length, accounting for trailing chunk
74+ long dimChunkLen = dimLimit - dimOffset ;
75+
76+ if (selOffset [dimIdx ] < dimOffset ) {
77+ // selection starts before current chunk
78+ chunkOffset [dimIdx ] = 0 ;
79+ // compute number of previous items, provides offset into output array
80+ outOffset [dimIdx ] = (int ) (dimOffset - selOffset [dimIdx ]);
81+ } else {
82+ // selection starts within current chunk
83+ chunkOffset [dimIdx ] = (int ) (selOffset [dimIdx ] - dimOffset );
84+ outOffset [dimIdx ] = 0 ;
85+ }
86+
87+ if (selOffset [dimIdx ] + selShape [dimIdx ] > dimLimit ) {
88+ // selection ends after current chunk
89+ shape [dimIdx ] = (int ) (chunkShape [dimIdx ] - selOffset [dimIdx ]);
90+ } else {
91+ // selection ends within current chunk
92+ shape [dimIdx ] = (int ) (selOffset [dimIdx ] + selShape [dimIdx ] - dimOffset - chunkOffset [dimIdx ]);
93+ }
94+ }
95+
96+ return new ChunkProjection (chunkCoords , chunkOffset , outOffset , shape );
97+ }
98+
99+ public static void copyRegion (Array source , int [] sourceOffset , Array target , int [] targetOffset , int [] shape ) {
100+ assert sourceOffset .length == targetOffset .length ;
101+ assert source .getRank () == sourceOffset .length ;
102+ assert target .getRank () == targetOffset .length ;
103+ assert shape .length == sourceOffset .length ;
104+
105+ try {
106+ final ArrayList <Range > sourceRanges = new ArrayList <>();
107+ final ArrayList <Range > targetRanges = new ArrayList <>();
108+ for (int dimIdx = 0 ; dimIdx < shape .length ; dimIdx ++) {
109+ assert sourceOffset [dimIdx ] + shape [dimIdx ] <= source .getShape ()[dimIdx ];
110+ assert targetOffset [dimIdx ] + shape [dimIdx ] <= target .getShape ()[dimIdx ];
111+
112+ sourceRanges .add (new Range (sourceOffset [dimIdx ], sourceOffset [dimIdx ] + shape [dimIdx ] - 1 ));
113+ targetRanges .add (new Range (targetOffset [dimIdx ], targetOffset [dimIdx ] + shape [dimIdx ] - 1 ));
114+ }
115+ final IndexIterator sourceRangeIterator = source .getRangeIterator (sourceRanges );
116+ final IndexIterator targetRangeIterator = target .getRangeIterator (targetRanges );
117+ final Class elementType = source .getElementType ();
118+ ValueSetter setter = createValueSetter (elementType );
119+ while (sourceRangeIterator .hasNext ()) {
120+ setter .set (sourceRangeIterator , targetRangeIterator );
121+ }
122+ } catch (InvalidRangeException ex ) {
123+ throw new RuntimeException ("Unreachable" );
124+ }
125+ }
126+
127+ private static ValueSetter createValueSetter (Class elementType ) {
128+ if (elementType == double .class ) {
129+ return (sourceIterator , targetIterator ) -> targetIterator .setDoubleNext (sourceIterator .getDoubleNext ());
130+ } else if (elementType == float .class ) {
131+ return (sourceIterator , targetIterator ) -> targetIterator .setFloatNext (sourceIterator .getFloatNext ());
132+ } else if (elementType == long .class ) {
133+ return (sourceIterator , targetIterator ) -> targetIterator .setLongNext (sourceIterator .getLongNext ());
134+ } else if (elementType == int .class ) {
135+ return (sourceIterator , targetIterator ) -> targetIterator .setIntNext (sourceIterator .getIntNext ());
136+ } else if (elementType == short .class ) {
137+ return (sourceIterator , targetIterator ) -> targetIterator .setShortNext (sourceIterator .getShortNext ());
138+ } else if (elementType == byte .class ) {
139+ return (sourceIterator , targetIterator ) -> targetIterator .setByteNext (sourceIterator .getByteNext ());
140+ }
141+ return (sourceIterator , targetIterator ) -> targetIterator .setObjectNext (sourceIterator .getObjectNext ());
142+ }
143+
144+ private interface ValueSetter {
145+
146+ void set (IndexIterator sourceIterator , IndexIterator targetIterator );
147+ }
148+
149+ public static final class ChunkProjection {
150+ public long [] chunkCoords ;
151+ public int [] chunkOffset ;
152+
153+ public int [] outOffset ;
154+ public int [] shape ;
155+
156+ public ChunkProjection (long [] chunkCoords , int [] chunkOffset , int [] outOffset , int [] shape ) {
157+ this .chunkCoords = chunkCoords ;
158+ this .chunkOffset = chunkOffset ;
159+ this .outOffset = outOffset ;
160+ this .shape = shape ;
161+ }
36162 }
37163}
0 commit comments