Contribution to Octave-forge with a simple Open-MPI Package

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 | Next >

Contribution to Octave-forge with a simple Open-MPI Package

by Riccardo Corradini :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Dear Octave users,
for my econometric computations I have built a simple package that uses the concept of MPI-Derived datatypes ( see http://static.msi.umn.edu/tutorial/scicomp/general/MPI/content6.html )  to spread octave_values objects over octave instances.
This package gets a lot of ideas from MPI_TB for octave but is simpler, doesn't use MPI_PACK and MPI_UNPACK and is very easy to update with newer versions of Octave ( I tested it with octave 3.2.3 , but I am user it will work also with development-version).
 
Before doing that I would like to submit the functions to this list to know your opinions, warnings, improvements  and some hints on how to build an octave forge package with open-mpi bindings.
Thanks a lot for all your help and patience concerning this issue.
 
Respectfully
Riccardo Corradini
 


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Søren Hauberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

tir, 03 11 2009 kl. 12:25 +0000, skrev Riccardo Corradini:
> for my econometric computations I have built a simple package that
> uses the concept of MPI-Derived datatypes
> ( see http://static.msi.umn.edu/tutorial/scicomp/general/MPI/content6.html )  to spread octave_values objects over octave instances.
> This package gets a lot of ideas from MPI_TB for octave but is
> simpler, doesn't use MPI_PACK and MPI_UNPACK and is very easy to
> update with newer versions of Octave ( I tested it with octave 3.2.3 ,
> but I am user it will work also with development-version).

Cool! I'm currently not using Octave on a cluster, so I don't have any
MPI experience. Is your code general-purpose or is it designed for
econometrics?

> Before doing that I would like to submit the functions to this list to
> know your opinions, warnings, improvements  and some hints on how to
> build an octave forge package with open-mpi bindings.

As I said, I don't have any MPI experience, but feel free to send the
code to this list. I don't mind given it a quick look to see if I catch
anything, and perhaps others will provide their thoughts as well.

Søren


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Riccardo Corradini :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Søren,
thanks for your quick reply.
The code is general-purpose, but as I told you I would love to use it for econometrics.
So the first step will be to install the following tarball from
http://www.open-mpi.org/software/ompi/v1.3/downloads/openmpi-1.3.3.tar.bz2
possibly in a multi-core computer to run my simple examples
and configure it for instance in the following way (/home/user is your $HOME)
./configure --enable-mpirun-prefix-by-default --enable-heterogeneous --prefix=/home/user/openmpi-1.3.3/ --enable-static

and modify .bashrc in your home
 OMPIBIN=`$ompi_info -path     bindir  -parsable | cut -d: -f3`
 OMPILIB=`$ompi_info -path     libdir  -parsable | cut -d: -f3`
 OMPISCD=`$ompi_info -path sysconfdir  -parsable | cut -d: -f3`

 OSCBIN=~/oompi-1.0.4/bin

export            PATH=$OMPIBIN:$PATH
export          PATH=$OSCBIN:$PATH
export LD_LIBRARY_PATH=:$OMPILIB:$LD_LIBRARY_PATH

unset  ompi_info OMPIBIN OMPILIB OMPISCD OSCBIN

After this type in a terminal mpiCC --showme
In my case I will have something like

g++ -I/home/user/openmpi-1.3.3/include -pthread -L/home/user/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -Wl,--export-dynamic -lnsl -lutil -lm -ldl

This will be useful for mkoctfile

Now I will include the basic functions

// mkoctfile -I/home/corradin/openmpi-1.3.3/include -lpthread -L/home/corradin/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -lnsl -lutil -lm -ldl MPI_Init.cc
/*
## Copyright (C) 2004-2007 Javier Fernández Baldomero, Mancia Anguita López
##
## This program is free software
## ----------------------------------------------------
## Author: Javier Fernández Baldomero <jfernand@...>, Mancia Anguita López
## Keywords: parallel MPI
## tested on octave 3.2.3 by Riccardo Corradini
## ----------------------------------------------------
 */
#define   NAME  MPI_Init
/*
 * ----------------------------------------------------
 * Initialize the MPI execution environment
 * info = MPI_Init [ ( 'arg' [, 'arg']... ) ]
 * ----------------------------------------------------
 */
#include "mpi.h"        // mpi.h, oct.h
#include <octave/oct.h>

DEFUN_DLD(NAME, args, nargout,
"MPI_Init               Initialize the MPI execution environment\n\
\n\
  info = MPI_Init [ ( 'arg' [, 'arg']... ) ]\n\
\n\
  arg (str) arguments to pass\n\
  info(int) return code\n\
      0 MPI_SUCCESS    No error\n\
     16 MPI_ERR_OTHER  Attempt was made to call MPI_INIT a  second  time\n\
                       MPI_INIT may only be called once in a program\n\
                       \n\
\n\
  SEE ALSO: MPI_Finalize, MPI_Initialized, MPI_Finalized\n\
            misc\n\
\n\
")
{
    int nargin = args.length();            // Too flexible to use NARGCHK
/*
 * info = MPI_Init [ ( 'arg' [, 'arg']... ) ]
 */
    for (int i=0; i<nargin; i++){
    if( ! args(i).is_string() ) {
        error("MPI_Init: args must be strings");
        return octave_value (MPI_ERR_ARG);    // error returns nothing
    }
    }

    string_vector argvec = args.make_argv("MPI_Init");
    char **argve= argvec.c_str_vec();
    char **argv =&argve[1];

//  printf("args: "); for (int i=0; i<nargin; i++) printf("%s ",argv[i]);
//  printf("\n");

    int info = MPI_Init(&nargin, &argv);
//     int info = MPI::Init();
    free(argve);
    return octave_value (info);
}
 

#define   NAME  MPI_Comm_rank
/*
 * ----------------------------------------------------
 * Determines the rank of the calling process in the communicator
 * [info rank] = MPI_Comm_rank (comm)
 * ----------------------------------------------------
 */

#include <octave/oct.h>
#include "mpi.h"       

DEFUN_DLD(NAME, args, nargout,
"MPI_Comm_rank          Determines rank of calling process in communicator\n\
\n\
  [info rank] =  MPI_Comm_rank (comm)\n\
\n\
  comm (int) communicator handle. MPI_COMM_NULL not valid\n\
  rank (int) rank of the calling process in group of comm\n\
\n\
  info (int) return code\n\
      0 MPI_SUCCESS    No error\n\
      5 MPI_ERR_COMM   Invalid communicator (NULL?)\n\
     13 MPI_ERR_ARG    Invalid argument (typically a NULL pointer?)\n\
\n\
  SEE ALSO: MPI_Comm_size\n\
            comms\n\
\n\
")

{
    octave_value_list results;
    int my_rank;
    int info = MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
    results(0) = info;
    results(1) = my_rank;

    /* [info rank] = MPI_Comm_rank (comm) */
   
    return results;
}

#define   NAME  MPI_Comm_size
/*
 * ----------------------------------------------------
 * Determines the size of the calling process in the communicator
 * [info rank] = MPI_Comm_size (comm)
 * ----------------------------------------------------
 */

#include <octave/oct.h>
#include "mpi.h"       

DEFUN_DLD(NAME, args, nargout,
"MPI_Comm_size          Determines rank of calling process in communicator\n\
\n\
  [info rank] =  MPI_Comm_size (comm)\n\
\n\
  comm (int) communicator handle. MPI_COMM_NULL not valid\n\
  size (int) size of the calling process in group of comm\n\
\n\
  info (int) return code\n\
      0 MPI_SUCCESS    No error\n\
      5 MPI_ERR_COMM   Invalid communicator (NULL?)\n\
     13 MPI_ERR_ARG    Invalid argument (typically a NULL pointer?)\n\
\n\
  SEE ALSO: MPI_Comm_rank\n\
            comms\n\
\n\
")

{
    octave_value_list results;
    int my_size;
    int info = MPI_Comm_size(MPI_COMM_WORLD,&my_size);
    results(0) = info;
    results(1) = my_size;

    /* [info rank] = MPI_Comm_size (comm) */
   
    return results;
}


#define   NAME    MPI_Finalize
/*
 * ----------------------------------------------------
 * Terminates MPI execution environment
 * info = MPI_Finalize
 * ----------------------------------------------------
 */
#include "mpi.h"       
#include <octave/oct.h>

DEFUN_DLD(NAME, args, nargout,
"MPI_Finalize           Terminates MPI execution environment\n\
\n\
  info = MPI_Finalize\n\
\n\
  info(int) return code\n\
      0 MPI_SUCCESS    No error\n\
     17 MPI_ERR_INTERN This is fatal. Please send bug report to LAM\n\
     16 MPI_ERR_OTHER  A different thread attempts to finalize MPI than\n\
                       the thread that initialized MPI\n\
\n\
  SEE ALSO: MPI_Init, MPI_Initialized, MPI_Finalized\n\
            misc\n\
\n\
")
{

    int info = MPI_Finalize();
   
    return octave_value(info);
}

#define   NAME  MPI_Finalized
/*
 * ----------------------------------------------------
 * Indicates whether MPI_Finalize has completed
 * [info flag] = MPI_Finalized
 * ----------------------------------------------------
 */
#include "mpi.h"       
#include <octave/oct.h>

DEFUN_DLD(NAME, args, nargout,
"MPI_Finalized          Indicates whether MPI_Finalize has completed\n\
\n\
  [info flag] = MPI_Finalized\n\
\n\
  flag(int) 0 false\n\
            1 true\n\
\n\
  info(int) return code\n\
      0 MPI_SUCCESS    This function always returns MPI_SUCCESS\n\
\n\
  SEE ALSO: MPI_Init, MPI_Finalize, MPI_Initialized\n\
            misc\n\
\n\
")
{
   octave_value_list results;
    int flag;            // Too flexible to use NARGCHK



    int info = MPI_Finalized(&flag);
    results(0) = info;
    results(1) = flag;
    return results;

    /* [info flag] = MPI_Finalized */
}

// mkoctfile -lpthread -L/home/user/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl  -lnsl -lutil -lm -ldl MPI_Initialized.cc

#define   NAME  MPI_Initialized
/*
 * ----------------------------------------------------
 * Indicates whether MPI_Init has been called
 * [info flag] = MPI_Initialized
 * ----------------------------------------------------
 */
#include "mpi.h"       
#include <octave/oct.h>

DEFUN_DLD(NAME, args, nargout,
"MPI_Initialized        Indicates whether MPI_Init has been called\n\
\n\
  [info flag] = MPI_Initialized\n\
\n\
  flag(int) 0 false\n\
            1 true\n\
\n\
  info(int) return code\n\
      0 MPI_SUCCESS    This function always returns MPI_SUCCESS\n\
\n\
  SEE ALSO: MPI_Init, MPI_Finalize,\n\
            misc\n\
\n\
")
{
   octave_value_list results;
    int flag;            // Too flexible to use NARGCHK



    int info = MPI_Initialized(&flag);
    results(0) = info;
    results(1) = flag;
    return results;
}

The following two functions MPI_Send and MPI_Recv are my real simple original contribution (I will report some test script as well)

MPI_Send.cc

// mkoctfile -lpthread  -I/home/user/openmpi-1.3.3/include/  -L/home/user/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl  -lnsl -lutil -lm -ldl MPI_Send.cc

// mkoctfile -lpthread  -I/home/corradin/openmpi-1.3.3/include/  -L/home/corradin/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl  -lnsl -lutil -lm -ldl MPI_Send.cc


/*
 * sends most Octave datatypes into contiguous memory
 * using derived datatypes
 * info = MPI_Send(var,rank)
 */
#include "mpi.h"   
#include <octave/oct.h>
#include <ov-cell.h>    // avoid errmsg "cell -- incomplete datatype"
#include <oct-map.h>    // avoid errmsg "Oct.map -- invalid use undef type"

enum ov_t_id
{

ov_unknown=0,
ov_cell,            // 1
ov_scalar,            // 2
ov_complex_scalar,        // 3
ov_matrix,            // 4
ov_diagonal_matrix,        // 5
ov_complex_matrix,        // 6
ov_complex_diagonal_matrix,        // 7
ov_range,            // 8
ov_bool,            // 9
ov_bool_matrix,            // 10
ov_char_matrix,            // 11
ov_string,            // 12
ov_sq_string,            // 13
ov_int8_scalar,            // 14
ov_int16_scalar,        // 15
ov_int32_scalar,        // 16
ov_int64_scalar,        // 17
ov_uint8_scalar,        // 18
ov_uint16_scalar,        // 19
ov_uint32_scalar,        // 20
ov_uint64_scalar,        // 21
ov_int8_matrix,            // 22
ov_int16_matrix,        // 23
ov_int32_matrix,        // 24
ov_int64_matrix,        // 25
ov_uint8_matrix,        // 26
ov_uint16_matrix,        // 27
ov_uint32_matrix,        // 28
ov_uint64_matrix,        // 29
ov_sparse_bool_matrix,        // 30
ov_sparse_matrix,        // 31
ov_sparse_complex_matrix,    // 32
ov_struct,            // 33
ov_class,            // 34
ov_list,            // 35
ov_cs_list,            // 36
ov_magic_colon,            // 37
ov_built_in_function,        // 38
ov_user_defined_function,    // 39   
ov_dynamically_linked_function,    // 40
ov_function_handle,        // 41
ov_inline_function,        // 42
ov_float_scalar,        // 43
ov_float_complex_scalar,    // 44
ov_float_matrix,        // 45
ov_float_diagonal_matrix,    // 46
ov_float_complex_matrix,    // 47
ov_float_complex_diagonal_matrix,    // 48
ov_permutation_matrix,            // 49
ov_null_matrix,                // 50
ov_null_string,                // 51
ov_null_sq_string,            // 52
};




/*----------------------------------*/        /* forward declaration */



int send_class( octave_value ov,  ColumnVector rankrec, int mytag);        /* along the datatype */
/*----------------------------------*/    /* to send any octave_value */
int send_scalar( double d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a double value */
  int info;
  int t_id = ov_scalar;
  int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_DOUBLE, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}

int send_float_scalar( float d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a double value */
  int info;
  int t_id = ov_float_scalar;
  int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_FLOAT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}

int send_i8( octave_int8 d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a double value */
  int info;
  int t_id = ov_int8_scalar;
  int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_BYTE, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}

int send_i16( octave_int16 d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a double value */
  int info;
  int t_id = ov_int16_scalar;
  OCTAVE_LOCAL_BUFFER(int,tanktag,2);
//   int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_SHORT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}

int send_i32( octave_int32 d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a double value */
  int info;
  int t_id = ov_int32_scalar;
  OCTAVE_LOCAL_BUFFER(int,tanktag,2);
//   int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}

int send_i64( octave_int64 d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a value */
  int info;
  int t_id = ov_int64_scalar;
  OCTAVE_LOCAL_BUFFER(int,tanktag,2);
//   int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_LONG_LONG, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}

int send_ui64( octave_uint64 d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a  value */
  int info;
  int t_id = ov_uint64_scalar;
  OCTAVE_LOCAL_BUFFER(int,tanktag,2);
//   int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_UNSIGNED_LONG_LONG, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}

int send_ui32( octave_uint32 d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a value */
  int info;
  int t_id = ov_uint32_scalar;
  OCTAVE_LOCAL_BUFFER(int,tanktag,2);
//   int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_UNSIGNED, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}

int send_ui16( octave_uint16 d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a  value */
  int info;
  int t_id = ov_uint16_scalar;
  OCTAVE_LOCAL_BUFFER(int,tanktag,2);
//   int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_UNSIGNED_SHORT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}


int send_ui8( octave_uint8 d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a value */
  int info;
  int t_id = ov_uint8_scalar;
  OCTAVE_LOCAL_BUFFER(int,tanktag,2);
//   int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_UNSIGNED_CHAR, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}



int send_bool( int d, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a  value */
  int info;
  int t_id = ov_bool;
  int tanktag[2];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 1,MPI_DOUBLE, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}



int send_complex_scalar( Complex c, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a value */
  int info;
  int t_id = ov_complex_scalar;
  OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  OCTAVE_LOCAL_BUFFER(double,d,2);
  d[0] = real(c);
  d[1] = imag(c);
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 2,MPI_DOUBLE, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}

int send_float_complex_scalar( std::complex<float>  c, ColumnVector rankrec, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a double value */
  int info;
  int t_id = ov_float_complex_scalar;
  OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  OCTAVE_LOCAL_BUFFER(float,d,2);
  d[0] = real(c);
  d[1] = imag(c);
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info = MPI_Send((&d), 2,MPI_FLOAT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
   return(MPI_SUCCESS);
}



int send_string(std::string  oi8,ColumnVector rankrec, int mytag){        /* directly pvm_pkbyte it, */
/*----------------------------------*/        /* just a char value */
  int info;
  int nitem = oi8.length();
  int tanktag[3];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  tanktag[2] = mytag+2;
//   OCTAVE_LOCAL_BUFFER(char,i8,nitem+1);
   char i8[nitem+1];
  strcpy(i8, oi8.c_str());
  int t_id = ov_string;

// Here we declare a contiguous derived datatype
// Create a contiguous datatype for the fortranvec
MPI_Datatype fortvec;
MPI_Type_contiguous(nitem,MPI_CHAR, &fortvec);
MPI_Type_commit(&fortvec);



  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
      printf("Sending block to %i \n",rankrec(i));   
          printf("Sending block with tag to %i \n",mytag);
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), mytag, MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      printf("Sending type of object  %i \n",t_id);   
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("Sending nitem  %i \n",nitem);   
      if (info !=MPI_SUCCESS) return info;
      info =  MPI_Send(&i8,1,fortvec,rankrec(i),tanktag[2],MPI_COMM_WORLD);
          printf("Info for sending fortvec  %i \n",info);   
      if (info !=MPI_SUCCESS) return info;
  }

    return(info);

}
/*-----------------------------------*/        /* to pack a struct */
int send_struct(Octave_map map,ColumnVector rankrec, int mytag){        /* we store nkeys, */

int n = map.nfields(); 
int info;
int t_id;
int tanktag[3];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  tanktag[2] = mytag+2;
int newtag = mytag+3;

// Create 3 contiguous derived datatype
// one for dim_vector struc_dims

  dim_vector struc_dims = map.dims();    // struct array dimensions (ND)
  dim_vector conts_dims;        // each key stores ND field-values

  int nd = map.ndims();

// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = struc_dims(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);


// Create a derived datatype containing three integer;
// n nd maxlenght
typedef struct
{ int sn, snd,smlenght;
} Particle;

Particle part;
MPI_Datatype particletype, oldtypes[1];
int blockcounts[1];

MPI_Aint offsets[1];
// MPI_Status

/* Setup description of 3 MPI_INT fields */
offsets[0] =0;
oldtypes[0] = MPI_INT;
blockcounts[0] = 3;
/* Now define structured type and commit */
MPI_Type_struct(1,blockcounts, offsets, oldtypes, &particletype);
MPI_Type_commit(&particletype);

/* Initialize the particle */
part.sn = n;
part.snd = nd; 

octave_idx_type  maxlen;

  Octave_map::const_iterator p = map.begin();    // iterate through keys(fnames)
  for (octave_idx_type i=0; p!=map.end(); p++, i++){
    std::string        key = map.key     (p);    // field name

    int len = key.length()+1;        /* fieldname len, works for len==0 */
    if  (len> maxlen) maxlen = len;
    Cell           conts = map.contents(p);
    conts_dims = conts.dims();        /* each elemt should have same ND */
    if (struc_dims != conts_dims){
        printf("MPI_Send: inconsistent map dims\n"); return(MPI_ERR_UNKNOWN);
    }
  if (n != map.nfields()){
      printf("MPI_Send: inconsistent map length\n");return(MPI_ERR_UNKNOWN);
  }
 }

part.smlenght  = maxlen;

MPI_Datatype fortvec;
MPI_Type_contiguous(maxlen,MPI_CHAR, &fortvec);
MPI_Type_commit(&fortvec);

// Now we start the big loop
  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// Send the particle struct derived datatype
    info = MPI_Send(&part,1,particletype,rankrec(i),tanktag[1],MPI_COMM_WORLD);
// Dimension vector
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;

    }
Octave_map::const_iterator b = map.begin();    // iterate through keys(fnames)
    for (octave_idx_type i=0; b!=map.end(); b++, i++){
        Cell           conts = map.contents(p);    // Cell w/ND contents
        newtag = newtag + conts.capacity();
        int info =send_class(conts,rankrec,newtag);
        if (info !=MPI_SUCCESS) return info;
        }

return(MPI_SUCCESS);
}


int send_cell(Cell cell, ColumnVector rankrec, int mytag){    /* we first store nelems and then */
/*----------------------------*/    /* recursively the elements themselves */

// Lists of items to send
// type_id to identify octave_value
// n for the cell capacity
// nd for number of dimensions
// dimvec derived datatype
// item of cell
  int t_id = ov_cell;
  int n = cell.capacity();
  int info;
  int tanktag[5];
  tanktag[0] = mytag;
  tanktag[1] = mytag+1;
  tanktag[2] = mytag+2;
  tanktag[3] = mytag+3;
  tanktag[4] = mytag+4;
  int newtag = tanktag[4];
  dim_vector    vdim   = cell. dims();
  int nd = cell.ndims();

// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = vdim(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);


// Now start the big loop

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send cell capacity
          info = MPI_Send(&n, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the dim vector
      info =  MPI_Send(dimV,1,dimvec,rankrec(i),tanktag[3],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }

// Now focus on every single octave_value
         for (octave_idx_type i=0; i<n; i++){
             octave_value ov = cell.data()[i];
         newtag = newtag +ov.capacity();
        info=send_class(ov,rankrec,newtag);
        if (info !=MPI_SUCCESS) return info;
        }



  return(MPI_SUCCESS); 


}

int send_sp_mat(SparseMatrix m ,ColumnVector rankrec, int mytag  ){

int info;
int t_id = ov_sparse_matrix;
int tanktag[5];
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[4] = mytag+4;
// octave_idx_type nr = m.rows ();
// octave_idx_type nc = m.cols ();
// octave_idx_type nz = m.nnz ();

OCTAVE_LOCAL_BUFFER(int,s,3);  
s[0]= m.rows();
s[1]= m.cols();
s[2]= m.capacity();// int n = m.capacity();

// Create a contiguous derived datatype// OCTAVE_LOCAL_BUFFER( double ,data,n);
MPI_Datatype sintsparse;// OCTAVE_LOCAL_BUFFER( int ,ridx,n);
MPI_Type_contiguous(3,MPI_INT, &sintsparse);
MPI_Type_commit(&sintsparse);


MPI_Datatype rowindex;
MPI_Type_contiguous(m.capacity(),MPI_INT, &rowindex);
MPI_Type_commit(&rowindex);

MPI_Datatype columnindex;
MPI_Type_contiguous(m.cols()+1,MPI_INT, &columnindex);
MPI_Type_commit(&columnindex);

MPI_Datatype numnnz;
MPI_Type_contiguous(m.capacity(),MPI_DOUBLE, &numnnz);
MPI_Type_commit(&numnnz);


OCTAVE_LOCAL_BUFFER( int ,sridx,m.capacity());
OCTAVE_LOCAL_BUFFER( int ,scidx,m.cols()+1);
OCTAVE_LOCAL_BUFFER( double ,sdata,m.capacity());
// Fill them with their respective value
  for (octave_idx_type ix = 0; ix < m.capacity(); ix++)
  {
      sdata[ix]=m.data(ix);
//       printf("sending %d \n",sdata[ix]);   
      sridx[ix]= m.ridx(ix);
//        printf("sending %i \n",sridx[ix]);   
  }
NDArray buf (dim_vector (m.capacity(), 1));
  for (int ix = 0; ix < m.capacity(); ix++)
  {
      buf(ix)=m.data(ix);
      sdata[ix] = buf(ix);
//     printf("sending buffer %d \n",sdata[ix]);
  }
  for (octave_idx_type ix = 0; ix < m.cols()+1; ix++)
  {
      scidx[ix]= m.cidx(ix);   
//        printf("sending %i \n",scidx[ix]);   

  }



  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the sintsparse vector named s
          info = MPI_Send(s, 1, sintsparse, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the vector with row indexes
      info =  MPI_Send(sridx,1,rowindex,rankrec(i),tanktag[2],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the vector with column indexes
      info =  MPI_Send(scidx,1,columnindex,rankrec(i),tanktag[3],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the vector of non zero elements
      info =  MPI_Send(sdata,1,numnnz,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }


return(info);
}





int send_sp_bl_mat(SparseBoolMatrix m ,ColumnVector rankrec, int mytag  ){

int info;
int t_id = ov_sparse_matrix;
int tanktag[5];
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[4] = mytag+4;
// octave_idx_type nr = m.rows ();
// octave_idx_type nc = m.cols ();
// octave_idx_type nz = m.nnz ();

OCTAVE_LOCAL_BUFFER(int,s,3);  
s[0]= m.rows();
s[1]= m.cols();
s[2]= m.capacity();// int n = m.capacity();

// Create a contiguous derived datatype// OCTAVE_LOCAL_BUFFER( double ,data,n);
MPI_Datatype sintsparse;// OCTAVE_LOCAL_BUFFER( int ,ridx,n);
MPI_Type_contiguous(3,MPI_INT, &sintsparse);
MPI_Type_commit(&sintsparse);


MPI_Datatype rowindex;
MPI_Type_contiguous(m.capacity(),MPI_INT, &rowindex);
MPI_Type_commit(&rowindex);

MPI_Datatype columnindex;
MPI_Type_contiguous(m.cols()+1,MPI_INT, &columnindex);
MPI_Type_commit(&columnindex);

MPI_Datatype numnnz;
MPI_Type_contiguous(m.capacity(),MPI_INT, &numnnz);
MPI_Type_commit(&numnnz);


OCTAVE_LOCAL_BUFFER( int ,sridx,m.capacity());
OCTAVE_LOCAL_BUFFER( int ,scidx,m.cols()+1);
OCTAVE_LOCAL_BUFFER( int ,sdata,m.capacity());
// Fill them with their respective value
  for (octave_idx_type ix = 0; ix < m.capacity(); ix++)
  {
      sdata[ix]=m.data(ix);
//       printf("sending %d \n",sdata[ix]);   
      sridx[ix]= m.ridx(ix);
//        printf("sending %i \n",sridx[ix]);   
  }
  for (octave_idx_type ix = 0; ix < m.cols()+1; ix++)
  {
      scidx[ix]= m.cidx(ix);   
//        printf("sending %i \n",scidx[ix]);   

  }



  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the sintsparse vector named s
          info = MPI_Send(s, 1, sintsparse, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the vector with row indexes
      info =  MPI_Send(sridx,1,rowindex,rankrec(i),tanktag[2],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the vector with column indexes
      info =  MPI_Send(scidx,1,columnindex,rankrec(i),tanktag[3],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the vector of non zero elements
      info =  MPI_Send(sdata,1,numnnz,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }


return(info);
}

int send_sp_cx_mat(SparseComplexMatrix m ,ColumnVector rankrec, int mytag  ){

int info;
int t_id = ov_sparse_complex_matrix;
OCTAVE_LOCAL_BUFFER(int,tanktag,6);
// int tanktag[5];
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[4] = mytag+4;
tanktag[5] = mytag+5;

OCTAVE_LOCAL_BUFFER(int,s,3);  
s[0]= m.rows();
s[1]= m.cols();
s[2]= m.capacity();// int n = m.capacity();

// Create a contiguous derived datatype// OCTAVE_LOCAL_BUFFER( double ,data,n);
MPI_Datatype sintsparse;// OCTAVE_LOCAL_BUFFER( int ,ridx,n);
MPI_Type_contiguous(3,MPI_INT, &sintsparse);
MPI_Type_commit(&sintsparse);


MPI_Datatype rowindex;
MPI_Type_contiguous(m.capacity(),MPI_INT, &rowindex);
MPI_Type_commit(&rowindex);

MPI_Datatype columnindex;
MPI_Type_contiguous(m.cols()+1,MPI_INT, &columnindex);
MPI_Type_commit(&columnindex);

MPI_Datatype numnnz;
MPI_Type_contiguous(m.capacity(),MPI_DOUBLE, &numnnz);
MPI_Type_commit(&numnnz);


OCTAVE_LOCAL_BUFFER( int ,sridx,m.capacity());
OCTAVE_LOCAL_BUFFER( int ,scidx,m.cols()+1);
OCTAVE_LOCAL_BUFFER( double ,rsdata,m.capacity());
OCTAVE_LOCAL_BUFFER( double ,isdata,m.capacity());
// Fill them with their respective value
  for (octave_idx_type ix = 0; ix < m.capacity(); ix++)
  {
      rsdata[ix]=real(m.data(ix));
      isdata[ix]=imag(m.data(ix));
//       printf("sending %d \n",sdata[ix]);   
      sridx[ix]= m.ridx(ix);
//        printf("sending %i \n",sridx[ix]);   
  }
  for (octave_idx_type ix = 0; ix < m.cols()+1; ix++)
  {
      scidx[ix]= m.cidx(ix);   
//        printf("sending %i \n",scidx[ix]);   

  }



  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the sintsparse vector named s
          info = MPI_Send(s, 1, sintsparse, rankrec(i), tanktag[1], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the vector with row indexes
      info =  MPI_Send(sridx,1,rowindex,rankrec(i),tanktag[2],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the vector with column indexes
      info =  MPI_Send(scidx,1,columnindex,rankrec(i),tanktag[3],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// send the vector of non zero elements
// real
      info =  MPI_Send(rsdata,1,numnnz,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
// img
      info =  MPI_Send(isdata,1,numnnz,rankrec(i),tanktag[5],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;

  }


return(info);
}


int send_complex_matrix(ComplexNDArray myCNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myCNDA.nelem();
  dim_vector dv = myCNDA.dims();
  OCTAVE_LOCAL_BUFFER(int,tanktag,6);
//   int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;
tanktag[5]= tanktag[4]+1;

  int nd = myCNDA.ndims ();
  int t_id = ov_complex_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

  NDArray rarray = real(myCNDA);
  NDArray imarray = imag(myCNDA);
  double *preal  = rarray.fortran_vec();
  double *pimag  = imarray.fortran_vec();

// two fortran_vec one for the real part and other one for the complex part
    OCTAVE_LOCAL_BUFFER(double,LBNDA,nitem);
  OCTAVE_LOCAL_BUFFER(double,CLBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = rarray(i) ;
      CLBNDA[i] = imarray(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_DOUBLE, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info =  MPI_Send(CLBNDA,1,fortvec,rankrec(i),tanktag[5],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;

  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}



int send_float_complex_matrix(FloatComplexNDArray myCNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myCNDA.nelem();
  dim_vector dv = myCNDA.dims();
  OCTAVE_LOCAL_BUFFER(int,tanktag,6);
//   int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;
tanktag[5]= tanktag[4]+1;

  int nd = myCNDA.ndims ();
  int t_id = ov_float_complex_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

  FloatNDArray rarray = real(myCNDA);
  FloatNDArray imarray = imag(myCNDA);
  float *preal  = rarray.fortran_vec();
  float *pimag  = imarray.fortran_vec();

// two fortran_vec one for the real part and other one for the complex part
    OCTAVE_LOCAL_BUFFER(float,LBNDA,nitem);
  OCTAVE_LOCAL_BUFFER(float,CLBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = rarray(i) ;
      CLBNDA[i] = imarray(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_FLOAT, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
      info =  MPI_Send(CLBNDA,1,fortvec,rankrec(i),tanktag[5],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;

  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}




int send_range(Range range,ColumnVector rankrec, int mytag){        /* put base,limit,incr,nelem */
/*-------------------------------*/        /* just 3 doubles + 1 int */
// octave_range (double base, double limit, double inc)
  OCTAVE_LOCAL_BUFFER(double,d,3);
  d[0]= range.base();
  d[1]= range.limit();
  d[2]= range.inc();
  int info;
    for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
  info = MPI_Send(d, 3, MPI_INT, rankrec(i), mytag, MPI_COMM_WORLD);
  }
   if (info !=MPI_SUCCESS) return info;
return(MPI_SUCCESS);
}

int send_matrix(NDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();
  OCTAVE_LOCAL_BUFFER(int,tanktag,5);
//   int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= mytag+1;
tanktag[2]= mytag+2;
tanktag[3]= mytag+3;
tanktag[4]= mytag+4;


  int nd = myNDA.ndims ();
  int t_id = ov_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(double,LBNDA,nitem);
    double *p  = myNDA.fortran_vec();

  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_DOUBLE, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}

// Here we have float_matrix
int send_float_matrix(FloatNDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();

  int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_float_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(float,LBNDA,nitem);
    float *p  = myNDA.fortran_vec();

  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_FLOAT, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}




int send_i8_mat(int8NDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();

  int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_int8_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(octave_int8,LBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_BYTE, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}





int send_i16_mat(int16NDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();

  int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_int16_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(octave_int16,LBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_SHORT, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}


int send_i32_mat(int32NDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();

  int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_int32_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(octave_int32,LBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_INT, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}

int send_i64_mat(int64NDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();

  int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_int64_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(octave_int64,LBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_LONG_LONG, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}
int send_ui8_mat(uint8NDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();

  int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_uint8_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(octave_uint8,LBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_UNSIGNED_CHAR, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}

int send_ui16_mat(uint16NDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();

  int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_uint16_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(octave_uint16,LBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_UNSIGNED_SHORT, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}
int send_ui32_mat(uint32NDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();

  int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_uint32_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(octave_uint32,LBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_UNSIGNED, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}




int send_ui64_mat(uint64NDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();

  int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_uint64_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(octave_uint64,LBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_UNSIGNED_LONG_LONG, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}




int send_ch_mat(charNDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();
 
OCTAVE_LOCAL_BUFFER(int,tanktag,5);
//   int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_char_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(char,LBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_CHAR, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}



int send_bl_mat(boolNDArray myNDA,ColumnVector rankrec, int mytag){       
  int info;
  int nitem = myNDA.nelem();
  dim_vector dv = myNDA.dims();

  int  tanktag[5];
tanktag[0] = mytag;
tanktag[1]= tanktag[0]+1;
tanktag[2]= tanktag[1]+1;
tanktag[3]= tanktag[2]+1;
tanktag[4]= tanktag[3]+1;


  int nd = myNDA.ndims ();
  int t_id = ov_matrix;
// Declare here the octave_local_buffers
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
 for (octave_idx_type i=0; i<nd; i++)
 {
  dimV[i] = dv(i) ;
 }

  // Now create the contiguos derived datatype
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

    OCTAVE_LOCAL_BUFFER(int,LBNDA,nitem);

  for (octave_idx_type i=0; i<nitem; i++)
  {
      LBNDA[i] = myNDA(i) ;
  }

  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_INT, &fortvec);
  MPI_Type_commit(&fortvec);

  for (octave_idx_type  i = 0; i< rankrec.nelem(); i++)
  {
//       t_id is the identifier of octave NDArray
      printf("Sending block to %i \n",rankrec(i));   
          info = MPI_Send(&t_id, 1, MPI_INT, rankrec(i), tanktag[0], MPI_COMM_WORLD); 
        printf("I have sent  %i \n",t_id);
      if (info !=MPI_SUCCESS) return info;
//       nitem is the total number of elements 
          info = MPI_Send(&nitem, 1, MPI_INT, rankrec(i), tanktag[1], MPI_COMM_WORLD);
          printf("I have sent  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Send(&nd, 1, MPI_INT, rankrec(i), tanktag[2], MPI_COMM_WORLD);
      printf("I have sent  %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//    vector of dimensions sending
          info = MPI_Send(dimV, 1, dimvec, rankrec(i), tanktag[3], MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
//      data matrix sending
      info =  MPI_Send(LBNDA,1,fortvec,rankrec(i),tanktag[4],MPI_COMM_WORLD);
      if (info !=MPI_SUCCESS) return info;
  }
//    printf("info for sending scalar matrix is = %i \n",info);
return(info);
}



int send_class(octave_value ov, ColumnVector rankrec,int mytag){    /* varname-strlength 1st, dims[ndim] */
/*----------------------------------*/    /* and then appropriate specific info */
  int t_id = ov.type_id();
//   printf("t_id =%i\n",t_id);

 
// The T_id would be the tag





  switch (t_id) {
      case ov_cell:    return(send_cell   (ov.cell_value   (),rankrec,mytag));
 
      case ov_scalar:    return(send_scalar (ov.scalar_value (),rankrec,mytag));
      case ov_complex_scalar:    return(send_complex_scalar(ov.complex_value(),rankrec,mytag));
      case ov_matrix:    return(send_matrix (ov.array_value  (),rankrec,mytag));
      case ov_sparse_matrix:  return(send_sp_mat (ov.sparse_matrix_value (),rankrec,mytag));
      case ov_complex_matrix:    return(send_complex_matrix(ov.complex_array_value(),rankrec,mytag));
      case ov_sparse_complex_matrix:  return(send_sp_cx_mat(ov.sparse_complex_matrix_value (),rankrec,mytag));

      case ov_float_scalar:    return(send_float_scalar (ov.float_scalar_value (),rankrec,mytag));
      case ov_float_complex_scalar:    return(send_float_complex_scalar(ov.float_complex_value(),rankrec,mytag));

      case ov_float_matrix:    return(send_float_matrix (ov.array_value  (),rankrec,mytag));
      case ov_float_complex_matrix:    return(send_float_complex_matrix(ov.float_complex_array_value(),rankrec,mytag));

      case ov_range:    return(send_range  (ov.range_value  (),rankrec,mytag));

      case ov_bool:    return(send_bool   (ov.bool_value   (),rankrec,mytag));
      case ov_bool_matrix:    return(send_bl_mat (ov.bool_array_value(),rankrec,mytag));
     case ov_sparse_bool_matrix:  return(send_sp_bl_mat (ov.sparse_bool_matrix_value (),rankrec,mytag));
     case ov_char_matrix:    return(send_ch_mat (ov.char_array_value(),rankrec,mytag));
    case ov_string:    return(send_string (ov.string_value(),rankrec,mytag));
    case ov_sq_string:  return(send_string (ov.string_value(),rankrec,mytag));

     case ov_int8_scalar:    return(send_i8     (ov.int8_scalar_value(),rankrec,mytag));
     case ov_int16_scalar:    return(send_i16    (ov.int16_scalar_value(),rankrec,mytag));
     case ov_int32_scalar:    return(send_i32    (ov.int32_scalar_value (),rankrec,mytag));
     case ov_int64_scalar:    return(send_i64    (ov.int32_scalar_value (),rankrec,mytag));

     case ov_uint8_scalar:    return(send_ui8     (ov.uint8_scalar_value(),rankrec,mytag));
     case ov_uint16_scalar:    return(send_ui16    (ov.uint16_scalar_value(),rankrec,mytag));
     case ov_uint64_scalar:    return(send_ui64    (ov.uint32_scalar_value(),rankrec,mytag));

    case ov_int8_matrix:    return(send_i8_mat (ov.int8_array_value(),rankrec,mytag));
    case ov_int16_matrix:    return(send_i16_mat(ov.int16_array_value(),rankrec,mytag));
    case ov_int32_matrix:    return(send_i32_mat(ov.int32_array_value(),rankrec,mytag));
    case ov_int64_matrix:    return(send_i32_mat(ov.int64_array_value(),rankrec,mytag));


    case ov_uint8_matrix:    return(send_ui8_mat (ov.uint8_array_value(),rankrec,mytag));
    case ov_uint16_matrix:    return(send_ui16_mat(ov.uint16_array_value(),rankrec,mytag));
    case ov_uint32_matrix:    return(send_ui32_mat(ov.uint32_array_value(),rankrec,mytag));
    case ov_uint64_matrix:    return(send_ui64_mat(ov.int64_array_value(),rankrec,mytag));


     case ov_struct:    return(send_struct (ov.map_value    (),rankrec,mytag));

     case ov_unknown:    printf("MPI_Send: unknown class\n");
             return(MPI_ERR_UNKNOWN );

case ov_class:           
case ov_list:           
case ov_cs_list:           
case ov_magic_colon:           
case ov_built_in_function:       
case ov_user_defined_function:       
case ov_dynamically_linked_function:   
case ov_function_handle:       
case ov_inline_function:       
case ov_float_diagonal_matrix:   
case ov_float_complex_diagonal_matrix:   
case ov_diagonal_matrix:   
case ov_complex_diagonal_matrix:   
case ov_permutation_matrix:           
case ov_null_matrix:               
case ov_null_string:               
case ov_null_sq_string:           
    default:        printf("MPI_Send: unsupported class %s\n",
                    ov.type_name().c_str());
            return(MPI_ERR_UNKNOWN );
  }
}





DEFUN_DLD(MPI_Send,args,, "MPI_Send sends almost any Octave datatypes into contiguous memory using openmpi library even over an hetherogeneous cluster i.e 32 bits CPUs and 64 bits CPU \n")
{
     octave_value retval;
//      Check if MPI environment is initialized
// first argument octave_value we want to send
// second argument columnv vector rank of the receivers
// for tag we use the type of octave_value ( see enum above )
// if alternative comunicator is provided select predefined MPI_COMM_WORLD
//      Put the rank of the receiver into a columnvector
  int nargin = args.length ();
  if (nargin != 3)
    {
      error ("expecting 3 input arguments");
      return retval;
    }
     ColumnVector tankrank = args(1).column_vector_value();    
  if (error_state)
    {
      error ("expecting second argument to be a column vector");
      return retval;
    }
     int mytag = args(2).int_value();    
  if (error_state)
    {
      error ("expecting third vector argument to be an integer value");
      return retval;
    }

     int info = send_class (args(0), tankrank, mytag);
     retval=info;
//     retval(1) = tanktag;
     return retval;
   
}
MPI_Recv.cc

// mkoctfile -lpthread -I/home/user/openmpi-1.3.3/include/ -L/home/user/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl  -lnsl -lutil -lm -ldl MPI_Send.cc
// mkoctfile -lpthread -I/home/corradin/openmpi-1.3.3/include/ -L/home/corradin/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl  -lnsl -lutil -lm -ldl MPI_Recv.cc


/*
 * Receives most Octave datatypes into contiguous memory
 * using derived datatypes
 * info = MPI_Send(var,rank)
 */
#include "mpi.h"   
#include <octave/oct.h>
#include <ov-cell.h>    // avoid errmsg "cell -- incomplete datatype"
#include <oct-map.h>    // avoid errmsg "Oct.map -- invalid use undef type"

// tested on Octave 3.2.3
// Octave 3.2.X

enum ov_t_id
{

ov_unknown=0,                // t_id=0
ov_cell,                // t_id=1
ov_scalar,                // t_id=2
ov_complex_scalar,            // t_id=3
ov_matrix,                // t_id=4
ov_diagonal_matrix,            // t_id=5
ov_complex_matrix,            // t_id=6
ov_complex_diagonal_matrix,        // t_id=7
ov_range,                // t_id=8
ov_bool,                // t_id=9
ov_bool_matrix,                // t_id=10
ov_char_matrix,                // t_id=11
ov_string,                // t_id=12
ov_sq_string,                // t_id=13
ov_int8_scalar,                // t_id=14
ov_int16_scalar,            // t_id=15
ov_int32_scalar,            // t_id=16
ov_int64_scalar,            // t_id=17
ov_uint8_scalar,            // t_id=18
ov_uint16_scalar,            // t_id=19
ov_uint32_scalar,            // t_id=20
ov_uint64_scalar,            // t_id=21
ov_int8_matrix,            // t_id=22
ov_int16_matrix,            // t_id=23
ov_int32_matrix,                    // t_id=24
ov_int64_matrix,                    // t_id=25
ov_uint8_matrix,            // t_id=26
ov_uint16_matrix,            // t_id=27
ov_uint32_matrix,            // t_id=28
ov_uint64_matrix,            // t_id=29
ov_sparse_bool_matrix,            // t_id=30

ov_sparse_matrix,                        // t_id=31
ov_sparse_complex_matrix,
ov_struct,
ov_class,
ov_list,
ov_cs_list,
ov_magic_colon,
ov_built_in_function,
ov_user_defined_function,
ov_dynamically_linked_function,
ov_function_handle,
ov_inline_function,
ov_float_scalar,
ov_float_complex_scalar,
ov_float_matrix,
ov_float_diagonal_matrix,
ov_float_complex_matrix,
ov_float_complex_diagonal_matrix,
ov_permutation_matrix,
ov_null_matrix,
ov_null_string,
ov_null_sq_string,
};



/*----------------------------------*/        /* forward declaration */



int recv_class( octave_value &ov,  int source, int mytag);        /* along the datatype */
/*----------------------------------*/    /* to send any octave_value */


int recv_string( octave_value  &ov, int source, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a double value */

OCTAVE_LOCAL_BUFFER(int, tanktag, 2);
tanktag[0]=mytag;
tanktag[1]=mytag+1;
tanktag[2]=mytag+2;

  int info,nitem;
  MPI_Status stat;
  info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  printf("I have received number of elements  %i \n",nitem);
  OCTAVE_LOCAL_BUFFER(char,mess,nitem+1);
  if (info !=MPI_SUCCESS) return info;
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_CHAR, &fortvec);
  MPI_Type_commit(&fortvec);


   info = MPI_Recv(mess, 1,fortvec, source, tanktag[2] , MPI_COMM_WORLD,&stat);
  printf("Flag for string received  %i \n",info);
   std::string cpp_string;
   cpp_string = mess;
   ov = cpp_string;
   if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 5);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[4] = mytag+4;

  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
   
   dv(i) = dimV[i] ;
   printf("I am printing dimvector  %i \n",dimV[i]);
 }
    NDArray myNDA(dv);
//     double *p = myNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(double,LBNDA,nitem);
//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_DOUBLE, &fortvec);
  MPI_Type_commit(&fortvec);
      printf("I am printing dimvector  %i \n",tanktag[4]);
          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;
  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      myNDA(i)=LBNDA[i];
  }
    ov = myNDA;
//     printf("info for receiving scalar matrix is = %i \n",info);

}

int recv_float_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 5);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[4] = mytag+4;
  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
    printf("I am printing dimvector  %i \n",dimV[i]);
   dv(i) = dimV[i] ;
 }
    FloatNDArray myNDA(dv);
    float *p = myNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(float,LBNDA,nitem);
//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_FLOAT, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;
  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      myNDA(i)=LBNDA[i];
  }
    ov = myNDA;
//     printf("info for receiving scalar matrix is = %i \n",info);

}



int recv_complex_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 6);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[4] = mytag+4;
tanktag[5] = mytag+5;

  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
//    printf("I am printing dimvector  %i \n",i);
   dv(i) = dimV[i] ;
 }
    NDArray rmyNDA(dv);  // for the real part
    NDArray imyNDA(dv);  // for the img part

   ComplexNDArray   oa (dv);            /* Create->Delete on ret?!? */

     double *p = rmyNDA.fortran_vec();
     double *ip = imyNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(double,LBNDA,nitem);
   OCTAVE_LOCAL_BUFFER(double,CLBNDA,nitem);

//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_DOUBLE, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;

          info = MPI_Recv((CLBNDA), 1,fortvec, source, tanktag[5] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;


  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      rmyNDA(i)=LBNDA[i];
      imyNDA(i)=CLBNDA[i];
      oa(i) = Complex (rmyNDA (i), imyNDA (i));
  }
    ov = oa;

return(MPI_SUCCESS);
}


int recv_float_complex_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 6);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[4] = mytag+4;
tanktag[5] = mytag+5;

  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
//    printf("I am printing dimvector  %i \n",i);
   dv(i) = dimV[i] ;
 }
    FloatNDArray rmyNDA(dv);  // for the real part
    FloatNDArray imyNDA(dv);  // for the img part

   FloatComplexNDArray   oa (dv);            /* Create->Delete on ret?!? */

     float *p = rmyNDA.fortran_vec();
     float *ip = imyNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(float,LBNDA,nitem);
   OCTAVE_LOCAL_BUFFER(float,CLBNDA,nitem);

//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_DOUBLE, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;

          info = MPI_Recv((CLBNDA), 1,fortvec, source, tanktag[5] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;


  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      rmyNDA(i)=LBNDA[i];
      imyNDA(i)=CLBNDA[i];
      std::complex<float>  c  = real(rmyNDA(i))+imag(imyNDA(i));
      oa(i) = c;
  }
    ov = oa;

return(MPI_SUCCESS);
}






int recv_sp_mat(octave_value &ov,int source, int mytag){   
int info;   
/*     int nr = m.rows();
     int nc = m.cols (); 
     int nnzm = m.nzmax ();*/
// tag[0] ----> type of octave_value
// tag[1] ----> array of three elements 1) num of rows 2) number of columns 3) number of non zero elements
// tag[2] ---->  vector of rowindex
// tag[3] ---->  vector of columnindex
// tag[5] ---->  vector of number of non zero elements
OCTAVE_LOCAL_BUFFER(int, tanktag,6);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[4] = mytag+4;
tanktag[5] = mytag+5;

MPI_Status stat;

OCTAVE_LOCAL_BUFFER(int,s,3);  

// Create a contiguous derived datatype
MPI_Datatype sintsparse;
MPI_Type_contiguous(3,MPI_INT, &sintsparse);
MPI_Type_commit(&sintsparse);

// receive the sintsparse vector named s
info = MPI_Recv(s, 1, sintsparse, source, tanktag[1], MPI_COMM_WORLD, &stat);
if (info !=MPI_SUCCESS) return info;

// int appo1, appo2, appo3;
// appo1 = s[0];
// appo2 = s[1];
// appo3 = s[2];
//
// printf("appo 1 is %i \n",appo1);
// printf("appo 2 is %i \n",appo2);
// printf("appo 3 is %i \n",appo3);



SparseMatrix m(s[0],s[1],s[2]);

// Create a contiguous derived datatype for row index
OCTAVE_LOCAL_BUFFER(int,sridx,s[2]); 
OCTAVE_LOCAL_BUFFER(double,sdata,s[2]);
// Create a contiguous derived datatype for column index
OCTAVE_LOCAL_BUFFER(int,scidx,s[1]+1);  
MPI_Datatype rowindex;
MPI_Type_contiguous(s[2],MPI_INT, &rowindex);
MPI_Type_commit(&rowindex);
MPI_Datatype datavect;
MPI_Type_contiguous(s[2],MPI_DOUBLE, &datavect);
MPI_Type_commit(&datavect);
MPI_Datatype columnindex;
MPI_Type_contiguous(s[1]+1,MPI_INT, &columnindex);
MPI_Type_commit(&columnindex);

// Now receive the two vectors

// receive the vector with row indexes
      info =  MPI_Recv(sridx,1,rowindex,source,tanktag[2],MPI_COMM_WORLD,&stat);
//       printf("Hope everything is fine here with ridx %i =\n",info);
      if (info !=MPI_SUCCESS) return info;

// receive the vector with column indexes
      info =  MPI_Recv(scidx,1,columnindex,source,tanktag[3],MPI_COMM_WORLD, &stat);
//     printf("Hope everything is fine here with scidx %i =\n",info);
      if (info !=MPI_SUCCESS) return info;

      info =  MPI_Recv(sdata,1,datavect,source,tanktag[4],MPI_COMM_WORLD,&stat);
//       printf("Hope everything is fine here with data vect %i =\n",info);

// int appoc;
NDArray buf (dim_vector (m.capacity(), 1));
for (octave_idx_type i = 0; i < s[2]; i++)
{
    m.ridx(i) = sridx[i];
    m.data(i) = sdata[i];
    buf(i) = sdata[i];
//     appoc = m.ridx(i);
//     printf("apporow is %i \n",appoc);
//     printf("appodata is %d \n",sdata[i]);
}
for (octave_idx_type i = 0; i < s[1]+1; i++)
{
    m.cidx(i) = scidx[i];
//     appoc=m.cidx(i);
//     printf("appocol is %i \n",appoc);
}


ov = m;
return(info);


}


//here ! int matrixes
int recv_int8_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 5);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[4] = mytag+4;
  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
//    printf("I am printing dimvector  %i \n",i);
   dv(i) = dimV[i] ;
 }
    int8NDArray myNDA(dv);
//     double *p = myNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(octave_int8,LBNDA,nitem);
//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_BYTE, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;
  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      myNDA(i)=LBNDA[i];
  }
    ov = myNDA;
//     printf("info for receiving scalar matrix is = %i \n",info);

}

int recv_int16_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 5);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[3] = mytag+4;
  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
//    printf("I am printing dimvector  %i \n",i);
   dv(i) = dimV[i] ;
 }
    int16NDArray myNDA(dv);
//     double *p = myNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(octave_int16,LBNDA,nitem);
//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_SHORT, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;
  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      myNDA(i)=LBNDA[i];
  }
    ov = myNDA;
//     printf("info for receiving scalar matrix is = %i \n",info);
   return(info);
}


int recv_int32_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 5);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[3] = mytag+4;

  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
//    printf("I am printing dimvector  %i \n",i);
   dv(i) = dimV[i] ;
 }
    int32NDArray myNDA(dv);
//     double *p = myNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(octave_int32,LBNDA,nitem);
//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_INT, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;
  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      myNDA(i)=LBNDA[i];
  }
    ov = myNDA;
//     printf("info for receiving scalar matrix is = %i \n",info);
   return(info);
}


int recv_int64_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 5);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[3] = mytag+4;

  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
//    printf("I am printing dimvector  %i \n",i);
   dv(i) = dimV[i] ;
 }
    int64NDArray myNDA(dv);
//     double *p = myNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(octave_int64,LBNDA,nitem);
//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_INT, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;
  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      myNDA(i)=LBNDA[i];
  }
    ov = myNDA;
//     printf("info for receiving scalar matrix is = %i \n",info);
   return(info);
}



int recv_uint64_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 5);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[3] = mytag+4;

  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
//    printf("I am printing dimvector  %i \n",i);
   dv(i) = dimV[i] ;
 }
    uint64NDArray myNDA(dv);
//     double *p = myNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(octave_uint64,LBNDA,nitem);
//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_UNSIGNED_LONG_LONG, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;
  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      myNDA(i)=LBNDA[i];
  }
    ov = myNDA;
//     printf("info for receiving scalar matrix is = %i \n",info);
   return(info);
}


