1 /*
2 * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
3 * University Research and Technology
4 * Corporation. All rights reserved.
5 * Copyright (c) 2004-2005 The University of Tennessee and The University
6 * of Tennessee Research Foundation. All rights
7 * reserved.
8 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9 * University of Stuttgart. All rights reserved.
10 * Copyright (c) 2004-2005 The Regents of the University of California.
11 * All rights reserved.
12 * Copyright (c) 2015 Los Alamos National Security, LLC. All rights
13 * reserved.
14 * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved.
15 * $COPYRIGHT$
16 *
17 * Additional copyrights may follow
18 *
19 * $HEADER$
20 *
21 *
22 * This file is almost a complete re-write for Open MPI compared to the
23 * original mpiJava package. Its license and copyright are listed below.
24 * See <path to ompi/mpi/java/README> for more information.
25 *
26 *
27 * Licensed under the Apache License, Version 2.0 (the "License");
28 * you may not use this file except in compliance with the License.
29 * You may obtain a copy of the License at
30 *
31 * http://www.apache.org/licenses/LICENSE-2.0
32 *
33 * Unless required by applicable law or agreed to in writing, software
34 * distributed under the License is distributed on an "AS IS" BASIS,
35 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36 * See the License for the specific language governing permissions and
37 * limitations under the License.
38 *
39 *
40 * File : Datatype.java
41 * Author : Sang Lim, Sung-Hoon Ko, Xinying Li, Bryan Carpenter
42 * Created : Thu Apr 9 12:22:15 1998
43 * Revision : $Revision: 1.14 $
44 * Updated : $Date: 2003/01/16 16:39:34 $
45 * Copyright: Northeast Parallel Architectures Center
46 * at Syracuse University 1998
47 */
48
49 package mpi;
50
51 import java.nio.*;
52
53 /**
54 * The {@code Datatype} class represents {@code MPI_Datatype} handles.
55 */
56 public final class Datatype implements Freeable, Cloneable
57 {
58 protected long handle;
59 protected int baseType;
60 protected int baseSize;
61
62 // Cache to avoid unnecessary jni calls.
63 private int lb, extent, trueLb, trueExtent;
64
65 protected static final int NULL = 0;
66 protected static final int BYTE = 1;
67 protected static final int CHAR = 2;
68 protected static final int SHORT = 3;
69 protected static final int BOOLEAN = 4;
70 protected static final int INT = 5;
71 protected static final int LONG = 6;
72 protected static final int FLOAT = 7;
73 protected static final int DOUBLE = 8;
74 protected static final int PACKED = 9;
75 protected static final int INT2 = 10;
76 protected static final int SHORT_INT = 11;
77 protected static final int LONG_INT = 12;
78 protected static final int FLOAT_INT = 13;
79 protected static final int DOUBLE_INT = 14;
80 protected static final int FLOAT_COMPLEX = 15;
81 protected static final int DOUBLE_COMPLEX = 16;
82
83 static
84 {
85 init();
86 }
87
88 private static native void init();
89
90 /*
91 * Constructor used in static initializer of 'MPI'.
92 *
93 * (Called before MPI.Init(), so cannot make any native MPI calls.)
94 *
95 * (Initialization done in separate 'setBasic', so can create
96 * datatype objects for 'BYTE', etc in static initializers invoked before
97 * MPI.Init(), then initialize objects after MPI initialized.)
98 */
99 protected Datatype()
100 {
101 }
102
103 protected void setBasic(int type)
104 {
105 baseType = type;
106 handle = getDatatype(type);
107 baseSize = type == NULL ? 0 : getSize(handle);
108 }
109
110 protected void setBasic(int type, Datatype oldType)
111 {
112 baseType = oldType.baseType;
113 handle = getDatatype(type);
114 baseSize = oldType.baseSize;
115 }
116
117 private static native long getDatatype(int type);
118
119 /*
120 * Constructor used in 'create*' methods.
121 */
122 private Datatype(Datatype oldType, long handle)
123 {
124 baseType = oldType.baseType;
125 baseSize = oldType.baseSize;
126 this.handle = handle;
127 }
128
129 /*
130 * Constructor used in 'create*' methods.
131 */
132 private Datatype(int baseType, int baseSize, long handle)
133 {
134 this.baseType = baseType;
135 this.baseSize = baseSize;
136 this.handle = handle;
137 }
138
139 /**
140 * Returns the lower bound of a datatype.
141 * <p>Java binding of the MPI operation {@code MPI_TYPE_GET_EXTENT}.
142 * @return lower bound of datatype
143 * @throws MPIException Signals that an MPI exception of some sort has occurred.
144 */
145 public int getLb() throws MPIException
146 {
147 if(extent == 0)
148 getLbExtent();
149
150 return lb;
151 }
152
153 /**
154 * Returns the extent of a datatype.
155 * <p>Java binding of the MPI operation {@code MPI_TYPE_GET_EXTENT}.
156 * @return datatype extent
157 * @throws MPIException Signals that an MPI exception of some sort has occurred.
158 */
159 public int getExtent() throws MPIException
160 {
161 if(extent == 0)
162 getLbExtent();
163
164 return extent;
165 }
166
167 private void getLbExtent() throws MPIException
168 {
169 MPI.check();
170 int lbExt[] = new int[2];
171 getLbExtent(handle, lbExt);
172 lb = lbExt[0] / baseSize;
173 extent = lbExt[1] / baseSize;
174 }
175
176 private native void getLbExtent(long handle, int[] lbExt);
177
178 /**
179 * Returns the true lower bound of a datatype.
180 * <p>Java binding of the MPI operation {@code MPI_TYPE_GET_TRUE_EXTENT}.
181 * @return lower bound of datatype
182 * @throws MPIException Signals that an MPI exception of some sort has occurred.
183 */
184 public int getTrueLb() throws MPIException
185 {
186 if(trueExtent == 0)
187 getTrueLbExtent();
188
189 return trueLb;
190 }
191
192 /**
193 * Returns the true extent of a datatype.
194 * <p>Java binding of the MPI operation {@code MPI_TYPE_GET_TRUE_EXTENT}.
195 * @return datatype true extent
196 * @throws MPIException Signals that an MPI exception of some sort has occurred.
197 */
198 public int getTrueExtent() throws MPIException
199 {
200 if(trueExtent == 0)
201 getTrueLbExtent();
202
203 return trueExtent;
204 }
205
206 private void getTrueLbExtent() throws MPIException
207 {
208 MPI.check();
209 int lbExt[] = new int[2];
210 getTrueLbExtent(handle, lbExt);
211 trueLb = lbExt[0] / baseSize;
212 trueExtent = lbExt[1] / baseSize;
213 }
214
215 private native void getTrueLbExtent(long handle, int[] lbExt);
216
217 /**
218 * Returns the total size of a datatype - the number of buffer
219 * elements it represents.
220 * <p>Java binding of the MPI operation {@code MPI_TYPE_SIZE}.
221 * @return datatype size
222 * @throws MPIException Signals that an MPI exception of some sort has occurred.
223 */
224 public int getSize() throws MPIException
225 {
226 MPI.check();
227 return getSize(handle) / baseSize;
228 }
229
230 private native int getSize(long type);
231
232 /**
233 * Commits a derived datatype.
234 * Java binding of the MPI operation {@code MPI_TYPE_COMMIT}.
235 * @throws MPIException Signals that an MPI exception of some sort has occurred.
236 */
237 public void commit() throws MPIException
238 {
239 MPI.check();
240 commit(handle);
241 }
242
243 private native void commit(long type);
244
245 /**
246 * Frees the datatype.
247 * <p>Java binding of the MPI operation {@code MPI_TYPE_FREE}.
248 * @throws MPIException Signals that an MPI exception of some sort has occurred.
249 */
250 @Override public void free() throws MPIException
251 {
252 MPI.check();
253 handle = free(handle);
254 }
255
256 private native long free(long type) throws MPIException;
257
258 /**
259 * Returns {@code true} if this datatype is MPI_DATATYPE_NULL.
260 * @return {@code true} if this datatype is MPI_DATATYPE_NULL
261 */
262 public boolean isNull()
263 {
264 return handle == MPI.DATATYPE_NULL.handle;
265 }
266
267 /**
268 * Java binding of {@code MPI_TYPE_DUP}.
269 * <p>It is recommended to use {@link #dup} instead of {@link #clone}
270 * because the last can't throw an {@link mpi.MPIException}.
271 * @return new datatype
272 */
273 @Override public Datatype clone()
274 {
275 try
276 {
277 return dup();
278 }
279 catch(MPIException e)
280 {
281 throw new RuntimeException(e.getMessage());
282 }
283 }
284
285 /**
286 * Java binding of {@code MPI_TYPE_DUP}.
287 * @return new datatype
288 * @throws MPIException Signals that an MPI exception of some sort has occurred.
289 */
290 public Datatype dup() throws MPIException
291 {
292 MPI.check();
293 return new Datatype(this, dup(handle));
294 }
295
296 private native long dup(long type) throws MPIException;
297
298 /**
299 * Construct new datatype representing replication of old datatype into
300 * contiguous locations.
301 * <p>Java binding of the MPI operation {@code MPI_TYPE_CONTIGUOUS}.
302 * <p>The base type of the new datatype is the same as the base type of
303 * {@code oldType}.
304 * @param count replication count
305 * @param oldType old datatype
306 * @return new datatype
307 * @throws MPIException Signals that an MPI exception of some sort has occurred.
308 */
309 public static Datatype createContiguous(int count, Datatype oldType)
310 throws MPIException
311 {
312 MPI.check();
313 return new Datatype(oldType, getContiguous(count, oldType.handle));
314 }
315
316 private static native long getContiguous(int count, long oldType);
317
318 /**
319 * Construct new datatype representing replication of old datatype into
320 * locations that consist of equally spaced blocks.
321 * <p>Java binding of the MPI operation {@code MPI_TYPE_VECTOR}.
322 * <p>The base type of the new datatype is the same as the base type of
323 * {@code oldType}.
324 * @param count number of blocks
325 * @param blockLength number of elements in each block
326 * @param stride number of elements between start of each block
327 * @param oldType old datatype
328 * @return new datatype
329 * @throws MPIException Signals that an MPI exception of some sort has occurred.
330 */
331 public static Datatype createVector(int count, int blockLength,
332 int stride, Datatype oldType)
333 throws MPIException
334 {
335 MPI.check();
336 long handle = getVector(count, blockLength, stride, oldType.handle);
337 return new Datatype(oldType, handle);
338 }
339
340 private static native long getVector(
341 int count, int blockLength, int stride, long oldType)
342 throws MPIException;
343
344 /**
345 * Identical to {@code createVector} except that the stride is expressed
346 * directly in terms of the buffer index, rather than the units of
347 * the old type.
348 * <p>Java binding of the MPI operation {@code MPI_TYPE_CREATE_HVECTOR}.
349 * @param count number of blocks
350 * @param blockLength number of elements in each
351 * @param stride number of bytes between start of each block
352 * @param oldType old datatype
353 * @return new datatype
354 * @throws MPIException Signals that an MPI exception of some sort has occurred.
355 */
356 public static Datatype createHVector(int count, int blockLength,
357 int stride, Datatype oldType)
358 throws MPIException
359 {
360 MPI.check();
361 long handle = getHVector(count, blockLength, stride, oldType.handle);
362 return new Datatype(oldType, handle);
363 }
364
365 private static native long getHVector(
366 int count, int blockLength, int stride, long oldType)
367 throws MPIException;
368
369 /**
370 * Construct new datatype representing replication of old datatype into
371 * a sequence of blocks where each block can contain a different number
372 * of copies and have a different displacement.
373 * <p>Java binding of the MPI operation {@code MPI_TYPE_INDEXED}.
374 * <p>The number of blocks is taken to be size of the {@code blockLengths}
375 * argument. The second argument, {@code displacements}, should be the
376 * same size. The base type of the new datatype is the same as the base
377 * type of {@code oldType}.
378 * @param blockLengths number of elements per block
379 * @param displacements displacement of each block in units of old type
380 * @param oldType old datatype
381 * @return new datatype
382 * @throws MPIException Signals that an MPI exception of some sort has occurred.
383 */
384 public static Datatype createIndexed(int[] blockLengths,
385 int[] displacements, Datatype oldType)
386 throws MPIException
387 {
388 MPI.check();
389 long handle = getIndexed(blockLengths, displacements, oldType.handle);
390 return new Datatype(oldType, handle);
391 }
392
393 private static native long getIndexed(
394 int[] blockLengths, int[] displacements, long oldType)
395 throws MPIException;
396
397 /**
398 * Identical to {@code createIndexed} except that the displacements are
399 * expressed directly in terms of the buffer index, rather than the
400 * units of the old type.
401 * <p>Java binding of the MPI operation {@code MPI_TYPE_CREATE_HINDEXED}.
402 * @param blockLengths number of elements per block
403 * @param displacements byte displacement in buffer for each block
404 * @param oldType old datatype
405 * @return new datatype
406 * @throws MPIException Signals that an MPI exception of some sort has occurred.
407 */
408 public static Datatype createHIndexed(int[] blockLengths,
409 int[] displacements, Datatype oldType)
410 throws MPIException
411 {
412 MPI.check();
413 long handle = getHIndexed(blockLengths, displacements, oldType.handle);
414 return new Datatype(oldType, handle);
415 }
416
417 private static native long getHIndexed(
418 int[] blockLengths, int[] displacements, long oldType)
419 throws MPIException;
420
421 /**
422 * The most general type constructor.
423 * <p>Java binding of the MPI operation {@code MPI_TYPE_CREATE_STRUCT}.
424 * <p>The number of blocks is taken to be size of the {@code blockLengths}
425 * argument. The second and third arguments, {@code displacements},
426 * and {@code types}, should be the same size.
427 * @param blockLengths number of elements in each block
428 * @param displacements byte displacement of each block
429 * @param types type of elements in each block
430 * @return new datatype
431 * @throws MPIException Signals that an MPI exception of some sort has occurred.
432 */
433 public static Datatype createStruct(int[] blockLengths,
434 int[] displacements, Datatype[] types)
435 throws MPIException
436 {
437 MPI.check();
438 long handle = getStruct(blockLengths, displacements, types);
439 return new Datatype(MPI.BYTE, handle);
440 }
441
442 private static native long getStruct(
443 int[] blockLengths, int[] displacements, Datatype[] types)
444 throws MPIException;
445
446 /*
447 * JMS add proper documentation here
448 * JMS int != Aint! This needs to be fixed throughout.
449 */
450 /**
451 * Create a datatype with a new lower bound and extent from an existing
452 * datatype.
453 * <p>Java binding of the MPI operation {@code MPI_TYPE_CREATE_RESIZED}.
454 * @param oldType input datatype
455 * @param lb new lower bound of datatype (address integer)
456 * @param extent new extent of datatype (address integer)
457 * @return new datatype
458 * @throws MPIException Signals that an MPI exception of some sort has occurred.
459 */
460 public static Datatype createResized(Datatype oldType, int lb, int extent)
461 throws MPIException
462 {
463 MPI.check();
464 long handle = getResized(oldType.handle, lb, extent);
465 return new Datatype(oldType, handle);
466 }
467
468 private static native long getResized(long oldType, int lb, int extent);
469
470 /**
471 * Sets the print name for the datatype.
472 * @param name name for the datatype
473 * @throws MPIException Signals that an MPI exception of some sort has occurred.
474 */
475 public void setName(String name) throws MPIException
476 {
477 MPI.check();
478 setName(handle, name);
479 }
480
481 private native void setName(long handle, String name) throws MPIException;
482
483 /**
484 * Return the print name from the datatype.
485 * @return name of the datatype
486 * @throws MPIException Signals that an MPI exception of some sort has occurred.
487 */
488 public String getName() throws MPIException
489 {
490 MPI.check();
491 return getName(handle);
492 }
493
494 private native String getName(long handle) throws MPIException;
495
496 /**
497 * Create a new attribute key.
498 * <p>Java binding of the MPI operation {@code MPI_TYPE_CREATE_KEYVAL}.
499 * @return attribute key for future access
500 * @throws MPIException Signals that an MPI exception of some sort has occurred.
501 */
502 public static int createKeyval() throws MPIException
503 {
504 MPI.check();
505 return createKeyval_jni();
506 }
507
508 private static native int createKeyval_jni() throws MPIException;
509
510 /**
511 * Frees an attribute key.
512 * <p>Java binding of the MPI operation {@code MPI_TYPE_FREE_KEYVAL}.
513 * @param keyval attribute key
514 * @throws MPIException Signals that an MPI exception of some sort has occurred.
515 */
516 public static void freeKeyval(int keyval) throws MPIException
517 {
518 MPI.check();
519 freeKeyval_jni(keyval);
520 }
521
522 private static native void freeKeyval_jni(int keyval) throws MPIException;
523
524 /**
525 * Stores attribute value associated with a key.
526 * <p>Java binding of the MPI operation {@code MPI_TYPE_SET_ATTR}.
527 * @param keyval attribute key
528 * @param value attribute value
529 * @throws MPIException Signals that an MPI exception of some sort has occurred.
530 */
531 public void setAttr(int keyval, Object value) throws MPIException
532 {
533 MPI.check();
534 setAttr(handle, keyval, MPI.attrSet(value));
535 }
536
537 private native void setAttr(long type, int keyval, byte[] value)
538 throws MPIException;
539
540 /**
541 * Retrieves attribute value by key.
542 * <p>Java binding of the MPI operation {@code MPI_TYPE_GET_ATTR}.
543 * @param keyval attribute key
544 * @return attribute value or null if no attribute is associated with the key.
545 * @throws MPIException Signals that an MPI exception of some sort has occurred.
546 */
547 public Object getAttr(int keyval) throws MPIException
548 {
549 MPI.check();
550 Object obj = getAttr(handle, keyval);
551 return obj instanceof byte[] ? MPI.attrGet((byte[])obj) : obj;
552 }
553
554 private native Object getAttr(long type, int keyval) throws MPIException;
555
556 /**
557 * Deletes an attribute value associated with a key.
558 * <p>Java binding of the MPI operation {@code MPI_TYPE_DELETE_ATTR}.
559 * @param keyval attribute key
560 * @throws MPIException Signals that an MPI exception of some sort has occurred.
561 */
562 public void deleteAttr(int keyval) throws MPIException
563 {
564 MPI.check();
565 deleteAttr(handle, keyval);
566 }
567
568 private native void deleteAttr(long type, int keyval) throws MPIException;
569
570 /**
571 * Gets the offset of a buffer in bytes.
572 * @param buffer buffer
573 * @return offset in bytes
574 */
575 protected int getOffset(Object buffer)
576 {
577 return baseSize * ((Buffer)buffer).arrayOffset();
578 }
579
580 } // Datatype