package GA version 0.1 { /* GA */
    
    /**
     * Global Arrays Port. 
     */
    interface GAPort extends gov.cca.Port {
	/**
	 * Initialize Global Arrays.
	 * Allocate and initialize internal data structures in Global Arrays.
	 * This is a collective operation.
	 */
	void initialize(in long heapsize, in long stackSize, in int type, 
			in long limit);
	
	/**
	 * Delete all active arrays and destroy internal data structures. 
	 * This is a collective operation.
	 */
	void terminate();
	
	/**  
	 * Creates an ndim-dimensional array using the regular distribution 
	 * model and returns integer handle representing the array. 
	 */
	GlobalArray createGA_reg(in int type, in int ndim, in array<int> dims, 
				 in string arrayname, in array<int> chunk);
	
	/**
	 * Creates an array by following the user-specified distribution and 
	 * returns integer handle representing the array. 
	 */
	GlobalArray createGA_irreg(in int type,in int ndim,in array<int> dims,
				   in string arrayname, in array<int> maps, 
				   in array<int> block);
	
	/**
	 * Creates a new array by applying all the default properties
	 */
	GlobalArray createGA();
	
	/**
	 * Creates a new array by applying all the properties of another 
	 * existing array (i.e.it duplicates). It returns array handle. 
	 * Return value: a non-zero array handle means the call was succesful. 
	 * This is a collective operation. 
	 */
	GlobalArray createGA_dup(in GlobalArray g_a, in string array_name);
	
	/**
	 * Broadcast from process root to all other processes a message of 
	 * length lenbuf. This is operation is provided only for convenience 
	 * purposes: it is available regardless of the message-passing library 
	 * that GA is running with. 
	 */
	void brdcst(in opaque buf, in int lenbuf, in int root);
	
	/**
	 * Creates a set containing the number of mutexes. Returns 0 if the 
	 * opereation succeeded or 1 when failed. Mutex is a simple 
	 * synchronization object used to protect Critical Sections. Only one 
	 * set of mutexes can exist at a time. Array of mutexes can be created 
	 * and destroyed as many times as needed.
	 */
	int createMutexes(in int number);
	
	/** 
	 * Destroys the set of mutexes created with ga_create_mutexes. 
	 * Returns 0 if the operation succeeded or 1 when failed. 
	 */
	int destroyMutexes();
	
	/**
	 * Double Global OPeration. 
	 *
	 * X(1:N) is a vector present on each process. DGOP 'sums' elements of 
	 * X accross all nodes using the commutative operator OP. The result is
	 * broadcast to all nodes. Supported operations include '+', '*', 
	 * 'max', 'min', 'absmax', 'absmin'. The use of lowerecase for 
	 * operators is necessary. This is operation is provided only for 
	 * convenience purposes: it is available regardless of the 
	 * message-passing library that GA is running with. 
	 * This is a collective operation.
	 */
	void dgop(in array<double> x, in int n, in string op);
	
	/**
	 * To be called in case of an error. Print an error message and an 
	 * integer value that represents error code. Releases some system 
	 * resources. This is the required way of aborting the program 
	 * execution. 
	 * This operation is local. 
	 */
	void error(in string message, in int code);
	
	/**
	 * Blocks the calling process until all the data transfers 
	 * corresponding to GA operations called after ga_init_fence complete.
	 * For example, since ga_put might return before the data reaches the 
	 * final destination, ga_init_fence and ga_fence allow process to wait
	 * until the data tranfer is fully completed: 
	 *
	 *          ga_init_fence();
	 *          ga_put(g_a, ...);
	 *          ga_fence();
	 * 
	 * ga_fence must be called after ga_init_fence. A barrier, ga_sync, 
	 * assures completion of all data transfers and implicitly cancels 
	 * all outstanding ga_init_fence calls. ga_init_fence and ga_fence 
	 * must be used in pairs, multiple calls to ga_fence require the 
	 * same number of corresponding ga_init_fence calls. 
	 * ga_init_fence/ga_fence pairs can be nested. 
	 * 
	 * ga_fence works for multiple GA operations. For example: 
	 * 
	 *         ga_init_fence();
	 *         ga_put(g_a, ...);
	 *         ga_scatter(g_a, ...);
	 *         ga_put(g_b, ...);
	 *         ga_fence();
	 *
	 * The calling process will be blocked until data movements 
	 * initiated by two calls to ga_put and one ga_scatter complete. 
	 */
	void fence();
	
	/**
	 * Integer Global OPeration. The integer (more precisely long) version 
	 * of ga_dgop described above, also include the bitwise OR operation. 
	 * This is operation is provided only for convenience purposes: it is 
	 * available regardless of the message-passing library that GA is 
	 * running with. This is a collective operation. 
	 */
	void igop(in array<int> x, in int n, in string op);
	
	/**
	 * Initializes tracing of completion status of data movement 
	 * operations. This operation is local. 
     */
	void initFence();
	
	/**
	 * Returns amount of memory (in bytes) used in the allocated global 
	 * arrays on the calling processor. This operation is local. 
	 */
	long inquireMemory();
	
	/**
	 * Locks a mutex object identified by the mutex number. It is a fatal 
	 * error for a process to attempt to lock a mutex which was already 
	 * locked by this process. 
	 */
	void lock(in int mutex);
	
	/**
	 * lesser of the amount available under the GA limit and the amount 
	 * available from MA (according to ma_inquire_avail operation). 
	 * If no GA limit has been set, it returns what MA says is available. 
	 * If ( ! GA_Uses_ma() && ! GA_Memory_limited() ) returns < 0, 
	 * indicating that the bound on currently available memory cannot 
	 * be determined. 
	 * This operation is local. 
	 */
	int memoryAvailable();
	
	/**
	 * Indicates if limit is set on memory usage in Global Arrays on the 
	 * calling processor. "1" means "yes", "0" means "no". This operation 
	 * is local. 
	 */
	int memoryLimited();
	
	/**
	 * @return Returns the GA process id (0, ..., ga_Nnodes()-1) of the 
	 * requesting compute process. This operation is local. 
	 */
	int nodeid();
	
	/**
	 * @return Returns the number of the GA compute (user) processes. 
	 * This operation is local. 
	 */
	int nodes();
	
	/** 
	 * This non-collective (MIMD) operation prints information about: 
	 *
	 * number of calls to the GA create/duplicate, destroy, get, put, 
	 * scatter, gather, and read_and_inc operations total amount of 
	 * data moved in the GA primitive operations amount of data moved
	 * in GA primitive operations to logicaly remote locations maximum 
	 * memory consumption in global arrays, and number of requests 
	 * serviced in the interrupt-driven implementations by the calling 
	 * process. This operation is local. 
	 */
	void printStats();
	
	/**
	 * Sets the amount of memory to be used (in bytes) per process. 
	 * This is a local operation. 
	 * @param limit    - the amount of memory in bytes per process [input]
	 */
	void setMemoryLimit(in long limit);
	
	/** 
	 * Prints info about allocated arrays. 
	 * @param verbose     - If true print distribution info [input]
	 */
	void summarize(in int verbose);
	
	/**
	 * Synchronize processes (a barrier) and ensure that all GA operations 
	 * completed. 
	 * This is a collective operation. 
	 */
	void sync();
	
	/**
	 * Unlocks a mutex object identified by the mutex number. It is a fatal
	 * error for a process to attempt to unlock a mutex which has not been 
	 * locked by this process. 
	 * @param mutex  - mutex object id [input]
	 */
	void unlock(in int mutex);
	
	/**
	 * @return Returns "1" if memory in global arrays comes from the Memory
	 * Allocator (MA). "0"means that memory comes from another source, for 
	 * example System V shared memory is used. This operation is local. 
	 */
	int usesMA();
	
	/**
	 * Returns "1" if GA uses Fortran API, else returns "0"
	 */
	int usesFAPI();
    }

    /**
     * Distributed Array Descriptor Factory (DADF) Port.
     */
    interface DADFPort extends gov.cca.Port {
	
    }
    
    /**
     * Global Arrray class.
     */
    
    class GlobalArray {  
	void createGA_reg(in int type, in int ndim, in array<int> dims, 
			  in string arrayname, in array<int> chunk);
	void createGA_irreg(in int type, in int ndim, in array<int> dims, 
			    in string arrayname, in array<int> block,
			    in array<int> maps);
	void createGA();
	void createGA_dup(in GlobalArray g_a, in string arrayname);
	
	/* access the data */
	/** @return returns the array handler*/
	int handle();
	
  /* Global Array operations */
  
  /** 
   * Combines data from local array buffer with data in the global array 
   * section. The local array is assumed to be have the same number of 
   * dimensions as the global array. 
   
   * global array section (lo[],hi[]) += *alpha * buffer
   
   * This is a one-sided and atomic operation.  
   * @param lo[ndim]   - array of starting indices for array section[input] 
   * @param hi[ndim]   - array of ending indices for array section  [input]
   * @param buf        - pointer to the local buffer array          [input]
   * @param ld[ndim-1] - array specifying leading dimensions/strides/extents 
   *                     for buffer array                           [input]
   * @param alpha      - scale factor (double/dcomplex/long *) [input]
   */
  void acc(in array<int> lo, in array<int> hi, in opaque buf, 
	   in array<int> ld, in opaque alpha);
  
  /**
   * Provides access to the specified patch of a global array. Returns 
   * array of leading dimensions ld and a pointer to the first element 
   * in the patch. This routine allows to access directly, in place 
   * elements in the local section of a global array. It useful for 
   * writing new GA operations. A call to ga_access normally follows a 
   * previous call to ga_distribution that returns coordinates of the 
   * patch associated with a processor. You need to make sure that the 
   * coordinates of the patch are valid (test values returned from 
   * ga_distribution). 
   *
   * Each call to ga_access has to be followed by a call to either 
   * ga_release or ga_release_update. You can access in this fashion only 
   * local data. Since the data is shared with other processes, you need 
   * to consider issues of mutual exclusion. This operation is local. 
   * 
   * @param ndim      - number of dimensions of the global array
   * @param lo[ndim]  - array of starting indices for array section [input]
   * @param hi[ndim]  - array of ending indices for array section   [input]
   * @param ptr       - points to location of first element in patch[output]
   * @param ld[ndim-1]- leading dimensions for the pacth elements   [output]
   */
  void access(in array<int> lo, in array<int> hi, in opaque ptr, 
	      in array<int> ld);
  
  /**
   * The arrays are aded together elemet-wise:
   * c = alpha * a + beta * b
   * The result c may replace one of he input arrays(a/b).
   * This is a collective operation.
   */
  void add(in opaque alpha, in GlobalArray g_a, 
	   in opaque beta,  in GlobalArray g_b);
  

  /**
   * Patches of arrays (which must have the same number of elements) are 
   * added together element-wise. 
   * c[ ][ ] = alpha * a[ ][ ] + beta * b[ ][ ]. 
   * This is a collective operation. 
   * @param g_a, g_b, g_c             array handles        [input] 
   * @param alo[], ahi[]              patch of g_a         [input]
   * @param blo[], bhi[]              patch of g_b         [input]
   * @param clo[], chi[]              patch of g_c         [input]
   * @param alpha, beta               scale factors        [input]  
   */
  void addPatch (in opaque alpha, in GlobalArray g_a, 
		 in array<int> alo, in array<int> ahi,
		 in opaque beta,  in GlobalArray g_b, 
		 in array<int> blo, in array<int> bhi,
		 in array<int> clo, in array<int> chi);
  
 
  /**
   * Check that the global array handle g_a is valid ... if not call 
   * ga_error with the string provided and some more info. 
   * This operation is local. 
   * @param g_a    - array handle               [input]
   * @param str - message string             [input]
   */
  void checkHandle(in string str);
  
  /**   
   * Compares distributions of two global arrays. Returns 0 if 
   * distributions are identical and 1 when they are not. 
   * This is a collective operation. 
   * @param g_a, g_b    - array handles               [input]
   */
  int compareDistr(in GlobalArray g_a);

  /**   
   * Copies elements in array represented by g_a into the array 
   * represented by g_b. The arrays must be the same type, shape, 
   * and identically aligned. 
   * This is a collective operation.
   * @param g_a - array handles       [input]
   */
  void copyAll(in GlobalArray g_a); /** "copy" is SIDL keyword */
  
  /**
   * Copies elements in a patch of one array into another one. The patches of 
   * arrays may be of different shapes but must have the same number of 
   * elements. Patches must be nonoverlapping (if gb=ga). 

   * trans = 'N' or 'n' means that the transpose operator should not be 
   * applied. trans = 'T' or 't' means that transpose operator should be 
   * applied. This is a collective operation. 
   * @param ga               - array handles         [input]
   * @param alo[]             - ga patch coordinates [input] 
   * @param ahi[]             - ga patch coordinates [input]
   * @param blo[]            - gb patch coordinates [input]  
   * @param bhi[]            - gb patch coordinates [input]  
   */
  void copyPatch(in GlobalArray ga, in array<int> alo, in array<int> ahi, 
		 in array<int> blo, in array<int> bhi);
  
  /**
   * Computes element-wise dot product of the two arrays which must be of
   * the same types and same number of elements.
   *          return value = SUM_ij a(i,j)*b(i,j)
   * This is a collective operation. 
   * @param g_a   - array handle                 [input]
   */
  double ddot(in GlobalArray  g_a); 
  
  /**
   * Computes the element-wise dot product of the two (possibly transposed) 
   * patches which must be of the same type and have the same number of 
   * elements. 
   * @param  g_a                  - array handles             [input]
   * @param  alo, ahi         - g_a patch coordinates     [input]
   * @param  blo, bhi         - g_b patch coordinates     [input]
   * @param  ta, tb               - transpose flags           [input]
   */
  double ddotPatch(in char ta, in array<int> alo, in array<int> ahi,
		   in GlobalArray  g_a, in char tb, in array<int> blo, 
		   in array<int> bhi);
  
  /** Deallocates the array and frees any associated resources. */
  void destroy();
  
  /**
   * Performs one of the matrix-matrix operations: 
   *     C := alpha*op( A )*op( B ) + beta*C,
   * where op( X ) is one of 
   *     op( X ) = X   or   op( X ) = X',
   * alpha and beta are scalars, and A, B and C are matrices, with op( A ) 
   * an m by k matrix, op( B ) a k by n matrix and C an m by n matrix. 
   * On entry, transa specifies the form of op( A ) to be used in the 
   * matrix multiplication as follows: 
   *         ta = 'N' or 'n', op( A ) = A. 
   *         ta = 'T' or 't', op( A ) = A'. 
   * This is a collective operation. 
   * @param g_a,g_b- handles to input arrays  [input]
   * @param g_c    - handles to output array  [input]
   * @param ta, tb - transpose operators      [input]
   * @param m  - number of rows of op(A) and of matrix  C           [input]
   * @param n  - number of columns of op(B) and of matrix  C        [input]
   * @param k  - number of columns of op(A) and rows of matrix op(B)[input]
   * @param alpha, beta  - scale factors                            [input]
   */
  void dgemm(in char ta, in char tb, in int m, in int n, in int k, 
	     in double alpha, in GlobalArray g_a, in GlobalArray g_b, 
	     in double beta);
  
  /**
   * Solve the generalized eigen-value problem returning all eigen-vectors 
   * and values in ascending order. The input matrices are not overwritten 
   * or destroyed. 
   * This is a collective operation. 
   * @param g_s     - Metric                         [input] 
   * @param g_v     - Global matrix to return evecs  [output]
   * @param eval    - Local array to return evals    [output]
   */
  void diag(in GlobalArray g_s, in GlobalArray g_v, in opaque eval);

  /**
   * Solve the generalized eigen-value problem returning all eigen-vectors 
   * and values in ascending order. Recommended for REPEATED calls if g_s 
   * is unchanged. Values of the control flag: 
   *          value       action/purpose 
   *           0          indicates first call to the eigensolver 
   *          >0          consecutive calls (reuses factored g_s) 
   *          <0          only erases factorized g_s; g_v and eval unchanged 
   *                      (should be called after previous use if another 
   *                      eigenproblem, i.e., different g_a and g_s, is to 
   *                      be solved) 
   * The input matrices are not destroyed. 
   * This is a collective operation. 
   * @param control - Control flag                   [input]
   * @param g_a     - Matrix to diagonalize          [input]
   * @param g_s     - Metric                         [input] 
   * @param g_v     - Global matrix to return evecs  [output]
   * @param eval    - Local array to return evals    [output]
   */
  void diagReuse(in int control, in GlobalArray g_s, in GlobalArray g_v, 
		 in opaque eval);
  
  /**
   * Solve the standard (non-generalized) eigenvalue problem returning 
   * all eigenvectors and values in the ascending order. The input matrix 
   * is neither overwritten nor destroyed. 
   * This is a collective operation. 
   * @param g_v     - Global matrix to return evecs  [output]
   * @param eval    - Local array to return evals    [output]
   */
  void diagStd(in GlobalArray g_v, in opaque eval);

  void diagSeq(in GlobalArray  g_s, in GlobalArray  g_v, 
		       in opaque eval);
  
  void diagStdSeq(in GlobalArray  g_v, in opaque eval);
  /** 
   * If no array elements are owned by process 'me', the range is returned
   * as lo[]=0 and hi[]=-1 for all dimensions. The operation is local.
   * @param iproc      - process number                            [input]
   * @param ndim       - number of dimensions of the global array
   * @param lo[ndim]   - array of starting indices for array section[input]
   * @param hi[ndim]   - array of ending indices for array section  [input]
   */
  void distribution(in int me, in array<int> lo, in array<int> hi);

  /**
   * Computes element-wise dot product of the two arrays which must be of
   * the same types and same number of elements.
   *          return value = SUM_ij a(i,j)*b(i,j)
   * This is a collective operation. 
   * @param g_a   - array handle                 [input]
   */
  float fdot(in GlobalArray  g_a);

  float fdotPatch(in char t_a, in array<int> alo, in array<int> ahi,
		  in GlobalArray g_b, in char t_b, in array<int> blo, 
		  in array<int> bhi);

  /**
   * (double/dcomplex/long) that matches array type.
   * Assign a single value to all elements in the array.
   * This is a collective operation. 
   * @param value   - pointer to the value of appropriate type 
   */
  void fill(in opaque value);
  
  /**
   * Fill the patch of g_a with  value of 'val' 
   * This is a collective operation. 
   * @param   g_a                       array handles        [input] 
   * @param lo[], hi[]                patch of g_a         [input]
   * @param val                       value to fill        [input]
   */
  void fillPatch (in array<int> lo, in array<int> hi, in opaque val);
  
  /** 
   * Gathers array elements from a global array into a local array. 
   * The contents of the input arrays (v, subscrArray) are preserved, 
   * but their contents might be (consistently) shuffled on return. 
   
   * for(k=0; k<= n; k++){
   *     v[k] = a[subsArray[k][0]][subsArray[k][1]][subsArray[k][2]]...;    
   * }

   * This is a one-sided operation.  
   * @param n   - number of elements              [input] 
   * @param  v[n]                - array containing values [input]        
   * @param  subsarray[n][ndim]  - array of subscripts for each element [input]
   */
  void gather(in opaque v, in array<int,2,row-major> subsarray, in int n);

  /**
   * One-side operations. 
   * Copies data from global array section to the local array buffer. The 
   * local array is assumed to be have the same number of dimensions as the 
   * global array. Any detected inconsitencies/errors in the input arguments
   * are fatal. 
   * 
   * Example: For ga_get operation transfering data from the [10:14,0:4] 
   * section of 2-dimensional 15x10 global array into local buffer 5x10 
   * array we have: lo={10,0}, hi={14,4}, ld={10}  
   *
   * @param lo[ndim] -array of starting indices for global array section[input]
   * @param hi[ndim] - array of ending indices for global array section[input]
   * @param buf - pointer to the local buffer array where the data goes[output]
   * @param ld[ndim-1] - array specifying leading dimensions/strides/extents 
   * for buffer array [input]
   */
  void get(in array<int> lo, in array<int> hi, in opaque buf, 
	   in array<int> ld);

  /**
   * Computes element-wise dot product of the two arrays which must be of
   * the same types and same number of elements.
   *          return value = SUM_ij a(i,j)*b(i,j)
   * This is a collective operation. 
   * @param g_a   - array handle                 [input]
   */
  long idot(in GlobalArray  g_a); 

  /**
   * Computes the element-wise dot product of the two (possibly transposed) 
   * patches which must be of the same type and have the same number of 
   * elements. 
   * @param  g_a                  - array handles             [input]
   * @param  alo[], ahi[]         - g_a patch coordinates     [input]
   * @param  blo[], bhi[]         - g_b patch coordinates     [input]
   * @param  ta, tb               - transpose flags           [input]
   */
  long idotPatch(in char ta, in array<int> alo, in array<int> ahi, 
		 in GlobalArray  g_a, in char tb, in array<int> blo, 
		 in array<int> bhi);
  
  /** 
   * @return Returns data type and dimensions of the array. 
   * This operation is local.   
   * @param type - data type                     [output]
   * @param ndim - number of dimensions          [output]
   * @param dims - array of dimensions           [output]
   */
  void inquire(in array<int> type, in array<int> ndim, in array<int> dims);

  /** 
   * @return Returns the name of an array represented by the handle g_a. 
   * This operation is local. 
   */
  string inquireName();

  /**
   * Computes element-wise dot product of the two arrays which must be of
   * the same types and same number of elements.
   *          return value = SUM_ij a(i,j)*b(i,j)
   * This is a collective operation. 
   * @param g_a   - array handle                 [input]
   */
  long ldot(in GlobalArray  g_a); 

  /**
   * Solves a system of linear equations 
   *            A * X = B 
   * using the Cholesky factorization of an NxN double precision symmetric 
   * positive definite matrix A (epresented by handle g_a). On successful 
   * exit B will contain the solution X. 
   * @return It returns: 
   *         = 0 : successful exit 
   *         > 0 : the leading minor of this order is not positive 
   *               definite and the factorization could 
   *               not be completed 
   * This is a collective operation. 
   * @param g_a     - coefficient matrix        [input]
   */
  int lltSolve(in GlobalArray  g_a);

  /**
   * Return in owner the GA compute process id that 'owns' the data. If any 
   * element of subscript[] is out of bounds "-1" is returned. This operation 
   * is local. 
   * @param subscript[ndim]  element subscript    [output]
   */
  int locate(in array<int> subscript);
  
  /**
   * Return the list of the GA processes id that 'own' the data. Parts of the 
   * specified patch might be actually 'owned' by several processes. If lo/hi 
   * are out of bounds "0" is returned, otherwise return value is equal to the 
   * number of processes that hold the data. This operation is local.
   * 
   *   map[i][0:ndim-1]       - lo[i]
   *   map[i][ndim:2*ndim-1]  - hi[i]
   *   procs[i]               - processor id that owns data in patch 
   *                            lo[i]:hi[i] 
   * @param ndim          - number of dimensions of the global array
   * @param lo[ndim]      - array of starting indices for array section[input]
   * @param hi[ndim]      - array of ending indices for array section  [input]
   * @param map[][2*ndim] - array with mapping information           [output]
   * @param procs[nproc]  - list of processes that own a part of array 
   *                        section[output]
   */
  int locateRegion(in array<int> lo, in array<int> hi, in array<int> map, 
		   in array<int> procs);

  /**
   * Solve the system of linear equations op(A)X = B based on the LU 
   * factorization. 
   * op(A) = A or A' depending on the parameter trans: 
   * trans = 'N' or 'n' means that the transpose operator should not 
   *          be applied. 
   * trans = 'T' or 't' means that the transpose operator should be applied. 
   * Matrix A is a general real matrix. Matrix B contains possibly multiple 
   * rhs vectors. The array associated with the handle g_b is overwritten 
   * by the solution matrix X. 
   * This is a collective operation. 
   * @param trans   - transpose or not transpose [input]
   * @param g_a     - coefficient matrix         [input]
   */
  void luSolve(in char trans, in GlobalArray g_a);
  
  /**
   * ga_matmul_patch is a patch version of ga_dgemm: 
   *      C[cilo:cihi,cjlo:cjhi] := alpha* AA[ailo:aihi,ajlo:ajhi] *
   *                                BB[bilo:bihi,bjlo:bjhi] ) + 
   *                                beta*C[cilo:cihi,cjlo:cjhi],
   * where AA = op(A), BB = op(B), and op( X ) is one of 
   *      op( X ) = X   or   op( X ) = X',
   * Valid values for transpose arguments: 'n', 'N', 't', 'T'. It works 
   * for both double and dcomplex data tape. 
   * This is a collective operation. 
   * @param g_a, g_b                  array handles        [input] 
   * @param ailo, aihi, ajlo, ajhi    patch of g_a         [input]
   * @param bilo, bihi, bjlo, bjhi    patch of g_b         [input]
   * @param cilo, cihi, cjlo, cjhi    patch of g_c         [input]
   * @param alpha, beta               scale factors        [input]
   * @param transa, transb            transpose operators  [input]
   */
  void matmulPatch(in string transa, in string transb, in opaque alpha, 
		   in opaque beta, in GlobalArray g_a, 
		   in int ailo, in int aihi, in int ajlo, in int ajhi,
		   in GlobalArray g_b, 
		   in int bilo, in int bihi, in int bjlo, in int bjhi,
		   in int cilo, in int cihi, in int cjlo, in int cjhi);
  
  /**
   * Given a distribution of an array represented by the handle g_a, 
   * returns the number of partitions of each array dimension. 
   * This operation is local. 
   * @param nblock[ndim]  - number of partitions for each dimension [output]
   */
  void nblock(in array<int> numblock);

  /**
   * @return Returns the number of dimensions in array represented by the 
   * handle g_a. This operation is local. 
   */
  int ndim();
  
  /**  
   * Same as nga_acc except the indices can extend beyond the array 
   * boundary/dimensions in which case the library wraps them around. 
   * This is a one-sided and atomic operation.     
   * @param ndim       - number of dimensions of the global array
   * @param lo[ndim]   - array of starting indices for array section [input] 
   * @param hi[ndim]   - array of ending indices for array section   [input]
   * @param buf        - pointer to the local buffer array           [input]
   * @param ld[ndim-1] - array specifying leading 
   *                     dimensions/strides/extents for buffer array [input]
   * @param double/dcomplex/long *alpha     scale factor 
   */
  void periodicAcc(in array<int> lo, in array<int> hi, in opaque buf, 
		   in array<int> ld, in opaque alpha);
  
  /**
   * Same as nga_get except the indices can extend beyond the array 
   * boundary/dimensions in which case the library wraps them around. 
   * This is a one-sided operation.
   * @param ndim       - number of dimensions of the global array
   * @param lo[ndim]   - array of starting indices for global array 
   *                     section [input] 
   * @param hi[ndim]   - array of ending indices for global array 
   *                     section [input] 
   * @param buf        - pointer to the local buffer array where the data 
   *                     goes    [output]
   * @param ld[ndim-1] - array specifying leading dimensions/strides/extents 
   *                     for buffer array [input]
   */
  void periodicGet(in array<int> lo, in array<int> hi, in opaque buf, 
		   in array<int> ld);
  
  /**
   * Same as nga_put except the indices can extend beyond the array 
   * boundary/dimensions in which case the library wraps them around. 
   * This is a one-sided operation.
   * @param ndim       - number of dimensions of the global array
   * @param lo[ndim]   - array of starting indices for global array 
   *                     section [input] 
   * @param hi[ndim]   - array of ending indices for global array 
   *                     section [input] 
   * @param buf        - pointer to the local buffer array where the data 
   *                     goes    [output]
   * @param ld[ndim-1] - array specifying leading dimensions/strides/extents 
   *                     for buffer array [input]
   */
  void periodicPut(in array<int> lo, in array<int> hi, in opaque buf, 
		   in array<int> ld);
  
  /** 
   * Prints an entire array to the standard output. 
   * This is a collective operation. 
   */
  void printAll(); /** print is SIDL Keyword */
  
  /** 
   * Prints the array distribution. 
   * This is a collective operation. 
   */
  void printDistribution();

  /** 
   * Prints the array distribution to a file. 
   * This is a collective operation. 
   */
  void printFile(in opaque file);
  
  /**
   * Prints a patch of g_a array to the standard output. If pretty has the 
   * value 0 then output is printed in a dense fashion. If pretty has the 
   * value 1 then output is formatted and rows/columns labeled. 
   
   * This is a collective operation.  
   * @param lo[]         - coordinates of the patch    [input]
   * @param hi[]         - coordinates of the patch    [input]
   * @param int pretty        - formatting flag        [input]
   */
  void printPatch(in array<int> lo, in array<int> hi, in array<int> pretty) ;
  
  /**
   * Based on the distribution of an array associated with handle g_a, 
   * determines coordinates of the specified processor in the 
   * processor grid corresponding to the distribution of array g_a. The 
   * numbering starts from 0. The values of -1 means that the processor 
   * doesn't 'own' any section of array represented by g_a. 
   * This operation is local. 
   * @param ndim              number of array dimensions 
   * @param proc              process id                    [input] 
   * @param coord[ndim]       coordinates in processor grid [output] 
   */
  void procTopology(in int proc, in array<int> coord);

  /* void procTopology(int proc, int *prow, int *pcol);*/ 
  
  /**
   * Copies data from local array buffer to the global array section . The 
   * local array is assumed to be have the same number of dimensions as the 
   * global array. Any detected inconsitencies/errors in input arguments are 
   * fatal. This is a one-sided operation. 
   *
   * @param lo[ndim]-array of starting indices for global array section[input] 
   * @param hi[ndim]- array of ending indices for global array section [input] 
   * @param buf - pointer to the local buffer array where the data is [input]
   * @param ld[ndim-1]-array specifying leading dimensions/strides/extents for 
   * @param buffer array [input]
   */
  void put(in array<int> lo, in array<int> hi, in opaque buf, 
	   in array<int> ld);
  

  /**
   * Atomically read and increment an element in an integer array. 
   *      *BEGIN CRITICAL SECTION*
   *       old_value = a(subscript)
   *       a(subscript) += inc
   *      *END CRITICAL SECTION*
   *       return old_value
   * This is a one-sided and atomic operation. 
   * @param ndim            - number of dimensions of the global array
   * @param subscript[ndim] - subscript array for the referenced element[input]
   */
  long readInc(in array<int> subscript, in long inc);

  /**
   * Releases access to a global array when the data was read only. 
   * Your code should look like: 
   *        NGA_Distribution(g_a, myproc, lo,hi);
   *        NGA_Access(g_a, lo, hi, &ptr, ld);
   *            
   *          <operate on the data referenced by ptr> 
   *        GA_Release(g_a, lo, hi);
   * @note NOTE: see restrictions specified for ga_access 
   * This operation is local. 
   * @param ndim       - number of dimensions of the global array
   * @param lo[ndim]   - array of starting indices for array section [input]
   * @param hi[ndim]   - array of ending indices for array section   [input]
   */
  void release(in array<int> lo, in array<int> hi);

  /**
   * Releases access to the data. It must be used if the data was accessed 
   * for writing. NOTE: see restrictions specified for ga_access. 
   * This operation is local. 
   * @param ndim       - number of dimensions of the global array
   * @param lo[ndim]   - array of starting indices for array section [input]
   * @param hi[ndim]   - array of ending indices for array section   [input]
   */
  void releaseUpdate(in array<int> lo, in array<int> hi);

  /** 
   * Scales an array by the constant s. Note that the library is unable 
   * to detect errors when the pointed value is of different type than 
   * the array. 
   * This is a collective operation. 
   * @param value   - pointer to the value of appropriate type 
   *                  (double/dcomplex/long) that matches array type    
   */
  void scale(in opaque value);

  /** 
   * Scale an array by the factor 'val' 
   * This is a collective operation. 
   * @param lo, hi                patch of g_a         [input]
   * @param val                       scale factor         [input]
   */
  void scalePatch (in array<int> lo, in array<int> hi, in opaque val);
  
  /** 
   * Scatters array elements into a global array. The contents of the input 
   * arrays (v,subscrArray) are preserved, but their contents might be 
   * (consistently) shuffled on return.    
   *   for(k=0; k<= n; k++){
   *     a[subsArray[k][0]][subsArray[k][1]][subsArray[k][2]]... = v[k];    
   *   }
   * This is a one-sided operation.  
   * @param n   - number of elements              [input] 
   * @param  v[n]                - array containing values [input]        
   * @param  subsarray[n][ndim]  - array of subscripts for each element [input]
   */
  void scatter(in opaque v, in array<int,2,row-major> subsarray, in int n);

  /**
   * Solves a system of linear equations 
   *            A * X = B 
   * It first will call the Cholesky factorization routine and, if 
   * sucessfully, will solve the system with the Cholesky solver. If 
   * Cholesky will be not be able to factorize A, then it will call the 
   * LU factorization routine and will solve the system with forward/backward 
   * substitution. On exit B will contain the solution X. 
   * @return It returns 
   *            = 0 : Cholesky factoriztion was succesful 
   *            > 0 : the leading minor of this order 
   *                  is not positive definite, Cholesky factorization 
   *                  could not be completed and LU factoriztion was used 
   * This is a collective operation. 
   * @param  g_a     - coefficient matrix         [input]
   */
  int solve(in GlobalArray  g_a);

  /**
   * It computes the inverse of a double precision using the Cholesky 
   * factorization of a NxN double precision symmetric positive definite 
   * matrix A stored in the global array represented by g_a. On successful 
   * exit, A will contain the inverse. 
   * @return It returns 
   *            = 0 : successful exit 
   *            > 0 : the leading minor of this order is not positive 
   *                  definite and the factorization could not be completed 
   *            < 0 : it returns the index i of the (i,i) 
   *                  element of the factor L/U that is zero and 
   *                  the inverse could not be computed 
   * This is a collective operation. 
   */
  int spdInvert();

  /**
   * @return Returns the value and index for an element that is selected by the 
   * specified operator  in a global array corresponding to g_a handle. 
   * This is a collective operation. 
   * @param  op              - operator {"min","max"}               [input]
   * @param  val             - address where value should be stored [output] 
   * @param  subscript[ndim] - array index for the selected element [output]
   */
  void selectElem(in string op, in opaque val, in array<int> index);

  /** 
   * Symmmetrizes matrix A with handle A:=.5 * (A+A').
   * This is a collective operation 
   */
  void symmetrize();
  
  /**
   * Transposes a matrix: B = A', where A and B are represented by 
   * handles g_a and g_b. This is a collective operation.
   */
  void transpose(in GlobalArray g_a);

  /* int validHandle();*/

  /**
   * Computes element-wise dot product of the two arrays which must be of
   * the same types and same number of elements.
   *          return value = SUM_ij a(i,j)*b(i,j)
   * This is a collective operation. 
   * @param g_a   - array handle                 [input]
   */
  dcomplex zdot(in GlobalArray g_a); 

  /**
   * Computes the element-wise dot product of the two (possibly transposed) 
   * patches which must be of the same type and have the same number of 
   * elements. 
   * @param  g_a                  - array handles             [input]
   * @param  alo, ahi         - g_a patch coordinates     [input]
   * @param  blo, bhi         - g_b patch coordinates     [input]
   * @param  ta, tb               - transpose flags           [input]
   */
  dcomplex zdotPatch(in char ta, in array<int> alo, in array<int> ahi, 
			  in GlobalArray  g_a, in char tb, in array<int> blo, 
			  in array<int> bhi) ;
  
  /** 
   * Sets value of all elements in the array to zero. 
   * This is a collective operation. 
   */
   void zero();
  
  /**
   * Set all the elements in the patch to zero. 
   * This is a collective operation. 
   * @param  lo, hi                patch of g_a         [input]
   */
  void zeroPatch (in array<int> lo, in array<int> hi);
  
  /* Utility Methods */
  /** 
   * @return Returns the total number of elements in the global array. 
   * This operation is local.
   */
  int numElements();

  /** 
   * @return Returns the total number of elements owned by the calling
   * process. '0' is returned, if no elements are owned by the calling 
   * process. This operation is local.
   */
  int numElementsLocal();
  
  /**
   * Take element-wise absolute value of the array. 
   * This is a collective operation. 
   */
  void absValue(); 

  /**
   * Take element-wise absolute value of the patch. 
   * This is a collective operation.
   * @param lo, hi           - g_a patch coordinates   [input] 
   */
  void absValuePatch(in array<int> lo, in array<int> hi);

  /**
   * Add the constant pointed by alpha to each element of the array. 
   * This is a collective operation. 
   * @param double/complex/int/long/float      *alpha      [input] 
   */
  void addConstant(in opaque alpha);
 
  /**
   * Add the constant pointed by alpha to each element of the patch. 
   * This is a collective operation. 
   * @param lo, hi           - g_a patch coordinates  [input] 
   * @param double/complex/int/long/float      *alpha     [input] 
   */
  void addConstantPatch(in array<int> lo, in array<int> hi, in opaque alpha);
  
  /**
   * Take element-wise reciprocal of the array. 
   * This is a collective operation. 
   */
  void recip();
  
  /**
   * Take element-wise reciprocal of the patch. 
   * This is a collective operation. 
   * @param   lo, hi           - g_a patch coordinates     [input] 
   */
  void recipPatch(in array<int> lo, in array<int> hi);
  
  
  /**
   * Computes the element-wise product of the two arrays 
   * which must be of the same types and same number of 
   * elements. For two-dimensional arrays, 
   *
   *            c(i, j)  = a(i,j)*b(i,j) 
   *
   * The result (c) may replace one of the input arrays (a/b). 
   * This is a collective operation. 
   * @param g_a, g_b - array handles         [input] 
   */
  void elemMultiply(in GlobalArray g_a, in GlobalArray g_b);
  
  
  /**
   * Computes the element-wise product of the two patches 
   * which must be of the same types and same number of 
   * elements. For two-dimensional arrays, 
   * 
   *             c(i, j)  = a(i,j)*b(i,j) 
   * 
   * The result (c) may replace one of the input arrays (a/b). 
   * This is a collective operation.
   * @param g_a, g_b - array handles                           [input] 
   * @param alo, ahi           - g_a patch coordinates     [input] 
   * @param blo, bhi           - g_b patch coordinates     [input] 
   * @param clo, chi           - g_c patch coordinates     [output]  
   */ 
  void elemMultiplyPatch(in GlobalArray  g_a, in array<int> alo,
			 in array<int> ahi, in GlobalArray g_b,
			 in array<int> blo, in array<int> bhi,
			 in array<int> clo,in array<int> chi);

  /**
   * @param g_a, g_b - array handles         [input] 
   *
   * Computes the element-wise quotient of the two arrays 
   * which must be of the same types and same number of 
   * elements. For two-dimensional arrays, 
   * 
   *             c(i, j)  = a(i,j)/b(i,j) 
   * 
   * The result (c) may replace one of the input arrays (a/b). If one of 
   * the elements of array g_b is zero, the quotient for the element of g_c 
   * will be set to GA_NEGATIVE_INFINITY. 
   * This is a collective operation. 
   */
  void elemDivide(in GlobalArray g_a, in GlobalArray g_b);
  
  /**
   * Computes the element-wise quotient of the two patches 
   * which must be of the same types and same number of 
   * elements. For two-dimensional arrays, 
   *
   *            c(i, j)  = a(i,j)/b(i,j) 
   *
   * The result (c) may replace one of the input arrays (a/b). 
   * This is a collective operation. 
   * @param g_a, g_b - array handles                           [input] 
   * @param alo, ahi           - g_a patch coordinates     [input] 
   * @param blo, bhi           - g_b patch coordinates     [input] 
   * @param clo, chi           - g_c patch coordinates     [output] 
   *
   */ 
  void elemDividePatch(in GlobalArray  g_a,in array<int> alo,
		       in array<int> ahi, in GlobalArray g_b,
		       in array<int> blo, in array<int> bhi,
		       in array<int> clo,in array<int> chi);
  /**
   * Computes the element-wise maximum of the two arrays 
   * which must be of the same types and same number of 
   * elements. For two dimensional arrays, 
   *
   *                c(i, j)  = max{a(i,j), b(i,j)} 
   *
   * The result (c) may replace one of the input arrays (a/b). 
   * This is a collective operation. 
   * @param g_a, g_b - array handles         [input] 
   */
  void elemMaximum(in GlobalArray g_a, in GlobalArray g_b);
  
  
  /**
   * Computes the element-wise maximum of the two patches 
   * which must be of the same types and same number of 
   * elements. For two-dimensional of noncomplex arrays, 
   *
   *             c(i, j)  = max{a(i,j), b(i,j)} 
   *
   * If the data type is complex, then 
   *     c(i, j).real = max{ |a(i,j)|, |b(i,j)|} while c(i,j).image = 0. 
   *
   * The result (c) may replace one of the input arrays (a/b). 
   * This is a collective operation. 
   * @param g_a, g_b - array handles         [input]   
   * @param alo, ahi           - g_a patch coordinates     [input] 
   * @param blo, bhi           - g_b patch coordinates     [input] 
   * @param clo, chi           - g_c patch coordinates     [output] 
   */
  void elemMaximumPatch(in GlobalArray  g_a,in array<int> alo,
			in array<int> ahi, in GlobalArray g_b, 
			in array<int> blo, in array<int> bhi,
			in array<int> clo, in array<int> chi);
  /**
    * Computes the element-wise minimum of the two arrays 
    * which must be of the same types and same number of 
    * elements. For two dimensional arrays, 
    * 
    *             c(i, j)  = min{a(i,j), b(i,j)} 
    * 
    * The result (c) may replace one of the input arrays (a/b). 
    * This is a collective operation. 
    * @param g_a, g_b - array handles         [input] 
    */
   void elemMinimum(in GlobalArray g_a, in GlobalArray g_b);
   
   /**
    * Computes the element-wise minimum of the two patches 
    * which must be of the same types and same number of 
    * elements. For two-dimensional of noncomplex arrays, 
    * 
    *             c(i, j)  = min{a(i,j), b(i,j)} 
    * 
    * If the data type is complex, then 
    *             c(i, j).real = min{ |a(i,j)|, |b(i,j)|} while c(i,j).image = 0. 
    * 
    * The result (c) may replace one of the input arrays (a/b). 
    * This is a collective operation. 
    * @param g_a, g_b - array handles                           [input] 
    * @param alo, ahi           - g_a patch coordinates     [input] 
    * @param blo, bhi           - g_b patch coordinates     [input] 
    * @param clo, chi           - g_c patch coordinates     [output] 
    */
   void elemMinimumPatch(in GlobalArray g_a,in array<int> alo,
			 in array<int> ahi, in GlobalArray g_b,
			 in array<int> blo, in array<int> bhi,
			 in array<int> clo, in array<int> chi);
   
   /** 
    * Calculates the largest multiple of a vector g_b that can be added 
    * to this vector g_a while keeping each element of this vector 
    * nonnegative. 
    * This is a collective operation. 
    * @param g_a, g_b - array handles where g_b is the step direction.[input] 
    * @param step        - the maximum step                           [output] 
    */  
   void stepMax(in GlobalArray  g_a, in array<double> step);
   
   /** 
    * Calculates the largest step size that should be used in a projected 
    * bound line search. 
    * This is a collective operation. 
    * @param g_vv, g_xxll, g_xxuu - array handles              [input] 
    * @param step2 - the maximum step size                     [output] 
    * where 
    * g_vv - the step direction 
    * g_xxll - lower bounds 
    * g_xxuu - upper bounds 
    */
   void stepMax2(in GlobalArray  g_vv, 
		 in GlobalArray  g_xxll, 
		 in GlobalArray  g_xxuu, in array<double> step2);

   void stepMaxPatch(in array<int> alo, in array<int> ahi, 
		     in GlobalArray g_b, in array<int> blo, 
		     in array<int> bhi, in array<double> step);

   void stepMax2Patch(in array<int> xxlo, in array<int> xxhi, 
		      in GlobalArray  g_vv, in array<int> vvlo, 
		      in array<int> vvhi, 
		      in GlobalArray  g_xxll, in array<int> xxlllo, 
		      in array<int> xxllhi,
		      in GlobalArray  g_xxuu, in array<int> xxuulo, 
		      in array<int> xxuuhi, in array<double> step2);
   
  
  /** Matrix Operations */
  
  /** 
   * Adds this constant to the diagonal elements of the matrix. 
   * This is a collective operation. 
   * @param double/complex/int/long/float      *c               [input] 
   */
  void shiftDiagonal(in opaque c);
  
  /**
   * Sets the diagonal elements of this matrix g_a with the elements of the 
   * vector g_v.  This is a collective operation. 
   * @param g_v - array handles       [input]  
   */
  void setDiagonal(in GlobalArray  g_v);
  
  /**
   * Sets the diagonal elements of this matrix g_a with zeros. 
   * This is a collective operation. 
   */
  void zeroDiagonal();
  
  /**
   * Adds the elements of the vector g_v to the diagonal of this matrix g_a. 
   * This is a collective operation. 
   * @param g_v - array handles       [input] 
   */
  void addDiagonal(in GlobalArray g_v);
  
  /**
   * Inserts the diagonal elements of this matrix g_a into the vector g_v. 
   * This is a collective operation. 
   * @param g_v - array handles       [input] 
   */
  void getDiagonal(in GlobalArray g_a);
  
  /**
   * Scales the rows of this matrix g_a using the vector g_v. 
   * This is a collective operation.  
   * @param g_v - array handles       [input] 
   */
  void scaleRows(in GlobalArray g_v);
  
  /** 
   * Scales the columns of this matrix g_a using the vector g_v. 
   * This is a collective operation. 
   * @param g_v - array handles       [input] 
   */
  void scaleCols(in GlobalArray g_v);
  
  /**
   * Computes the 1-norm of the matrix or vector g_a. 
   * This is a collective operation. 
   * @param nm - matrix/vector 1-norm value 
   */
  void norm1(in array<double> nm);
  
  /**
   * Computes the 1-norm of the matrix or vector g_a. 
   * This is a collective operation. 
   * @param nm - matrix/vector 1-norm value 
   */
  void normInfinity(in array<double> nm);
  
  /**
   * Computes the componentwise Median of three arrays g_a, g_b, and g_c, and 
   * stores the result in this array g_m.  The result (m) may replace one of the 
   * input arrays (a/b/c). This is a collective operation. 
   * @param g_a, g_b, g_c- array handles       [input] 
   */
  void median(in GlobalArray g_a, in GlobalArray g_b, 
	      in GlobalArray g_c);
  
  /**
   * Computes the componentwise Median of three patches g_a, g_b, and g_c, and 
   * stores the result in this patch g_m.  The result (m) may replace one of the 
   * input patches (a/b/c). This is a collective operation. 
   * @param g_a, g_b, g_c - array handles         [input] 
   * @param alo, ahi           - g_a patch coordinates     [input] 
   * @param blo, bhi           - g_b patch coordinates     [input] 
   * @param clo, chi           - g_c patch coordinates     [intput] 
   * @param mlo, mhi           - g_m patch coordinates     [output] 
   */
  void medianPatch(in GlobalArray g_a, in array<int> alo, in array<int> ahi, 
		   in GlobalArray g_b, in array<int> blo, in array<int> bhi, 
		   in GlobalArray g_c, in array<int> clo, in array<int> chi, 
		   in array<int> mlo, in array<int> mhi);
  }
    

    /**  	
     * GAComponent : Global Arrays Component. 
     * 
     * Collecting the global information: who am I, and how many processors 
     * are being used. Initialize the communication library, either MPI or 
     * TCSMSG and Global Array. Allocate momory to be used by GA 
     * by calling MA and create global array objects.
     */
    class GAComponent implements-all GAPort, DADFPort, gov.cca.Component {
	
    }
}