int recv_uint8_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 5);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[3] = mytag+4;

  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
//    printf("I am printing dimvector  %i \n",i);
   dv(i) = dimV[i] ;
 }
    uint8NDArray myNDA(dv);
//     double *p = myNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(octave_uint8,LBNDA,nitem);
//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_UNSIGNED_CHAR, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;
  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      myNDA(i)=LBNDA[i];
  }
    ov = myNDA;
//     printf("info for receiving scalar matrix is = %i \n",info);
   return(info);
}



int recv_uint16_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 5);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[3] = mytag+4;

  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
//    printf("I am printing dimvector  %i \n",i);
   dv(i) = dimV[i] ;
 }
    uint16NDArray myNDA(dv);
//     double *p = myNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(octave_uint16,LBNDA,nitem);
//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_UNSIGNED_SHORT, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;
  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      myNDA(i)=LBNDA[i];
  }
    ov = myNDA;
//     printf("info for receiving scalar matrix is = %i \n",info);
   return(info);
}

int recv_uint32_matrix(octave_value &ov,int source, int mytag){       

OCTAVE_LOCAL_BUFFER(int, tanktag, 5);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[3] = mytag+4;

  int info;
  int nitem,nd;
  MPI_Status stat;
  dim_vector dv;
 
//       nitem is the total number of elements 
          info = MPI_Recv((&nitem), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
//       printf("I have received number of elements  %i \n",nitem);
      if (info !=MPI_SUCCESS) return info;
//      ndims is number of dimensions
          info = MPI_Recv((&nd), 1,MPI_INT, source, tanktag[2] , MPI_COMM_WORLD,&stat);
//             printf("I have received number of dimensions %i \n",nd);
      if (info !=MPI_SUCCESS) return info;
//  Now create contiguos datatype for dim vector
  dv.resize(nd);
  OCTAVE_LOCAL_BUFFER(int,dimV,nd);
  MPI_Datatype dimvec;
  MPI_Type_contiguous(nd,MPI_INT, &dimvec);
  MPI_Type_commit(&dimvec);

          info = MPI_Recv((dimV), 1,dimvec, source, tanktag[3] , MPI_COMM_WORLD,&stat);
      if (info !=MPI_SUCCESS) return info;

// Now reverse the content of int vector into dim vector
 for (octave_idx_type i=0; i<nd; i++)
 {
//    printf("I am printing dimvector  %i \n",i);
   dv(i) = dimV[i] ;
 }
    uint32NDArray myNDA(dv);
//     double *p = myNDA.fortran_vec();
   OCTAVE_LOCAL_BUFFER(octave_uint32,LBNDA,nitem);
//    printf("BUFFER CREATED \n");
  // Now create the contiguous derived datatype
  MPI_Datatype fortvec;
  MPI_Type_contiguous(nitem,MPI_UNSIGNED, &fortvec);
  MPI_Type_commit(&fortvec);

          info = MPI_Recv((LBNDA), 1,fortvec, source, tanktag[4] , MPI_COMM_WORLD,&stat);
//           printf("info for receiving data is = %i \n",info);
      if (info !=MPI_SUCCESS) return info;
  for (octave_idx_type i=0; i<nitem; i++)
  {
//       *LBNDA = *p;
//       LBNDA++;
//       p++;
      myNDA(i)=LBNDA[i];
  }
    ov = myNDA;
//     printf("info for receiving scalar matrix is = %i \n",info);
   return(info);
}




int recv_complex_sp_mat(octave_value &ov,int source, int mytag){   
int info;   
/*     int nr = m.rows();
     int nc = m.cols (); 
     int nnzm = m.nzmax ();*/
// tag[0] ----> type of octave_value
// tag[1] ----> array of three elements 1) num of rows 2) number of columns 3) number of non zero elements
// tag[2] ---->  vector of rowindex
// tag[3] ---->  vector of columnindex
// tag[5] ---->  vector of number of non zero elements
OCTAVE_LOCAL_BUFFER(int, tanktag,6);
tanktag[0] = mytag;
tanktag[1] = mytag+1;
tanktag[2] = mytag+2;
tanktag[3] = mytag+3;
tanktag[4] = mytag+4;
tanktag[5] = mytag+5;

MPI_Status stat;

OCTAVE_LOCAL_BUFFER(int,s,3);  

// Create a contiguous derived datatype
MPI_Datatype sintsparse;
MPI_Type_contiguous(3,MPI_INT, &sintsparse);
MPI_Type_commit(&sintsparse);

// receive the sintsparse vector named s
info = MPI_Recv(s, 1, sintsparse, source, tanktag[1], MPI_COMM_WORLD, &stat);
if (info !=MPI_SUCCESS) return info;

// int appo1, appo2, appo3;
// appo1 = s[0];
// appo2 = s[1];
// appo3 = s[2];
//
// printf("appo 1 is %i \n",appo1);
// printf("appo 2 is %i \n",appo2);
// printf("appo 3 is %i \n",appo3);



SparseMatrix m(s[0],s[1],s[2]);

// Create a contiguous derived datatype for row index
OCTAVE_LOCAL_BUFFER(int,sridx,s[2]); 
OCTAVE_LOCAL_BUFFER(double,sdata,s[2]);
// Create a contiguous derived datatype for column index
OCTAVE_LOCAL_BUFFER(int,scidx,s[1]+1);  
MPI_Datatype rowindex;
MPI_Type_contiguous(s[2],MPI_INT, &rowindex);
MPI_Type_commit(&rowindex);
MPI_Datatype datavect;
MPI_Type_contiguous(s[2],MPI_DOUBLE, &datavect);
MPI_Type_commit(&datavect);
MPI_Datatype columnindex;
MPI_Type_contiguous(s[1]+1,MPI_INT, &columnindex);
MPI_Type_commit(&columnindex);

// Now receive the two vectors

// receive the vector with row indexes
      info =  MPI_Recv(sridx,1,rowindex,source,tanktag[2],MPI_COMM_WORLD,&stat);
//       printf("Hope everything is fine here with ridx %i =\n",info);
      if (info !=MPI_SUCCESS) return info;

// receive the vector with column indexes
      info =  MPI_Recv(scidx,1,columnindex,source,tanktag[3],MPI_COMM_WORLD, &stat);
//     printf("Hope everything is fine here with scidx %i =\n",info);
      if (info !=MPI_SUCCESS) return info;

      info =  MPI_Recv(sdata,1,datavect,source,tanktag[4],MPI_COMM_WORLD,&stat);
//       printf("Hope everything is fine here with data vect %i =\n",info);

// int appoc;
NDArray buf (dim_vector (m.capacity(), 1));
for (octave_idx_type i = 0; i < s[2]; i++)
{
    m.ridx(i) = sridx[i];
    m.data(i) = sdata[i];
    buf(i) = sdata[i];
//     appoc = m.ridx(i);
//     printf("apporow is %i \n",appoc);
//     printf("appodata is %d \n",sdata[i]);
}
for (octave_idx_type i = 0; i < s[1]+1; i++)
{
    m.cidx(i) = scidx[i];
//     appoc=m.cidx(i);
//     printf("appocol is %i \n",appoc);
}


ov = m;
return(info);


}









int recv_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Recv it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;
  int info;
  MPI_Status stat;
  double d = ov.double_value();
  info = MPI_Recv((&d), 1,MPI_DOUBLE, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  ov =d;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_int8_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Recv it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;
  int info;
  MPI_Status stat;
  octave_int8 d = ov.int8_scalar_value();
  info = MPI_Recv((&d), 1,MPI_BYTE, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  ov =d;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_int16_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Recv it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;
  int info;
  MPI_Status stat;
  octave_int16 d = ov.int16_scalar_value();
  info = MPI_Recv((&d), 1,MPI_SHORT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  ov =d;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_int32_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Recv it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;
  int info;
  MPI_Status stat;
  octave_int32 d = ov.int32_scalar_value();
  info = MPI_Recv((&d), 1,MPI_INT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  ov =d;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_int64_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Recv it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;
  int info;
  MPI_Status stat;
  octave_int64 d = ov.int64_scalar_value();
  info = MPI_Recv((&d), 1,MPI_LONG_LONG, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  ov =d;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_uint64_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Recv it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;
  int info;
  MPI_Status stat;
  octave_uint64 d = ov.uint64_scalar_value();
  info = MPI_Recv((&d), 1,MPI_UNSIGNED_LONG_LONG, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  ov =d;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_uint32_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Recv it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;
  int info;
  MPI_Status stat;
  octave_uint32 d = ov.uint32_scalar_value();
  info = MPI_Recv((&d), 1,MPI_UNSIGNED, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  ov =d;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_uint16_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Recv it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;
  int info;
  MPI_Status stat;
  octave_uint16 d = ov.uint16_scalar_value();
  info = MPI_Recv((&d), 1,MPI_UNSIGNED_SHORT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  ov =d;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_uint8_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Recv it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;
  int info;
  MPI_Status stat;
  octave_uint8 d = ov.uint8_scalar_value();
  info = MPI_Recv((&d), 1,MPI_UNSIGNED_CHAR, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  ov =d;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}









int recv_complex_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;

  OCTAVE_LOCAL_BUFFER(double,d,2);



  int info;
  MPI_Status stat;
  info = MPI_Recv((&d), 2,MPI_DOUBLE, source, tanktag[1] , MPI_COMM_WORLD,&stat);

  ov =Complex(d[0],d[1]);;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_complex_float_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Send it, */
/*-----------------------------*/        /* it's just a double value */
OCTAVE_LOCAL_BUFFER(int,tanktag,2);
  tanktag[0]=mytag;
  tanktag[1]=mytag+1;

  OCTAVE_LOCAL_BUFFER(float,d,2);



  int info;
  MPI_Status stat;
  info = MPI_Recv((&d), 2,MPI_FLOAT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  std::complex<float>  c = real(d[0])+imag(d[1]);
  ov =c;;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}






int recv_float_scalar( octave_value &ov, int source, int mytag){        /* directly MPI_Recv it, */
/*-----------------------------*/        /* it's just a Float value */

OCTAVE_LOCAL_BUFFER(int,tanktag,2);
tanktag[0] = mytag;
tanktag[1] = mytag+1;


  int info;
  MPI_Status stat;
  float d = ov.float_value();
  info = MPI_Recv((&d), 1,MPI_FLOAT, source, tanktag[1] , MPI_COMM_WORLD,&stat);
  ov =d;
//   printf("info for scalar is = %i \n",info);
  if (info !=MPI_SUCCESS) return info;
   return(MPI_SUCCESS);
}

int recv_class(octave_value &ov, int source, int mytag ){    /* varname-strlength 1st, dims[ndim] */
/*----------------------------------*/    /* and then appropriate specific info */
  int t_id,n;
//   int mytag = cvtag(0);
  MPI_Status status;
  printf("1-> source =%i\n",source);
  printf("2-> tag for id =%i\n",mytag);
  int info = MPI_Recv(&t_id,1, MPI_INT, source,mytag,MPI_COMM_WORLD,&status);

   printf(" I have received t_id =%i\n",t_id);

  if (info !=MPI_SUCCESS) return info;

  switch (t_id) {

    case ov_scalar:    return(recv_scalar (ov,source,mytag));
    case ov_int8_scalar:    return(recv_int8_scalar (ov,source,mytag));
    case ov_int16_scalar:    return(recv_int16_scalar (ov,source,mytag));
    case ov_int32_scalar:    return(recv_int32_scalar (ov,source,mytag));
    case ov_int64_scalar:    return(recv_int64_scalar (ov,source,mytag));
    case ov_uint8_scalar:    return(recv_uint8_scalar (ov,source,mytag));
    case ov_uint16_scalar:    return(recv_uint16_scalar (ov,source,mytag));
    case ov_uint32_scalar:    return(recv_uint32_scalar (ov,source,mytag));
    case ov_uint64_scalar:    return(recv_uint64_scalar (ov,source,mytag));
    case ov_float_scalar: return(recv_float_scalar(ov,source,mytag));
    case ov_complex_scalar:    return(recv_complex_scalar (ov,source,mytag));
    case ov_float_complex_scalar: return(recv_complex_float_scalar(ov,source,mytag));

    case ov_string:    return(recv_string (ov,source,mytag));
    case ov_matrix:    return(recv_matrix (ov,source,mytag));
    case ov_complex_matrix:    return(recv_complex_matrix(ov,source,mytag));
    case ov_int8_matrix:    return(recv_int8_matrix (ov,source,mytag));
    case ov_int16_matrix:    return(recv_int16_matrix (ov,source,mytag));
    case ov_int32_matrix:    return(recv_int32_matrix (ov,source,mytag));
    case ov_int64_matrix:    return(recv_int64_matrix (ov,source,mytag));


    case ov_uint8_matrix:    return(recv_uint8_matrix (ov,source,mytag));
    case ov_uint16_matrix:    return(recv_uint16_matrix (ov,source,mytag));
    case ov_uint32_matrix:    return(recv_uint32_matrix (ov,source,mytag));
    case ov_uint64_matrix:    return(recv_uint64_matrix (ov,source,mytag));

    case ov_float_matrix:    return(recv_float_matrix (ov,source,mytag));
    case ov_float_complex_matrix:    return(recv_float_complex_matrix (ov,source,mytag));
    case ov_sparse_matrix:    return(recv_sp_mat(ov,source,mytag));
    case ov_sparse_complex_matrix:    return(recv_complex_sp_mat(ov,source,mytag));
    case ov_unknown:    printf("MPI_Recv: unknown class\n");
            return(MPI_ERR_UNKNOWN );

case ov_class:           
case ov_list:           
case ov_cs_list:           
case ov_magic_colon:           
case ov_built_in_function:       
case ov_user_defined_function:       
case ov_dynamically_linked_function:   
case ov_function_handle:       
case ov_inline_function:       
case ov_float_diagonal_matrix:   
case ov_float_complex_diagonal_matrix:   
case ov_diagonal_matrix:   
case ov_complex_diagonal_matrix:   
case ov_permutation_matrix:           
case ov_null_matrix:               
case ov_null_string:               
case ov_null_sq_string:           

    default:        printf("MPI_Recv: unsupported class %s\n",
                    ov.type_name().c_str());
            return(MPI_ERR_UNKNOWN );
  }
}





DEFUN_DLD(MPI_Recv,args,, "MPI_Recv sends almost any Octave datatype into contiguous memory using openmpi library even over an hetherogeneous cluster i.e 32 bits CPUs and 64 bits CPU \n")
{
     octave_value_list retval;
//      Check if MPI environment is initialized
// first argument rank of the receiver
// for tag we use the type of octave_value ( see enum above )
// if alternative comunicator is provided select predefined MPI_COMM_WORLD
//      Put the rank of the receiver into a columnvector
     int source = args(0).int_value();    
  if (error_state)
    {
      error ("expecting first argument to be an integer");
      return retval;
    }
 int mytag = args(1).int_value();
  if (error_state)
    {
      error ("expecting second argument to be a column vector");
      return retval;
    }/*
  if (mytags.numel() < 3)
    {
      error ("expecting second argument having  more than two elements");
      return retval;
    }*/
     octave_value result;
     int info = recv_class (result,source, mytag );
     retval(0)=info;
     retval(1)=result;
     return retval;
   
}

 Now I may show you some simple helloworld octave scripts
if not(MPI_Initialized)
   info = MPI_Init();
end

  [info my_rank] = MPI_Comm_rank();
  [info p ] = MPI_Comm_size();
  mytag = 48;


  message="";
  if (my_rank != 0)
      message = sprintf('Greetings from process: %d!',my_rank);
      dest = 0;
%       rankvect is the vector containing the list of rank  destination process
     rankvect = 0;
     [info] = MPI_Send(message,rankvect,mytag);
     info
  else
        for source = 1:p-1
          disp("We are at rank 0 that is master etc..");
          [info message] = MPI_Recv(source,mytag);
        printf('%s\n', message);
          endfor
  end   


  if not(MPI_Finalized)
   info = MPI_Finalize();
  end

or
if not(MPI_Initialized)
   info = MPI_Init();
end

  [info my_rank] = MPI_Comm_rank();
  [info p ] = MPI_Comm_size();
  mytag = 48;


 
  if (my_rank != 0)
%        Generate a random matrix
       message=rand(90,90);
%        load message
%        dest = 0;
%       rankvect is the vector containing the list of rank  destination process
     rankvect = 0;
     [info] = MPI_Send(message,rankvect,mytag);
  else
        for source = 1:p-1
          disp("We are at rank 0 that is master etc..");
          [info messager] = MPI_Recv(source,mytag);
          disp("Rank 0 is the master receiving ... :");
            if (info == true)
              disp('OK!');
          endif
          endfor
  end   


  if not(MPI_Finalized)
   info = MPI_Finalize();
  end


or with  a
sparse matrix
if not(MPI_Initialized)
   info = MPI_Init();
end

  [info my_rank] = MPI_Comm_rank();
  [info p ] = MPI_Comm_size();
%  // tag[0] ----> type of octave_value
%  // tag[1] ----> array of three elements 1) num of rows 2) number of columns 3) number of non zero elements
%  // tag[2] ---->  vector of rowindex
%  // tag[3] ---->  vector of columnindex
%  // tag[4] ---->  vector of  non zero elements


  mytag = 48;





  M=5;
  N=5;
  D=0.9;
%    message = sprand (M, N, D);
  load message
 

 
  if (my_rank != 0)
      dest = 0;
%       rankvect is the vector containing the list of rank  destination process
     rankvect(1,1) = 0;
     [info] = MPI_Send(message,rankvect,mytag);
     disp("This is flag for sending the message --")
     info
  else
        for source = 1:p-1
          messager='';
          disp("We are at rank 0 that is master etc..");
          [info messager] = MPI_Recv(source,mytag);
          disp("Rank 0 is the master receiving ... :");
          if (messager/message)
                disp('OK!');
          endif
      messager
          endfor
  end   


  if not(MPI_Finalized)
   info = MPI_Finalize();
  end

You could run the examples with mpirun -np 6 octave --eval testhello

I would try to implement MPI_Probe MPI_Iprobe and MPI_ISend and MPI_IRecv using the same strategy implemented above.
Please let me know your opinion.

Thanks a lot
Riccardo Corradini






--- Mer 4/11/09, Søren Hauberg <soren@...> ha scritto:

Da: Søren Hauberg <soren@...>
Oggetto: Re: [OctDev] Contribution to Octave-forge with a simple Open-MPI Package
A: "Riccardo Corradini" <riccardocorradini@...>
Cc: octave-dev@...
Data: Mercoledì 4 novembre 2009, 15:45

Hi,

tir, 03 11 2009 kl. 12:25 +0000, skrev Riccardo Corradini:
> for my econometric computations I have built a simple package that
> uses the concept of MPI-Derived datatypes
> ( see http://static.msi.umn.edu/tutorial/scicomp/general/MPI/content6.html )  to spread octave_values objects over octave instances.
> This package gets a lot of ideas from MPI_TB for octave but is
> simpler, doesn't use MPI_PACK and MPI_UNPACK and is very easy to
> update with newer versions of Octave ( I tested it with octave 3.2.3 ,
> but I am sure it will work also with development-version).

Cool! I'm currently not using Octave on a cluster, so I don't have any
MPI experience. Is your code general-purpose or is it designed for
econometrics?

> Before doing that I would like to submit the functions to this list to
> know your opinions, warnings, improvements  and some hints on how to
> build an octave forge package with open-mpi bindings.

As I said, I don't have any MPI experience, but feel free to send the
code to this list. I don't mind given it a quick look to see if I catch
anything, and perhaps others will provide their thoughts as well.

Søren




------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Jaroslav Hajek-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Wed, Nov 4, 2009 at 4:49 PM, Riccardo Corradini <riccardocorradini@...> wrote:
Hi Søren,
thanks for your quick reply.
The code is general-purpose, but as I told you I would love to use it for econometrics.
So the first step will be to install the following tarball from
http://www.open-mpi.org/software/ompi/v1.3/downloads/openmpi-1.3.3.tar.bz2
possibly in a multi-core computer to run my simple examples
and configure it for instance in the following way (/home/user is your $HOME)
./configure --enable-mpirun-prefix-by-default --enable-heterogeneous --prefix=/home/user/openmpi-1.3.3/ --enable-static

and modify .bashrc in your home
 OMPIBIN=`$ompi_info -path     bindir  -parsable | cut -d: -f3`
 OMPILIB=`$ompi_info -path     libdir  -parsable | cut -d: -f3`
 OMPISCD=`$ompi_info -path sysconfdir  -parsable | cut -d: -f3`

 OSCBIN=~/oompi-1.0.4/bin

export            PATH=$OMPIBIN:$PATH
export          PATH=$OSCBIN:$PATH
export LD_LIBRARY_PATH=:$OMPILIB:$LD_LIBRARY_PATH

unset  ompi_info OMPIBIN OMPILIB OMPISCD OSCBIN

After this type in a terminal mpiCC --showme
In my case I will have something like

g++ -I/home/user/openmpi-1.3.3/include -pthread -L/home/user/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -Wl,--export-dynamic -lnsl -lutil -lm -ldl

This will be useful for mkoctfile

Now I will include the basic functions

// mkoctfile -I/home/corradin/openmpi-1.3.3/include -lpthread -L/home/corradin/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -lnsl -lutil -lm -ldl MPI_Init.cc


This looks good. Do I get it correctly that it is not necessary to relink Octave? I'd suggest you create the package on OctaveForge, then others will be able to try it and contribute.

regards

--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Parent Message unknown Re: Contribution to Octave-forge with a simple Open-MPI Package

by Riccardo Corradini :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Yes Jaroslav. It's not necessary to relink octave, you just have to include the header of openmpi and -l the other open mpi libraries.
I tried to run on my ubuntu terminal as explained here
http://octave.sourceforge.net/developers.html

svn co https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge
svn: OPTIONS di 'https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge': could not connect to server

How do you suggest to proceed?

Thanks a lot
Riccardo

--- Gio 5/11/09, Jaroslav Hajek <highegg@...> ha scritto:

Da: Jaroslav Hajek <highegg@...>
Oggetto: Re: [OctDev] Contribution to Octave-forge with a simple Open-MPI Package
A: "Riccardo Corradini" <riccardocorradini@...>
Cc: "Søren Hauberg" <soren@...>, octave-dev@...
Data: Giovedì 5 novembre 2009, 21:34



On Wed, Nov 4, 2009 at 4:49 PM, Riccardo Corradini <riccardocorradini@...> wrote:
Hi Søren,
thanks for your quick reply.
The code is general-purpose, but as I told you I would love to use it for econometrics.
So the first step will be to install the following tarball from
http://www.open-mpi.org/software/ompi/v1.3/downloads/openmpi-1.3.3.tar.bz2
possibly in a multi-core computer to run my simple examples
and configure it for instance in the following way (/home/user is your $HOME)
./configure --enable-mpirun-prefix-by-default --enable-heterogeneous --prefix=/home/user/openmpi-1.3.3/ --enable-static

and modify .bashrc in your home
 OMPIBIN=`$ompi_info -path     bindir  -parsable | cut -d: -f3`
 OMPILIB=`$ompi_info -path     libdir  -parsable | cut -d: -f3`
 OMPISCD=`$ompi_info -path sysconfdir  -parsable | cut -d: -f3`

 OSCBIN=~/oompi-1.0.4/bin

export            PATH=$OMPIBIN:$PATH
export          PATH=$OSCBIN:$PATH
export LD_LIBRARY_PATH=:$OMPILIB:$LD_LIBRARY_PATH

unset  ompi_info OMPIBIN OMPILIB OMPISCD OSCBIN

After this type in a terminal mpiCC --showme
In my case I will have something like

g++ -I/home/user/openmpi-1.3.3/include -pthread -L/home/user/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -Wl,--export-dynamic -lnsl -lutil -lm -ldl

This will be useful for mkoctfile

Now I will include the basic functions

// mkoctfile -I/home/corradin/openmpi-1.3.3/include -lpthread -L/home/corradin/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -lnsl -lutil -lm -ldl MPI_Init.cc


This looks good. Do I get it correctly that it is not necessary to relink Octave? I'd suggest you create the package on OctaveForge, then others will be able to try it and contribute.

regards

--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Jaroslav Hajek-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Fri, Nov 6, 2009 at 1:37 PM, Riccardo Corradini <riccardocorradini@...> wrote:
Yes Jaroslav. It's not necessary to relink octave, you just have to include the header of openmpi and -l the other open mpi libraries.
I tried to run on my ubuntu terminal as explained here
http://octave.sourceforge.net/developers.html

svn co https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge
svn: OPTIONS di 'https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge': could not connect to server

How do you suggest to proceed?

Thanks a lot
Riccardo


This should work (works for me). Can you access the address using a web browser? Maybe sourceforge was just down at the moment.
For write access, you'll need to register at sourceforge (unless you already did so) and tell Soren your username, so that he can add you to the OctaveForge group. I think that it is not needed for a checkout, by I may be wrong.

hth

--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Riccardo Corradini :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Søren,
I would inform that my account for sourceforge is
http://sourceforge.net/users/rikcorradini
Now I have just to find out the solution for uploading the package
because my svn doesn't work
svn co https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge
svn: OPTIONS di 'https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge': I I could not connect to the server (https://octave.svn.sourceforge.net)

But I could  connect  my browser.
Is it possible to use ftp or something else similar?

Thanks a lot
Riccardo


--- Gio 5/11/09, Jaroslav Hajek <highegg@...> ha scritto:

Da: Jaroslav Hajek <highegg@...>
Oggetto: Re: [OctDev] Contribution to Octave-forge with a simple Open-MPI Package
A: "Riccardo Corradini" <riccardocorradini@...>
Cc: "Søren Hauberg" <soren@...>, octave-dev@...
Data: Giovedì 5 novembre 2009, 21:34



On Wed, Nov 4, 2009 at 4:49 PM, Riccardo Corradini <riccardocorradini@...> wrote:
Hi Søren,
thanks for your quick reply.
The code is general-purpose, but as I told you I would love to use it for econometrics.
So the first step will be to install the following tarball from
http://www.open-mpi.org/software/ompi/v1.3/downloads/openmpi-1.3.3.tar.bz2
possibly in a multi-core computer to run my simple examples
and configure it for instance in the following way (/home/user is your $HOME)
./configure --enable-mpirun-prefix-by-default --enable-heterogeneous --prefix=/home/user/openmpi-1.3.3/ --enable-static

and modify .bashrc in your home
 OMPIBIN=`$ompi_info -path     bindir  -parsable | cut -d: -f3`
 OMPILIB=`$ompi_info -path     libdir  -parsable | cut -d: -f3`
 OMPISCD=`$ompi_info -path sysconfdir  -parsable | cut -d: -f3`

 OSCBIN=~/oompi-1.0.4/bin

export            PATH=$OMPIBIN:$PATH
export          PATH=$OSCBIN:$PATH
export LD_LIBRARY_PATH=:$OMPILIB:$LD_LIBRARY_PATH

unset  ompi_info OMPIBIN OMPILIB OMPISCD OSCBIN

After this type in a terminal mpiCC --showme
In my case I will have something like

g++ -I/home/user/openmpi-1.3.3/include -pthread -L/home/user/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -Wl,--export-dynamic -lnsl -lutil -lm -ldl

This will be useful for mkoctfile

Now I will include the basic functions

// mkoctfile -I/home/corradin/openmpi-1.3.3/include -lpthread -L/home/corradin/openmpi-1.3.3/lib -lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -lnsl -lutil -lm -ldl MPI_Init.cc


This looks good. Do I get it correctly that it is not necessary to relink Octave? I'd suggest you create the package on OctaveForge, then others will be able to try it and contribute.

regards

--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Søren Hauberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

fre, 06 11 2009 kl. 14:04 +0000, skrev Riccardo Corradini:
> I would inform that my account for sourceforge is
> http://sourceforge.net/users/rikcorradini

I've added you as a developer.

> Now I have just to find out the solution for uploading the package
> because my svn doesn't work
> svn co
https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge
> svn: OPTIONS di
'https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge':
> I I could not connect to the server
(https://octave.svn.sourceforge.net)

> But I could  connect  my browser.
> Is it possible to use ftp or something else similar?

I don't know what could be the cause of this error. Perhaps just try
again later. If you still can't connect, then I guess we'll have to
investigate some more.

Søren


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Riccardo Corradini :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Søren ,
after a long battle I found out the solution to use svn properly
I am behind proxy so I have to set up the server file into the .subversion folder under my $HOME (have look at http://subversion.tigris.org/faq.html What if I am behind proxy?).
It is very important to not leave space when the proxy is indicated
For instance
 http://myproxy.it
will give error
while
http://myproxy.it
will work properly.
I was thinking to call it openmpi_ext and add just a subfolder src for the .cc files.
For the pkg script and so on I will wait for your hints

Thanks a lot
Riccardo Corradini

--- Ven 6/11/09, Søren Hauberg <soren@...> ha scritto:

Da: Søren Hauberg <soren@...>
Oggetto: Re: [OctDev] Contribution to Octave-forge with a simple Open-MPI Package
A: "Riccardo Corradini" <riccardocorradini@...>
Cc: "Jaroslav Hajek" <highegg@...>, octave-dev@...
Data: Venerdì 6 novembre 2009, 21:31

Hi,

fre, 06 11 2009 kl. 14:04 +0000, skrev Riccardo Corradini:
> I would inform that my account for sourceforge is
> http://sourceforge.net/users/rikcorradini

I've added you as a developer.

> Now I have just to find out the solution for uploading the package
> because my svn doesn't work
> svn co
https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge
> svn: OPTIONS di
'https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge':
> I I could not connect to the server
(https://octave.svn.sourceforge.net)

> But I could  connect  my browser.
> Is it possible to use ftp or something else similar?

I don't know what could be the cause of this error. Perhaps just try
again later. If you still can't connect, then I guess we'll have to
investigate some more.

Søren



------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Riccardo Corradini :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Dear Jaroslav,
I have just uploaded into octave-forge extra the openmpi_ext folder containing all the files
I sent you introducing the MPI toolbox that uses MPI Derived datatypes to send and receive almost any octave_value.
Please let me know about your suggestions or if there is something really wrong.
Thanks a lot to all of you for all your patience.
Bests
Riccardo Corradini

--- Ven 6/11/09, Søren Hauberg <soren@...> ha scritto:

Da: Søren Hauberg <soren@...>
Oggetto: Re: [OctDev] Contribution to Octave-forge with a simple Open-MPI Package
A: "Riccardo Corradini" <riccardocorradini@...>
Cc: "Jaroslav Hajek" <highegg@...>, octave-dev@...
Data: Venerdì 6 novembre 2009, 21:31

Hi,

fre, 06 11 2009 kl. 14:04 +0000, skrev Riccardo Corradini:
> I would inform that my account for sourceforge is
> http://sourceforge.net/users/rikcorradini

I've added you as a developer.

> Now I have just to find out the solution for uploading the package
> because my svn doesn't work
> svn co
https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge
> svn: OPTIONS di
'https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge':
> I I could not connect to the server
(https://octave.svn.sourceforge.net)

> But I could  connect  my browser.
> Is it possible to use ftp or something else similar?

I don't know what could be the cause of this error. Perhaps just try
again later. If you still can't connect, then I guess we'll have to
investigate some more.

Søren



------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Jaroslav Hajek-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Mon, Nov 16, 2009 at 4:48 PM, Riccardo Corradini <riccardocorradini@...> wrote:
Dear Jaroslav,
I have just uploaded into octave-forge extra the openmpi_ext folder containing all the files
I sent you introducing the MPI toolbox that uses MPI Derived datatypes to send and receive almost any octave_value.
Please let me know about your suggestions or if there is something really wrong.
Thanks a lot to all of you for all your patience.
Bests

Riccardo Corradini

Hi Riccardo,

thanks for the info. I'll have a look as soon as I have time.

regards

--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Jaroslav Hajek-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Thu, Nov 19, 2009 at 10:13 PM, Jaroslav Hajek <highegg@...> wrote:


On Mon, Nov 16, 2009 at 4:48 PM, Riccardo Corradini <riccardocorradini@...> wrote:
Dear Jaroslav,
I have just uploaded into octave-forge extra the openmpi_ext folder containing all the files
I sent you introducing the MPI toolbox that uses MPI Derived datatypes to send and receive almost any octave_value.
Please let me know about your suggestions or if there is something really wrong.
Thanks a lot to all of you for all your patience.
Bests

Riccardo Corradini

Hi Riccardo,

thanks for the info. I'll have a look as soon as I have time.


regards

Excellent. I think I just made it work under Intel's C++ and MPI on an AMD cluster.
I have a few comments/questions:

1. info is the first output argument in all functions. I think it should be the second one, so that it can be easily ignored if wanted.
In particular, the check in examples

if not(MPI_Initialized)
   info = MPI_Init();
end

makes no sense (unless I'm missing something) because it's the info output from MPI_Initialized that is tested and that is always zero.

2. include "mpi.h" should precede include "oct.h" everywhere, because oct.h takes some system headers in. Some MPI libs require this (Intel's MPI does).

3. what's your copyright policy? If I improve some of your functions, can I retain the copyright?

thx and best regards
it seems this will be a viable (less convenient but more powerful) alternative to parcellfun/pararrayfun for me.

--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Riccardo Corradini :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Thanks for your hints,
but I don't understand the question concerning the copyright, because it's GNU software.
What is your strategy when you improve JWE and others developers code?
Do you simple add your name ?
I guess my policy is the same of Michael Creel ,JWE and the author of MPITB for octave.
Am i right? Is it clear from the Octave forge contribution?
Thanks a lot
Riccardo Corradini
--- Ven 20/11/09, Jaroslav Hajek <highegg@...> ha scritto:

Da: Jaroslav Hajek <highegg@...>
Oggetto: Re: [OctDev] Contribution to Octave-forge with a simple Open-MPI Package
A: "Riccardo Corradini" <riccardocorradini@...>
Cc: "Søren Hauberg" <soren@...>, octave-dev@...
Data: Venerdì 20 novembre 2009, 12:46



On Thu, Nov 19, 2009 at 10:13 PM, Jaroslav Hajek <highegg@...> wrote:


On Mon, Nov 16, 2009 at 4:48 PM, Riccardo Corradini <riccardocorradini@...> wrote:
Dear Jaroslav,
I have just uploaded into octave-forge extra the openmpi_ext folder containing all the files
I sent you introducing the MPI toolbox that uses MPI Derived datatypes to send and receive almost any octave_value.
Please let me know about your suggestions or if there is something really wrong.
Thanks a lot to all of you for all your patience.
Bests

Riccardo Corradini

Hi Riccardo,

thanks for the info. I'll have a look as soon as I have time.


regards

Excellent. I think I just made it work under Intel's C++ and MPI on an AMD cluster.
I have a few comments/questions:

1. info is the first output argument in all functions. I think it should be the second one, so that it can be easily ignored if wanted.
In particular, the check in examples

if not(MPI_Initialized)
   info = MPI_Init();
end

makes no sense (unless I'm missing something) because it's the info output from MPI_Initialized that is tested and that is always zero.

2. include "mpi.h" should precede include "oct.h" everywhere, because oct.h takes some system headers in. Some MPI libs require this (Intel's MPI does).

3. what's your copyright policy? If I improve some of your functions, can I retain the copyright?

thx and best regards
it seems this will be a viable (less convenient but more powerful) alternative to parcellfun/pararrayfun for me.

--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPI Package

by Jaroslav Hajek-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Fri, Nov 20, 2009 at 1:15 PM, Riccardo Corradini <riccardocorradini@...> wrote:

Thanks for your hints,
but I don't understand the question concerning the copyright, because it's GNU software.
What is your strategy when you improve JWE and others developers code?
Do you simple add your name ?

Yes, basically the question is whether I can add my copyright statement under yours. This is what is usually done in Octave.


--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPIPackage

by Michael Creel :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi all,

In another message, Jaroslav made the comment

1. info is the first output argument in all functions. I think it should be the second one, so that it can be easily ignored if wanted.
In particular, the check in examples

if not(MPI_Initialized)
   info = MPI_Init();
end

makes no sense (unless I'm missing something) because it's the info output from MPI_Initialized that is tested and that is always zero.

This follows the MPI standard, which says:

All MPI routines (except MPI_Wtime and MPI_Wtick) return an error value; C routines as the value of the function and Fortran routines in the last argument. Before the value is returned, the current MPI error handler is called. By default, this error handler aborts the MPI job. The error handler may be changed with MPI_Errhandler_set; the predefined error handler MPI_ERRORS_RETURN may be used to cause error values to be returned. Note that MPI does not guarentee that an MPI program can continue past an error.

MPI_SUCCESS
No error; MPI routine completed successfully.
Following the standard is a big plus, in my opinion. That way, knowledge about MPI previously gained from C or Fortran will be useful when using MPI with Octave. MPITB work this way, too. I have yet to try it, but I believe that I could use Riccardo's stuff as a drop-in replacement for functions from MPITB. Both packages respect the standard. This level of compatibility should help to make both Riccardo's stuff and MPITB stronger, and will favor its use for large scale research.

Michael





------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPIPackage

by Jaroslav Hajek-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Fri, Nov 20, 2009 at 1:44 PM, Michael Creel <michael.creel@...> wrote:
Hi all,

In another message, Jaroslav made the comment


1. info is the first output argument in all functions. I think it should be the second one, so that it can be easily ignored if wanted.
In particular, the check in examples

if not(MPI_Initialized)
   info = MPI_Init();
end

makes no sense (unless I'm missing something) because it's the info output from MPI_Initialized that is tested and that is always zero.

This follows the MPI standard, which says:

All MPI routines (except MPI_Wtime and MPI_Wtick) return an error value; C routines as the value of the function and Fortran routines in the last argument. Before the value is returned, the current MPI error handler is called. By default, this error handler aborts the MPI job. The error handler may be changed with MPI_Errhandler_set; the predefined error handler MPI_ERRORS_RETURN may be used to cause error values to be returned. Note that MPI does not guarentee that an MPI program can continue past an error.

MPI_SUCCESS
No error; MPI routine completed successfully.
Following the standard is a big plus, in my opinion. That way, knowledge about MPI previously gained from C or Fortran will be useful when using MPI with Octave.

Yes, my approach still follows the standard, it's just more convenient to use. The standard says nothing about how external bindings should behave.
 
MPITB work this way, too. I have yet to try it, but I believe that I could use Riccardo's stuff as a drop-in replacement for functions from MPITB. Both packages respect the standard. This level of compatibility should help to make both Riccardo's stuff and MPITB stronger, and will favor its use for large scale research.

Michael

If MPITB does the same, the same arguments apply for MPITB. Why not improve the design?
In C, the error code is the (single) return value; that makes it possible to easily ignore it if you simply resort to the default error handler (which aborts program). Octave has no output arguments but instead multiple return values, and the closest approximation is to always return info as the last argument, so that it can be safely ignored in the calls.

Riccardo, what's your opinion? Do you prefer MPITB compatibility or convenience?

--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPIPackage

by Michael Creel :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Fri, Nov 20, 2009 at 1:57 PM, Jaroslav Hajek <highegg@...> wrote:
>
>
> On Fri, Nov 20, 2009 at 1:44 PM, Michael Creel <michael.creel@...> wrote:
>>
>> Hi all,
>>
>> In another message, Jaroslav made the comment
>>
>>> 1. info is the first output argument in all functions. I think it should
>>> be the second one, so that it can be easily ignored if wanted.
>>> In particular, the check in examples
>>>
>>> if not(MPI_Initialized)
>>>    info = MPI_Init();
>>> end
>>>
>>> makes no sense (unless I'm missing something) because it's the info
>>> output from MPI_Initialized that is tested and that is always zero.
>>
>> This follows the MPI standard, which says:
>>>
>>> All MPI routines (except MPI_Wtime and MPI_Wtick) return an error value;
>>> C routines as the value of the function and Fortran routines in the last
>>> argument. Before the value is returned, the current MPI error handler is
>>> called. By default, this error handler aborts the MPI job. The error handler
>>> may be changed with MPI_Errhandler_set; the predefined error handler
>>> MPI_ERRORS_RETURN may be used to cause error values to be returned. Note
>>> that MPI does not guarentee that an MPI program can continue past an error.
>>>
>>> MPI_SUCCESS No error; MPI routine completed successfully.
>>
>> Following the standard is a big plus, in my opinion. That way, knowledge
>> about MPI previously gained from C or Fortran will be useful when using MPI
>> with Octave.
>
> Yes, my approach still follows the standard, it's just more convenient to
> use. The standard says nothing about how external bindings should behave.
>  

Right, but MPI functions for C or Fortran don't return anything but things like info, flag, status. The contents of messages passed back and forth are not obtained from return values of functions.  It's certainly possible to place a received message into the output of a MPI_Recv binding, and there may be a some logic to the idea, but it is a step away from the C and Fortran way of doing things.  Most people will learn about MPI though C and Fortan tutorials, so following that syntax is not a bad idea. What would you propose to use as outputs of functions?
 
M.

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPIPackage

by Jaroslav Hajek-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Fri, Nov 20, 2009 at 2:57 PM, Michael Creel <michael.creel@...> wrote:


On Fri, Nov 20, 2009 at 1:57 PM, Jaroslav Hajek <highegg@...> wrote:
>
>
> On Fri, Nov 20, 2009 at 1:44 PM, Michael Creel <michael.creel@...> wrote:
>>
>> Hi all,
>>
>> In another message, Jaroslav made the comment
>>
>>> 1. info is the first output argument in all functions. I think it should
>>> be the second one, so that it can be easily ignored if wanted.
>>> In particular, the check in examples
>>>
>>> if not(MPI_Initialized)
>>>    info = MPI_Init();
>>> end
>>>
>>> makes no sense (unless I'm missing something) because it's the info
>>> output from MPI_Initialized that is tested and that is always zero.
>>
>> This follows the MPI standard, which says:
>>>
>>> All MPI routines (except MPI_Wtime and MPI_Wtick) return an error value;
>>> C routines as the value of the function and Fortran routines in the last
>>> argument. Before the value is returned, the current MPI error handler is
>>> called. By default, this error handler aborts the MPI job. The error handler
>>> may be changed with MPI_Errhandler_set; the predefined error handler
>>> MPI_ERRORS_RETURN may be used to cause error values to be returned. Note
>>> that MPI does not guarentee that an MPI program can continue past an error.
>>>
>>> MPI_SUCCESS No error; MPI routine completed successfully.
>>
>> Following the standard is a big plus, in my opinion. That way, knowledge
>> about MPI previously gained from C or Fortran will be useful when using MPI
>> with Octave.
>
> Yes, my approach still follows the standard, it's just more convenient to
> use. The standard says nothing about how external bindings should behave.
>  

Right, but MPI functions for C or Fortran don't return anything but things like info, flag, status. The contents of messages passed back and forth are not obtained from return values of functions.  It's certainly possible to place a received message into the output of a MPI_Recv binding, and there may be a some logic to the idea, but it is a step away from the C and Fortran way of doing things.  Most people will learn about MPI though C and Fortan tutorials, so following that syntax is not a bad idea. What would you propose to use as outputs of functions?
 
M.

I think you didn't understand, Michael. What I'm proposing is just to switch the order to a more convenient one.
Take the simplest example: MPI_Initialized.
This is now called like

[info, flag] = MPI_Initialized ();

where info is always zero (MPI_SUCCESS) and flag is the actual result. What I'm proposing is to use instead

[flag, info] = MPI_Initialized ();

because then the call

flag = MPI_Initialized (); # ignore info

is possible, and it is also possible to do

if (MPI_Initialized)
   something
endif

In C, the corresponding call is
info  = MPI_Initialized (&flag);
but there is *no* way you can preserve this structure in Octave. In Octave, every output argument must be a return value; there is no other way (unless you pass names and manipulate the caller scope directly).

--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPIPackage

by Michael Creel :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Fri, Nov 20, 2009 at 3:20 PM, Jaroslav Hajek <highegg@...> wrote:


On Fri, Nov 20, 2009 at 2:57 PM, Michael Creel <michael.creel@...> wrote:


On Fri, Nov 20, 2009 at 1:57 PM, Jaroslav Hajek <highegg@...> wrote:
>
>
> On Fri, Nov 20, 2009 at 1:44 PM, Michael Creel <michael.creel@...> wrote:
>>
>> Hi all,
>>
>> In another message, Jaroslav made the comment
>>
>>> 1. info is the first output argument in all functions. I think it should
>>> be the second one, so that it can be easily ignored if wanted.
>>> In particular, the check in examples
>>>
>>> if not(MPI_Initialized)
>>>    info = MPI_Init();
>>> end
>>>
>>> makes no sense (unless I'm missing something) because it's the info
>>> output from MPI_Initialized that is tested and that is always zero.
>>
>> This follows the MPI standard, which says:
>>>
>>> All MPI routines (except MPI_Wtime and MPI_Wtick) return an error value;
>>> C routines as the value of the function and Fortran routines in the last
>>> argument. Before the value is returned, the current MPI error handler is
>>> called. By default, this error handler aborts the MPI job. The error handler
>>> may be changed with MPI_Errhandler_set; the predefined error handler
>>> MPI_ERRORS_RETURN may be used to cause error values to be returned. Note
>>> that MPI does not guarentee that an MPI program can continue past an error.
>>>
>>> MPI_SUCCESS No error; MPI routine completed successfully.
>>
>> Following the standard is a big plus, in my opinion. That way, knowledge
>> about MPI previously gained from C or Fortran will be useful when using MPI
>> with Octave.
>
> Yes, my approach still follows the standard, it's just more convenient to
> use. The standard says nothing about how external bindings should behave.
>  

Right, but MPI functions for C or Fortran don't return anything but things like info, flag, status. The contents of messages passed back and forth are not obtained from return values of functions.  It's certainly possible to place a received message into the output of a MPI_Recv binding, and there may be a some logic to the idea, but it is a step away from the C and Fortran way of doing things.  Most people will learn about MPI though C and Fortan tutorials, so following that syntax is not a bad idea. What would you propose to use as outputs of functions?
 
M.

I think you didn't understand, Michael. What I'm proposing is just to switch the order to a more convenient one.
Take the simplest example: MPI_Initialized.
This is now called like

[info, flag] = MPI_Initialized ();

where info is always zero (MPI_SUCCESS) and flag is the actual result. What I'm proposing is to use instead

[flag, info] = MPI_Initialized ();

because then the call

flag = MPI_Initialized (); # ignore info

is possible, and it is also possible to do

if (MPI_Initialized)
   something
endif

In C, the corresponding call is
info  = MPI_Initialized (&flag);
but there is *no* way you can preserve this structure in Octave. In Octave, every output argument must be a return value; there is no other way (unless you pass names and manipulate the caller scope directly).


--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

OK, I see what you mean. I think that new bindings should try to emulate MPITB as closely as possible. For one thing, MPITB is clearly the most widely used way of using MPI with Octave, so most existing code uses its syntax. At the moment it is much more complete. Second, if one follows MPITB syntax, then the documentation that is already written will be valid.  I also hope that it might be possible for the projects to merge or at least benefit from one another, so getting too far apart from the outset for little benefit might not be a good idea. However, I'm a user, not a developer, so I'll start being more quiet about it :-)
M.


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev

Re: Contribution to Octave-forge with a simple Open-MPIPackage

by Jaroslav Hajek-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Fri, Nov 20, 2009 at 3:31 PM, Michael Creel <michael.creel@...> wrote:


On Fri, Nov 20, 2009 at 3:20 PM, Jaroslav Hajek <highegg@...> wrote:


On Fri, Nov 20, 2009 at 2:57 PM, Michael Creel <michael.creel@...> wrote:


On Fri, Nov 20, 2009 at 1:57 PM, Jaroslav Hajek <highegg@...> wrote:
>
>
> On Fri, Nov 20, 2009 at 1:44 PM, Michael Creel <michael.creel@...> wrote:
>>
>> Hi all,
>>
>> In another message, Jaroslav made the comment
>>
>>> 1. info is the first output argument in all functions. I think it should
>>> be the second one, so that it can be easily ignored if wanted.
>>> In particular, the check in examples
>>>
>>> if not(MPI_Initialized)
>>>    info = MPI_Init();
>>> end
>>>
>>> makes no sense (unless I'm missing something) because it's the info
>>> output from MPI_Initialized that is tested and that is always zero.
>>
>> This follows the MPI standard, which says:
>>>
>>> All MPI routines (except MPI_Wtime and MPI_Wtick) return an error value;
>>> C routines as the value of the function and Fortran routines in the last
>>> argument. Before the value is returned, the current MPI error handler is
>>> called. By default, this error handler aborts the MPI job. The error handler
>>> may be changed with MPI_Errhandler_set; the predefined error handler
>>> MPI_ERRORS_RETURN may be used to cause error values to be returned. Note
>>> that MPI does not guarentee that an MPI program can continue past an error.
>>>
>>> MPI_SUCCESS No error; MPI routine completed successfully.
>>
>> Following the standard is a big plus, in my opinion. That way, knowledge
>> about MPI previously gained from C or Fortran will be useful when using MPI
>> with Octave.
>
> Yes, my approach still follows the standard, it's just more convenient to
> use. The standard says nothing about how external bindings should behave.
>  

Right, but MPI functions for C or Fortran don't return anything but things like info, flag, status. The contents of messages passed back and forth are not obtained from return values of functions.  It's certainly possible to place a received message into the output of a MPI_Recv binding, and there may be a some logic to the idea, but it is a step away from the C and Fortran way of doing things.  Most people will learn about MPI though C and Fortan tutorials, so following that syntax is not a bad idea. What would you propose to use as outputs of functions?
 
M.

I think you didn't understand, Michael. What I'm proposing is just to switch the order to a more convenient one.
Take the simplest example: MPI_Initialized.
This is now called like

[info, flag] = MPI_Initialized ();

where info is always zero (MPI_SUCCESS) and flag is the actual result. What I'm proposing is to use instead

[flag, info] = MPI_Initialized ();

because then the call

flag = MPI_Initialized (); # ignore info

is possible, and it is also possible to do

if (MPI_Initialized)
   something
endif

In C, the corresponding call is
info  = MPI_Initialized (&flag);
but there is *no* way you can preserve this structure in Octave. In Octave, every output argument must be a return value; there is no other way (unless you pass names and manipulate the caller scope directly).


--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

OK, I see what you mean. I think that new bindings should try to emulate MPITB as closely as possible. For one thing, MPITB is clearly the most widely used way of using MPI with Octave, so most existing code uses its syntax. At the moment it is much more complete.

But MPITB is already free software (isn't it?), so why develop a clone? MPITB users can still run their code using MPITB.
But this is a chance to do things better than MPITB.

 
Second, if one follows MPITB syntax, then the documentation that is already written will be valid. 

Documentation? What documentation?
 
I also hope that it might be possible for the projects to merge or at least benefit from one another, so getting too far apart from the outset for little benefit might not be a good idea.

I wouldn't call it a little benefit. I'm not sure if any merge is possible; in any case I don't think there's a public repository for MPITB (vital for shared development). I was also hoping I could help keep this package better synced with current Octave development.
Ultimately it's up to Riccardo to decide whether the development should be constrained by MPITB. If so, I'll probably fork my own version.


--
RNDr. Jaroslav Hajek
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Octave-dev mailing list
Octave-dev@...
https://lists.sourceforge.net/lists/listinfo/octave-dev
< Prev | 1 - 2 | Next >