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         : MPI.java
41  * Author       : Sang Lim, Sung-Hoon Ko, Xinying Li, Bryan Carpenter
42  *                (contributions from MAEDA Atusi)
43  * Created      : Thu Apr  9 12:22:15 1998
44  * Revision     : $Revision: 1.18 $
45  * Updated      : $Date: 2003/01/16 16:39:34 $
46  * Copyright: Northeast Parallel Architectures Center
47  *            at Syracuse University 1998
48  */
49 package mpi;
50 
51 import java.io.*;
52 import java.nio.*;
53 
54 /**
55  * MPI environment.
56  */
57 public final class MPI
58 {
59 	private static boolean initialized, finalized;
60 	private static byte[] buffer = null; // Buffer allocation
61 	private static final int MAX_PROCESSOR_NAME = 256;
62 	private static final ByteOrder nativeOrder = ByteOrder.nativeOrder();
63 
64 	public static final Intracomm COMM_WORLD, COMM_SELF;
65 
66 	public static final int THREAD_SINGLE, THREAD_FUNNELED, THREAD_SERIALIZED,
67 	THREAD_MULTIPLE;
68 
69 	public static final int GRAPH, DIST_GRAPH, CART;
70 	public static final int ANY_SOURCE, ANY_TAG;
71 
72 	public static final Op MAX, MIN, SUM, PROD, LAND, BAND,
73 	LOR, BOR, LXOR, BXOR, REPLACE, NO_OP;
74 
75 	/**
76 	 * Global minimum operator.
77 	 * <p>{@code MINLOC} and {@link #MAXLOC} can be used with each of the following
78 	 * datatypes: {@link #INT2}, {@link #SHORT_INT}, {@link #LONG_INT},
79 	 * {@link #FLOAT_INT} and {@link #DOUBLE_INT}.
80 	 */
81 	public static final Op MINLOC;
82 
83 	/** Global maximum operator. See {@link #MINLOC}.*/
84 	public static final Op MAXLOC;
85 
86 	public static final Datatype DATATYPE_NULL;
87 
88 	public static final Datatype BYTE, CHAR, SHORT, BOOLEAN,
89 	INT, LONG, FLOAT, DOUBLE, PACKED,
90 	FLOAT_COMPLEX, DOUBLE_COMPLEX;
91 
92 	/** Struct which must be used with {@link #int2}. */
93 	public static final Datatype INT2;
94 	/** Struct which must be used with {@link #shortInt}. */
95 	public static final Datatype SHORT_INT;
96 	/** Struct which must be used with {@link #longInt}. */
97 	public static final Datatype LONG_INT;
98 	/** Struct which must be used with {@link #floatInt}. */
99 	public static final Datatype FLOAT_INT;
100 	/** Struct which must be used with {@link #doubleInt}. */
101 	public static final Datatype DOUBLE_INT;
102 
103 	/** Struct object for {@link #INT2} datatype. */
104 	public static final Int2 int2;
105 	/** Struct object for {@link #SHORT_INT} datatype. */
106 	public static final ShortInt shortInt;
107 	/** Struct object for {@link #LONG_INT} datatype. */
108 	public static final LongInt longInt;
109 	/** Struct object for {@link #FLOAT_INT} datatype. */
110 	public static final FloatInt floatInt;
111 	/** Struct object for {@link #DOUBLE_INT} datatype. */
112 	public static final DoubleInt doubleInt;
113 
114 	public static final Request REQUEST_NULL;
115 	public static final Group GROUP_EMPTY;
116 	public static final Info INFO_ENV, INFO_NULL;
117 
118 	public static final int PROC_NULL;
119 	public static final int UNDEFINED;
120 	public static final int IDENT, CONGRUENT, SIMILAR, UNEQUAL;
121 	public static final int TAG_UB, HOST, IO, WTIME_IS_GLOBAL;
122 
123 	public static final int APPNUM, LASTUSEDCODE, UNIVERSE_SIZE, WIN_BASE,
124 	WIN_SIZE, WIN_DISP_UNIT;
125 
126 	public static final int VERSION, SUBVERSION;
127 	public static final int ROOT, KEYVAL_INVALID, BSEND_OVERHEAD;
128 	public static final int MAX_OBJECT_NAME, MAX_PORT_NAME, MAX_DATAREP_STRING;
129 	public static final int MAX_INFO_KEY, MAX_INFO_VAL;
130 	public static final int ORDER_C, ORDER_FORTRAN;
131 	public static final int DISTRIBUTE_BLOCK, DISTRIBUTE_CYCLIC, DISTRIBUTE_NONE,
132 	DISTRIBUTE_DFLT_DARG;
133 
134 	public static final int MODE_CREATE, MODE_RDONLY, MODE_WRONLY, MODE_RDWR,
135 	MODE_DELETE_ON_CLOSE, MODE_UNIQUE_OPEN, MODE_EXCL,
136 	MODE_APPEND, MODE_SEQUENTIAL;
137 	public static final int DISPLACEMENT_CURRENT;
138 	public static final int SEEK_SET, SEEK_CUR, SEEK_END;
139 
140 	public static final int MODE_NOCHECK, MODE_NOPRECEDE, MODE_NOPUT,
141 	MODE_NOSTORE, MODE_NOSUCCEED;
142 	public static final int LOCK_EXCLUSIVE, LOCK_SHARED;
143 
144 	public static final Errhandler ERRORS_ARE_FATAL, ERRORS_RETURN;
145 
146 	// Error classes and codes
147 	public static final int SUCCESS;
148 	public static final int ERR_BUFFER;
149 	public static final int ERR_COUNT;
150 	public static final int ERR_TYPE;
151 	public static final int ERR_TAG;
152 	public static final int ERR_COMM;
153 	public static final int ERR_RANK;
154 	public static final int ERR_REQUEST;
155 	public static final int ERR_ROOT;
156 	public static final int ERR_GROUP;
157 	public static final int ERR_OP;
158 	public static final int ERR_TOPOLOGY;
159 	public static final int ERR_DIMS;
160 	public static final int ERR_ARG;
161 	public static final int ERR_UNKNOWN;
162 	public static final int ERR_TRUNCATE;
163 	public static final int ERR_OTHER;
164 	public static final int ERR_INTERN;
165 	public static final int ERR_IN_STATUS;
166 	public static final int ERR_PENDING;
167 	public static final int ERR_ACCESS;
168 	public static final int ERR_AMODE;
169 	public static final int ERR_ASSERT;
170 	public static final int ERR_BAD_FILE;
171 	public static final int ERR_BASE;
172 	public static final int ERR_CONVERSION;
173 	public static final int ERR_DISP;
174 	public static final int ERR_DUP_DATAREP;
175 	public static final int ERR_FILE_EXISTS;
176 	public static final int ERR_FILE_IN_USE;
177 	public static final int ERR_FILE;
178 	public static final int ERR_INFO_KEY;
179 	public static final int ERR_INFO_NOKEY;
180 	public static final int ERR_INFO_VALUE;
181 	public static final int ERR_INFO;
182 	public static final int ERR_IO;
183 	public static final int ERR_KEYVAL;
184 	public static final int ERR_LOCKTYPE;
185 	public static final int ERR_NAME;
186 	public static final int ERR_NO_MEM;
187 	public static final int ERR_NOT_SAME;
188 	public static final int ERR_NO_SPACE;
189 	public static final int ERR_NO_SUCH_FILE;
190 	public static final int ERR_PORT;
191 	public static final int ERR_QUOTA;
192 	public static final int ERR_READ_ONLY;
193 	public static final int ERR_RMA_CONFLICT;
194 	public static final int ERR_RMA_SYNC;
195 	public static final int ERR_SERVICE;
196 	public static final int ERR_SIZE;
197 	public static final int ERR_SPAWN;
198 	public static final int ERR_UNSUPPORTED_DATAREP;
199 	public static final int ERR_UNSUPPORTED_OPERATION;
200 	public static final int ERR_WIN;
201 	public static final int ERR_LASTCODE;
202 	public static final int ERR_SYSRESOURCE;
203 
204 	static
205 	{
206 		System.loadLibrary("mpi_java");
207 
208 		DATATYPE_NULL = new Datatype();
209 
210 		BYTE    = new Datatype();
211 		CHAR    = new Datatype();
212 		SHORT   = new Datatype();
213 		BOOLEAN = new Datatype();
214 		INT     = new Datatype();
215 		LONG    = new Datatype();
216 		FLOAT   = new Datatype();
217 		DOUBLE  = new Datatype();
218 		PACKED  = new Datatype();
219 		INT2    = new Datatype();
220 
221 		SHORT_INT  = new Datatype();
222 		LONG_INT   = new Datatype();
223 		FLOAT_INT  = new Datatype();
224 		DOUBLE_INT = new Datatype();
225 		FLOAT_COMPLEX  = new Datatype();
226 		DOUBLE_COMPLEX = new Datatype();
227 
228 		int2      = newInt2();
229 		shortInt  = newShortInt();
230 		longInt   = newLongInt();
231 		floatInt  = newFloatInt();
232 		doubleInt = newDoubleInt();
233 
234 		MAX    = new Op(1);
235 		MIN    = new Op(2);
236 		SUM    = new Op(3);
237 		PROD   = new Op(4);
238 		LAND   = new Op(5);
239 		BAND   = new Op(6);
240 		LOR    = new Op(7);
241 		BOR    = new Op(8);
242 		LXOR   = new Op(9);
243 		BXOR   = new Op(10);
244 		MINLOC = new Op(11);
245 		MAXLOC = new Op(12);
246 		REPLACE = new Op(13);
247 		NO_OP = new Op(14);
248 
249 		GROUP_EMPTY  = new Group(Group.getEmpty());
250 		REQUEST_NULL = new Request(Request.getNull());
251 		INFO_ENV     = Info.newEnv();
252 		INFO_NULL    = new Info(Info.NULL);
253 
254 		Constant c = new Constant();
255 
256 		THREAD_SINGLE     = c.THREAD_SINGLE;
257 		THREAD_FUNNELED   = c.THREAD_FUNNELED;
258 		THREAD_SERIALIZED = c.THREAD_SERIALIZED;
259 		THREAD_MULTIPLE   = c.THREAD_MULTIPLE;
260 
261 		GRAPH      = c.GRAPH;
262 		DIST_GRAPH = c.DIST_GRAPH;
263 		CART       = c.CART;
264 
265 		ANY_SOURCE = c.ANY_SOURCE;
266 		ANY_TAG    = c.ANY_TAG;
267 		PROC_NULL  = c.PROC_NULL;
268 
269 		UNDEFINED = c.UNDEFINED;
270 
271 		IDENT     = c.IDENT;
272 		CONGRUENT = c.CONGRUENT;
273 		SIMILAR   = c.SIMILAR;
274 		UNEQUAL   = c.UNEQUAL;
275 
276 		TAG_UB          = c.TAG_UB;
277 		HOST            = c.HOST;
278 		IO              = c.IO;
279 		WTIME_IS_GLOBAL = c.WTIME_IS_GLOBAL;
280 
281 		APPNUM        = c.APPNUM;
282 		LASTUSEDCODE  = c.LASTUSEDCODE;
283 		UNIVERSE_SIZE = c.UNIVERSE_SIZE;
284 		WIN_BASE      = c.WIN_BASE;
285 		WIN_SIZE      = c.WIN_SIZE;
286 		WIN_DISP_UNIT = c.WIN_DISP_UNIT;
287 
288 		VERSION    = c.VERSION;
289 		SUBVERSION = c.SUBVERSION;
290 
291 		ROOT           = c.ROOT;
292 		KEYVAL_INVALID = c.KEYVAL_INVALID;
293 		BSEND_OVERHEAD = c.BSEND_OVERHEAD;
294 
295 		MAX_OBJECT_NAME    = c.MAX_OBJECT_NAME;
296 		MAX_PORT_NAME      = c.MAX_PORT_NAME;
297 		MAX_DATAREP_STRING = c.MAX_DATAREP_STRING;
298 
299 		MAX_INFO_KEY = c.MAX_INFO_KEY;
300 		MAX_INFO_VAL = c.MAX_INFO_VAL;
301 
302 		ORDER_C       = c.ORDER_C;
303 		ORDER_FORTRAN = c.ORDER_FORTRAN;
304 
305 		DISTRIBUTE_BLOCK     = c.DISTRIBUTE_BLOCK;
306 		DISTRIBUTE_CYCLIC    = c.DISTRIBUTE_CYCLIC;
307 		DISTRIBUTE_NONE      = c.DISTRIBUTE_NONE;
308 		DISTRIBUTE_DFLT_DARG = c.DISTRIBUTE_DFLT_DARG;
309 
310 		MODE_CREATE          = c.MODE_CREATE;
311 		MODE_RDONLY          = c.MODE_RDONLY;
312 		MODE_WRONLY          = c.MODE_WRONLY;
313 		MODE_RDWR            = c.MODE_RDWR;
314 		MODE_DELETE_ON_CLOSE = c.MODE_DELETE_ON_CLOSE;
315 		MODE_UNIQUE_OPEN     = c.MODE_UNIQUE_OPEN;
316 		MODE_EXCL            = c.MODE_EXCL;
317 		MODE_APPEND          = c.MODE_APPEND;
318 		MODE_SEQUENTIAL      = c.MODE_SEQUENTIAL;
319 
320 		DISPLACEMENT_CURRENT = c.DISPLACEMENT_CURRENT;
321 
322 		SEEK_SET = c.SEEK_SET;
323 		SEEK_CUR = c.SEEK_CUR;
324 		SEEK_END = c.SEEK_END;
325 
326 		MODE_NOCHECK   = c.MODE_NOCHECK;
327 		MODE_NOPRECEDE = c.MODE_NOPRECEDE;
328 		MODE_NOPUT     = c.MODE_NOPUT;
329 		MODE_NOSTORE   = c.MODE_NOSTORE;
330 		MODE_NOSUCCEED = c.MODE_NOSUCCEED;
331 		LOCK_EXCLUSIVE = c.LOCK_EXCLUSIVE;
332 		LOCK_SHARED    = c.LOCK_SHARED;
333 
334 		ERRORS_ARE_FATAL = new Errhandler(Errhandler.getFatal());
335 		ERRORS_RETURN    = new Errhandler(Errhandler.getReturn());
336 
337 		COMM_WORLD = new Intracomm();
338 		COMM_SELF  = new Intracomm();
339 
340 		// Error classes and codes
341 		SUCCESS          = c.SUCCESS;
342 		ERR_BUFFER       = c.ERR_BUFFER;
343 		ERR_COUNT        = c.ERR_COUNT;
344 		ERR_TYPE         = c.ERR_TYPE;
345 		ERR_TAG          = c.ERR_TAG;
346 		ERR_COMM         = c.ERR_COMM;
347 		ERR_RANK         = c.ERR_RANK;
348 		ERR_REQUEST      = c.ERR_REQUEST;
349 		ERR_ROOT         = c.ERR_ROOT;
350 		ERR_GROUP        = c.ERR_GROUP;
351 		ERR_OP           = c.ERR_OP;
352 		ERR_TOPOLOGY     = c.ERR_TOPOLOGY;
353 		ERR_DIMS         = c.ERR_DIMS;
354 		ERR_ARG          = c.ERR_ARG;
355 		ERR_UNKNOWN      = c.ERR_UNKNOWN;
356 		ERR_TRUNCATE     = c.ERR_TRUNCATE;
357 		ERR_OTHER        = c.ERR_OTHER;
358 		ERR_INTERN       = c.ERR_INTERN;
359 		ERR_IN_STATUS    = c.ERR_IN_STATUS;
360 		ERR_PENDING      = c.ERR_PENDING;
361 		ERR_ACCESS       = c.ERR_ACCESS;
362 		ERR_AMODE        = c.ERR_AMODE;
363 		ERR_ASSERT       = c.ERR_ASSERT;
364 		ERR_BAD_FILE     = c.ERR_BAD_FILE;
365 		ERR_BASE         = c.ERR_BASE;
366 		ERR_CONVERSION   = c.ERR_CONVERSION;
367 		ERR_DISP         = c.ERR_DISP;
368 		ERR_DUP_DATAREP  = c.ERR_DUP_DATAREP;
369 		ERR_FILE_EXISTS  = c.ERR_FILE_EXISTS;
370 		ERR_FILE_IN_USE  = c.ERR_FILE_IN_USE;
371 		ERR_FILE         = c.ERR_FILE;
372 		ERR_INFO_KEY     = c.ERR_INFO_KEY;
373 		ERR_INFO_NOKEY   = c.ERR_INFO_NOKEY;
374 		ERR_INFO_VALUE   = c.ERR_INFO_VALUE;
375 		ERR_INFO         = c.ERR_INFO;
376 		ERR_IO           = c.ERR_IO;
377 		ERR_KEYVAL       = c.ERR_KEYVAL;
378 		ERR_LOCKTYPE     = c.ERR_LOCKTYPE;
379 		ERR_NAME         = c.ERR_NAME;
380 		ERR_NO_MEM       = c.ERR_NO_MEM;
381 		ERR_NOT_SAME     = c.ERR_NOT_SAME;
382 		ERR_NO_SPACE     = c.ERR_NO_SPACE;
383 		ERR_NO_SUCH_FILE = c.ERR_NO_SUCH_FILE;
384 		ERR_PORT         = c.ERR_PORT;
385 		ERR_QUOTA        = c.ERR_QUOTA;
386 		ERR_READ_ONLY    = c.ERR_READ_ONLY;
387 		ERR_RMA_CONFLICT = c.ERR_RMA_CONFLICT;
388 		ERR_RMA_SYNC     = c.ERR_RMA_SYNC;
389 		ERR_SERVICE      = c.ERR_SERVICE;
390 		ERR_SIZE         = c.ERR_SIZE;
391 		ERR_SPAWN        = c.ERR_SPAWN;
392 		ERR_UNSUPPORTED_DATAREP   = c.ERR_UNSUPPORTED_DATAREP;
393 		ERR_UNSUPPORTED_OPERATION = c.ERR_UNSUPPORTED_OPERATION;
394 		ERR_WIN          = c.ERR_WIN;
395 		ERR_LASTCODE     = c.ERR_LASTCODE;
396 		ERR_SYSRESOURCE  = c.ERR_SYSRESOURCE;
397 
initVersion()398 		initVersion();
399 	}
400 
newInt2()401 	private static native Int2      newInt2();
newShortInt()402 	private static native ShortInt  newShortInt();
newLongInt()403 	private static native LongInt   newLongInt();
newFloatInt()404 	private static native FloatInt  newFloatInt();
newDoubleInt()405 	private static native DoubleInt newDoubleInt();
initVersion()406 	private static native void initVersion();
407 
initCommon()408 	private static void initCommon() throws MPIException
409 	{
410 		initialized = true;
411 
412 		DATATYPE_NULL.setBasic(Datatype.NULL);
413 
414 		BYTE.setBasic(Datatype.BYTE);
415 		CHAR.setBasic(Datatype.CHAR);
416 		SHORT.setBasic(Datatype.SHORT);
417 		BOOLEAN.setBasic(Datatype.BOOLEAN);
418 		INT.setBasic(Datatype.INT);
419 		LONG.setBasic(Datatype.LONG);
420 		FLOAT.setBasic(Datatype.FLOAT);
421 		DOUBLE.setBasic(Datatype.DOUBLE);
422 		PACKED.setBasic(Datatype.PACKED);
423 
424 		INT2.setBasic(Datatype.INT2, MPI.BYTE);
425 		SHORT_INT.setBasic(Datatype.SHORT_INT, MPI.BYTE);
426 		LONG_INT.setBasic(Datatype.LONG_INT, MPI.BYTE);
427 		FLOAT_INT.setBasic(Datatype.FLOAT_INT, MPI.BYTE);
428 		DOUBLE_INT.setBasic(Datatype.DOUBLE_INT, MPI.BYTE);
429 		FLOAT_COMPLEX.setBasic(Datatype.FLOAT_COMPLEX, MPI.FLOAT);
430 		DOUBLE_COMPLEX.setBasic(Datatype.DOUBLE_COMPLEX, MPI.DOUBLE);
431 
432 		COMM_WORLD.setType(Intracomm.WORLD);
433 		COMM_SELF.setType(Intracomm.SELF);
434 	}
435 
436 	/**
437 	 * Initialize MPI.
438 	 * <p>Java binding of the MPI operation {@code MPI_INIT}.
439 	 * @param args arguments to the {@code main} method.
440 	 * @return arguments
441 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
442 	 */
Init(String[] args)443 	public static String[] Init(String[] args) throws MPIException
444 	{
445 		if(initialized)
446 			throw new MPIException("MPI is already initialized.");
447 
448 		String[] newArgs = Init_jni(args);
449 		initCommon();
450 		return newArgs;
451 	}
452 
Init_jni(String[] args)453 	private static native String [] Init_jni(String[] args);
454 
455 	/**
456 	 * Initialize MPI with threads.
457 	 * <p>Java binding of the MPI operation {@code MPI_INIT_THREAD}.
458 	 * @param args     arguments to the {@code main} method.
459 	 * @param required desired level of thread support
460 	 * @return provided level of thread support
461 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
462 	 */
InitThread(String[] args, int required)463 	public static int InitThread(String[] args, int required) throws MPIException
464 	{
465 		if(initialized)
466 			throw new MPIException("MPI is already initialized.");
467 
468 		int provided = InitThread_jni(args, required);
469 		initCommon();
470 		return provided;
471 	}
472 
InitThread_jni(String[] args, int required)473 	private static native int InitThread_jni(String[] args, int required)
474 			throws MPIException;
475 
476 	/**
477 	 * Java binding of the MPI operation {@code MPI_QUERY_THREAD}.
478 	 * @return provided level of thread support
479 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
480 	 */
queryThread()481 	public static int queryThread() throws MPIException
482 	{
483 		MPI.check();
484 		return queryThread_jni();
485 	}
486 
queryThread_jni()487 	private static native int queryThread_jni() throws MPIException;
488 
489 	/**
490 	 * Java binding of the MPI operation {@code MPI_IS_THREAD_MAIN}.
491 	 * @return true if it is the main thread
492 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
493 	 */
isThreadMain()494 	public static boolean isThreadMain() throws MPIException
495 	{
496 		MPI.check();
497 		return isThreadMain_jni();
498 	}
499 
isThreadMain_jni()500 	private static native boolean isThreadMain_jni() throws MPIException;
501 
502 	/**
503 	 * Finalize MPI.
504 	 * <p>Java binding of the MPI operation {@code MPI_FINALIZE}.
505 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
506 	 */
Finalize()507 	public static void Finalize() throws MPIException
508 	{
509 		check();
510 		Finalize_jni();
511 		finalized = true;
512 	}
513 
Finalize_jni()514 	private static native void Finalize_jni() throws MPIException;
515 
516 	/**
517 	 * Returns an elapsed time on the calling processor.
518 	 * <p>Java binding of the MPI operation {@code MPI_WTIME}.
519 	 * @return time in seconds since an arbitrary time in the past.
520 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
521 	 */
wtime()522 	public static double wtime() throws MPIException
523 	{
524 		check();
525 		return wtime_jni();
526 	}
527 
wtime_jni()528 	private static native double wtime_jni();
529 
530 	/**
531 	 * Returns resolution of timer.
532 	 * <p>Java binding of the MPI operation {@code MPI_WTICK}.
533 	 * @return resolution of {@code wtime} in seconds.
534 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
535 	 */
wtick()536 	public static double wtick() throws MPIException
537 	{
538 		check();
539 		return wtick_jni();
540 	}
541 
wtick_jni()542 	private static native double wtick_jni();
543 
544 	/**
545 	 * Returns a version object representing the version of MPI being used.
546 	 * <p>Java binding of the MPI operation {@code MPI_GET_VERSION}.
547 	 * @return A version object representing the version and subversion of MPI being used.
548 	 */
getVersion()549 	public static Version getVersion() {
550 		return getVersionJNI();
551 	}
552 
getVersionJNI()553 	private static native Version getVersionJNI();
554 
555 	/**
556 	 * Returns the version of the MPI Library
557 	 * <p>Java binding of the MPI operation {@code MPI_GET_LIBRARY_VERSION}.
558 	 * @return A string representation of the MPI Library
559 	 */
getLibVersion()560 	public static String getLibVersion() {
561 		return getLibVersionJNI();
562 	}
563 
getLibVersionJNI()564 	private static native String getLibVersionJNI();
565 
566 	/**
567 	 * Returns the name of the processor on which it is called.
568 	 * <p>Java binding of the MPI operation {@code MPI_GET_PROCESSOR_NAME}.
569 	 * @return A unique specifier for the actual node.
570 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
571 	 */
getProcessorName()572 	static public String getProcessorName() throws MPIException
573 	{
574 		check();
575 		byte[] buf = new byte[MAX_PROCESSOR_NAME];
576 		int lengh = getProcessorName(buf);
577 		return new String(buf,0,lengh);
578 	}
579 
getProcessorName(byte[] buf)580 	static private native int getProcessorName(byte[] buf);
581 
582 	/**
583 	 * Test if MPI has been initialized.
584 	 * <p>Java binding of the MPI operation {@code MPI_INITIALIZED}.
585 	 * @return {@code true} if {@code Init} has been called,
586 	 *         {@code false} otherwise.
587 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
588 	 */
isInitialized()589 	static public native boolean isInitialized() throws MPIException;
590 
591 	/**
592 	 * Test if MPI has been finalized.
593 	 * <p>Java binding of the MPI operation {@code MPI_FINALIZED}.
594 	 * @return {@code true} if {@code Finalize} has been called,
595 	 *         {@code false} otherwise.
596 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
597 	 */
isFinalized()598 	static public native boolean isFinalized() throws MPIException;
599 
600 	/**
601 	 * Attaches a user-provided buffer for sending.
602 	 * <p>Java binding of the MPI operation {@code MPI_BUFFER_ATTACH}.
603 	 * @param buffer initial buffer
604 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
605 	 */
attachBuffer(byte[] buffer)606 	static public void attachBuffer(byte[] buffer) throws MPIException
607 	{
608 		check();
609 		MPI.buffer = buffer;
610 		attachBuffer_jni(buffer);
611 	}
612 
attachBuffer_jni(byte[] buffer)613 	static private native void attachBuffer_jni(byte[] buffer);
614 
615 	/**
616 	 * Removes an existing buffer (for use in sending).
617 	 * <p>Java binding of the MPI operation {@code MPI_BUFFER_DETACH}.
618 	 * @return initial buffer
619 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
620 	 */
detachBuffer()621 	static public byte[] detachBuffer() throws MPIException
622 	{
623 		check();
624 		detachBuffer_jni(buffer);
625 		byte[] result = MPI.buffer;
626 		MPI.buffer = null;
627 		return result;
628 	}
629 
detachBuffer_jni(byte[] buffer)630 	static private native void detachBuffer_jni(byte[] buffer);
631 
632 	/**
633 	 * Controls profiling.
634 	 * <p>This method is not implemented.
635 	 * <p>Java binding of the MPI operation {@code MPI_PCONTROL}.
636 	 * @param level Profiling level.
637 	 * @param obj   Profiling information.
638 	 */
pControl(int level, Object obj)639 	public static void pControl(int level, Object obj)
640 	{
641 		// Nothing to do here.
642 	}
643 
644 	/**
645 	 * Check if MPI has been initialized and hasn't been finalized.
646 	 * @throws MPIException Signals that an MPI exception of some sort has occurred.
647 	 */
check()648 	protected static void check() throws MPIException
649 	{
650 		if(!initialized)
651 			throw new MPIException("MPI is not initialized.");
652 
653 		if(finalized)
654 			throw new MPIException("MPI is finalized.");
655 	}
656 
attrSet(Object value)657 	protected static byte[] attrSet(Object value) throws MPIException
658 	{
659 		try
660 		{
661 			ByteArrayOutputStream baos = new ByteArrayOutputStream();
662 			ObjectOutputStream os = new ObjectOutputStream(baos);
663 			os.writeObject(value);
664 			os.close();
665 			return baos.toByteArray();
666 		}
667 		catch(IOException ex)
668 		{
669 			MPIException mpiex = new MPIException(ex);
670 			mpiex.setStackTrace(ex.getStackTrace());
671 			throw mpiex;
672 		}
673 	}
674 
attrGet(byte[] value)675 	protected static Object attrGet(byte[] value) throws MPIException
676 	{
677 		if(value == null)
678 			return null;
679 
680 		try
681 		{
682 			ByteArrayInputStream bais = new ByteArrayInputStream(value);
683 			ObjectInputStream is = new ObjectInputStream(bais);
684 			Object obj = is.readObject();
685 			is.close();
686 			return obj;
687 		}
688 		catch(ClassNotFoundException ex)
689 		{
690 			throw new MPIException(ex);
691 		}
692 		catch(IOException ex)
693 		{
694 			throw new MPIException(ex);
695 		}
696 	}
697 
698 	/**
699 	 * Allocates a new direct byte buffer.
700 	 * @param capacity The new buffer's capacity, in bytes
701 	 * @return The new byte buffer
702 	 */
newByteBuffer(int capacity)703 	public static ByteBuffer newByteBuffer(int capacity)
704 	{
705 		ByteBuffer buf = ByteBuffer.allocateDirect(capacity);
706 		buf.order(nativeOrder);
707 		return buf;
708 	}
709 
710 	/**
711 	 * Allocates a new direct char buffer.
712 	 * @param capacity The new buffer's capacity, in chars
713 	 * @return The new char buffer
714 	 */
newCharBuffer(int capacity)715 	public static CharBuffer newCharBuffer(int capacity)
716 	{
717 		assert capacity <= Integer.MAX_VALUE / 2;
718 		ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 2);
719 		buf.order(nativeOrder);
720 		return buf.asCharBuffer();
721 	}
722 
723 	/**
724 	 * Allocates a new direct short buffer.
725 	 * @param capacity The new buffer's capacity, in shorts
726 	 * @return The new short buffer
727 	 */
newShortBuffer(int capacity)728 	public static ShortBuffer newShortBuffer(int capacity)
729 	{
730 		assert capacity <= Integer.MAX_VALUE / 2;
731 		ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 2);
732 		buf.order(nativeOrder);
733 		return buf.asShortBuffer();
734 	}
735 
736 	/**
737 	 * Allocates a new direct int buffer.
738 	 * @param capacity The new buffer's capacity, in ints
739 	 * @return The new int buffer
740 	 */
newIntBuffer(int capacity)741 	public static IntBuffer newIntBuffer(int capacity)
742 	{
743 		assert capacity <= Integer.MAX_VALUE / 4;
744 		ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 4);
745 		buf.order(nativeOrder);
746 		return buf.asIntBuffer();
747 	}
748 
749 	/**
750 	 * Allocates a new direct long buffer.
751 	 * @param capacity The new buffer's capacity, in longs
752 	 * @return The new long buffer
753 	 */
newLongBuffer(int capacity)754 	public static LongBuffer newLongBuffer(int capacity)
755 	{
756 		assert capacity <= Integer.MAX_VALUE / 8;
757 		ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 8);
758 		buf.order(nativeOrder);
759 		return buf.asLongBuffer();
760 	}
761 
762 	/**
763 	 * Allocates a new direct float buffer.
764 	 * @param capacity The new buffer's capacity, in floats
765 	 * @return The new float buffer
766 	 */
newFloatBuffer(int capacity)767 	public static FloatBuffer newFloatBuffer(int capacity)
768 	{
769 		assert capacity <= Integer.MAX_VALUE / 4;
770 		ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 4);
771 		buf.order(nativeOrder);
772 		return buf.asFloatBuffer();
773 	}
774 
775 	/**
776 	 * Allocates a new direct double buffer.
777 	 * @param capacity The new buffer's capacity, in doubles
778 	 * @return The new double buffer
779 	 */
newDoubleBuffer(int capacity)780 	public static DoubleBuffer newDoubleBuffer(int capacity)
781 	{
782 		assert capacity <= Integer.MAX_VALUE / 8;
783 		ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 8);
784 		buf.order(nativeOrder);
785 		return buf.asDoubleBuffer();
786 	}
787 
788 	/**
789 	 * Asserts that a buffer is direct.
790 	 * @param buf buffer
791 	 */
assertDirectBuffer(Buffer buf)792 	protected static void assertDirectBuffer(Buffer buf)
793 	{
794 		if(!buf.isDirect())
795 			throw new IllegalArgumentException("The buffer must be direct.");
796 	}
797 
798 	/**
799 	 * Asserts that buffers are direct.
800 	 * @param sendbuf	The send buffer
801 	 * @param recvbuf	The receive buffer
802 	 */
assertDirectBuffer(Buffer sendbuf, Buffer recvbuf)803 	protected static void assertDirectBuffer(Buffer sendbuf, Buffer recvbuf)
804 	{
805 		if(!sendbuf.isDirect())
806 			throw new IllegalArgumentException("The send buffer must be direct.");
807 
808 		if(!recvbuf.isDirect())
809 			throw new IllegalArgumentException("The recv. buffer must be direct.");
810 	}
811 
812 	/**
813 	 * Checks if an object is a direct buffer.
814 	 * @param obj object
815 	 * @return true if the object is a direct buffer
816 	 */
isDirectBuffer(Object obj)817 	protected static boolean isDirectBuffer(Object obj)
818 	{
819 		return obj instanceof Buffer && ((Buffer)obj).isDirect();
820 	}
821 
822 	/**
823 	 * Checks if an object is a heap buffer.
824 	 * @param obj object
825 	 * @return true if the object is a heap buffer
826 	 */
isHeapBuffer(Object obj)827 	protected static boolean isHeapBuffer(Object obj)
828 	{
829 		return obj instanceof Buffer && !((Buffer)obj).isDirect();
830 	}
831 
832 	/**
833 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
834 	 * <p>The content of the new buffer will start at the specified offset.
835 	 * @param buf    buffer
836 	 * @param offset offset
837 	 * @return the new buffer.
838 	 */
slice(ByteBuffer buf, int offset)839 	public static ByteBuffer slice(ByteBuffer buf, int offset)
840 	{
841 		return ((ByteBuffer)buf.clear().position(offset))
842 				.slice().order(nativeOrder);
843 	}
844 
845 	/**
846 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
847 	 * <p>The content of the new buffer will start at the specified offset.
848 	 * @param buf    buffer
849 	 * @param offset offset
850 	 * @return the new buffer.
851 	 */
slice(CharBuffer buf, int offset)852 	public static CharBuffer slice(CharBuffer buf, int offset)
853 	{
854 		return ((CharBuffer)buf.clear().position(offset)).slice();
855 	}
856 
857 	/**
858 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
859 	 * <p>The content of the new buffer will start at the specified offset.
860 	 * @param buf    buffer
861 	 * @param offset offset
862 	 * @return the new buffer.
863 	 */
slice(ShortBuffer buf, int offset)864 	public static ShortBuffer slice(ShortBuffer buf, int offset)
865 	{
866 		return ((ShortBuffer)buf.clear().position(offset)).slice();
867 	}
868 
869 	/**
870 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
871 	 * <p>The content of the new buffer will start at the specified offset.
872 	 * @param buf    buffer
873 	 * @param offset offset
874 	 * @return the new buffer.
875 	 */
slice(IntBuffer buf, int offset)876 	public static IntBuffer slice(IntBuffer buf, int offset)
877 	{
878 		return ((IntBuffer)buf.clear().position(offset)).slice();
879 	}
880 
881 	/**
882 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
883 	 * <p>The content of the new buffer will start at the specified offset.
884 	 * @param buf    buffer
885 	 * @param offset offset
886 	 * @return the new buffer.
887 	 */
slice(LongBuffer buf, int offset)888 	public static LongBuffer slice(LongBuffer buf, int offset)
889 	{
890 		return ((LongBuffer)buf.clear().position(offset)).slice();
891 	}
892 
893 	/**
894 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
895 	 * <p>The content of the new buffer will start at the specified offset.
896 	 * @param buf    buffer
897 	 * @param offset offset
898 	 * @return the new buffer.
899 	 */
slice(FloatBuffer buf, int offset)900 	public static FloatBuffer slice(FloatBuffer buf, int offset)
901 	{
902 		return ((FloatBuffer)buf.clear().position(offset)).slice();
903 	}
904 
905 	/**
906 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
907 	 * <p>The content of the new buffer will start at the specified offset.
908 	 * @param buf    buffer
909 	 * @param offset offset
910 	 * @return the new buffer.
911 	 */
slice(DoubleBuffer buf, int offset)912 	public static DoubleBuffer slice(DoubleBuffer buf, int offset)
913 	{
914 		return ((DoubleBuffer)buf.clear().position(offset)).slice();
915 	}
916 
917 	/**
918 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
919 	 * <p>The content of the new buffer will start at the specified offset.
920 	 * @param buf    buffer
921 	 * @param offset offset
922 	 * @return the new buffer.
923 	 */
slice(byte[] buf, int offset)924 	public static ByteBuffer slice(byte[] buf, int offset)
925 	{
926 		return ByteBuffer.wrap(buf, offset, buf.length - offset)
927 				.slice().order(nativeOrder);
928 	}
929 
930 	/**
931 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
932 	 * <p>The content of the new buffer will start at the specified offset.
933 	 * @param buf    buffer
934 	 * @param offset offset
935 	 * @return the new buffer.
936 	 */
slice(char[] buf, int offset)937 	public static CharBuffer slice(char[] buf, int offset)
938 	{
939 		return CharBuffer.wrap(buf, offset, buf.length - offset).slice();
940 	}
941 
942 	/**
943 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
944 	 * <p>The content of the new buffer will start at the specified offset.
945 	 * @param buf    buffer
946 	 * @param offset offset
947 	 * @return the new buffer.
948 	 */
slice(short[] buf, int offset)949 	public static ShortBuffer slice(short[] buf, int offset)
950 	{
951 		return ShortBuffer.wrap(buf, offset, buf.length - offset).slice();
952 	}
953 
954 	/**
955 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
956 	 * <p>The content of the new buffer will start at the specified offset.
957 	 * @param buf    buffer
958 	 * @param offset offset
959 	 * @return the new buffer.
960 	 */
slice(int[] buf, int offset)961 	public static IntBuffer slice(int[] buf, int offset)
962 	{
963 		return IntBuffer.wrap(buf, offset, buf.length - offset).slice();
964 	}
965 
966 	/**
967 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
968 	 * <p>The content of the new buffer will start at the specified offset.
969 	 * @param buf    buffer
970 	 * @param offset offset
971 	 * @return the new buffer.
972 	 */
slice(long[] buf, int offset)973 	public static LongBuffer slice(long[] buf, int offset)
974 	{
975 		return LongBuffer.wrap(buf, offset, buf.length - offset).slice();
976 	}
977 
978 	/**
979 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
980 	 * <p>The content of the new buffer will start at the specified offset.
981 	 * @param buf    buffer
982 	 * @param offset offset
983 	 * @return the new buffer.
984 	 */
slice(float[] buf, int offset)985 	public static FloatBuffer slice(float[] buf, int offset)
986 	{
987 		return FloatBuffer.wrap(buf, offset, buf.length - offset).slice();
988 	}
989 
990 	/**
991 	 * Creates a new buffer whose content is a shared subsequence of a buffer.
992 	 * <p>The content of the new buffer will start at the specified offset.
993 	 * @param buf    buffer
994 	 * @param offset offset
995 	 * @return the new buffer.
996 	 */
slice(double[] buf, int offset)997 	public static DoubleBuffer slice(double[] buf, int offset)
998 	{
999 		return DoubleBuffer.wrap(buf, offset, buf.length - offset).slice();
1000 	}
1001 
1002 } // MPI
1003