+ op->apply( contiguous_buf_char, noncontiguous_buf_char, &n, this);
+}
+
+int Datatype::create_contiguous(int count, MPI_Datatype old_type, MPI_Aint lb, MPI_Datatype* new_type){
+ if(old_type->flags_ & DT_FLAG_DERIVED){
+ //handle this case as a hvector with stride equals to the extent of the datatype
+ return create_hvector(count, 1, old_type->get_extent(), old_type, new_type);
+ }
+ if(count>0)
+ *new_type = new Type_Contiguous(count * old_type->size(), lb, lb + count * old_type->size(),
+ DT_FLAG_DERIVED, count, old_type);
+ else
+ *new_type = new Datatype(count * old_type->size(), lb, lb + count * old_type->size(),0);
+ return MPI_SUCCESS;
+}
+
+int Datatype::create_vector(int count, int block_length, int stride, MPI_Datatype old_type, MPI_Datatype* new_type)
+{
+ int retval;
+ if (block_length<0)
+ return MPI_ERR_ARG;
+ MPI_Aint lb = 0;
+ MPI_Aint ub = 0;
+ if(count>0){
+ lb=old_type->lb();
+ ub=((count-1)*stride+block_length-1)*old_type->get_extent()+old_type->ub();
+ }
+ if(old_type->flags() & DT_FLAG_DERIVED || stride != block_length){
+ *new_type = new Type_Vector(count * (block_length) * old_type->size(), lb, ub,
+ DT_FLAG_DERIVED, count, block_length, stride, old_type);
+ retval=MPI_SUCCESS;
+ }else{
+ /* in this situation the data are contiguous thus it's not required to serialize and unserialize it*/
+ *new_type = new Datatype(count * block_length * old_type->size(), 0, ((count -1) * stride + block_length)*
+ old_type->size(), DT_FLAG_CONTIGUOUS);
+ retval=MPI_SUCCESS;
+ }
+ return retval;
+}
+
+
+int Datatype::create_hvector(int count, int block_length, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type)
+{
+ int retval;
+ if (block_length<0)
+ return MPI_ERR_ARG;
+ MPI_Aint lb = 0;
+ MPI_Aint ub = 0;
+ if(count>0){
+ lb=old_type->lb();
+ ub=((count-1)*stride)+(block_length-1)*old_type->get_extent()+old_type->ub();
+ }
+ if(old_type->flags() & DT_FLAG_DERIVED || stride != block_length*old_type->get_extent()){
+ *new_type = new Type_Hvector(count * (block_length) * old_type->size(), lb, ub,
+ DT_FLAG_DERIVED, count, block_length, stride, old_type);
+ retval=MPI_SUCCESS;
+ }else{
+ /* in this situation the data are contiguous thus it's not required to serialize and unserialize it*/
+ *new_type = new Datatype(count * block_length * old_type->size(), 0, count * block_length * old_type->size(), DT_FLAG_CONTIGUOUS);
+ retval=MPI_SUCCESS;
+ }
+ return retval;
+}
+
+int Datatype::create_indexed(int count, int* block_lengths, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type){
+ int size = 0;
+ bool contiguous=true;
+ MPI_Aint lb = 0;
+ MPI_Aint ub = 0;
+ if(count>0){
+ lb=indices[0]*old_type->get_extent();
+ ub=indices[0]*old_type->get_extent() + block_lengths[0]*old_type->ub();
+ }
+
+ for (int i = 0; i < count; i++) {
+ if (block_lengths[i] < 0)
+ return MPI_ERR_ARG;
+ size += block_lengths[i];
+
+ if(indices[i]*old_type->get_extent()+old_type->lb()<lb)
+ lb = indices[i]*old_type->get_extent()+old_type->lb();
+ if(indices[i]*old_type->get_extent()+block_lengths[i]*old_type->ub()>ub)
+ ub = indices[i]*old_type->get_extent()+block_lengths[i]*old_type->ub();
+
+ if ( (i< count -1) && (indices[i]+block_lengths[i] != indices[i+1]) )
+ contiguous=false;
+ }
+ if(old_type->flags_ & DT_FLAG_DERIVED)
+ contiguous=false;
+
+ if(!contiguous){
+ *new_type = new Type_Indexed(size * old_type->size(),lb,ub,
+ DT_FLAG_DERIVED|DT_FLAG_DATA, count, block_lengths, indices, old_type);
+ }else{
+ Datatype::create_contiguous(size, old_type, lb, new_type);
+ }
+ return MPI_SUCCESS;
+}
+
+int Datatype::create_hindexed(int count, int* block_lengths, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* new_type){
+ int size = 0;
+ bool contiguous=true;
+ MPI_Aint lb = 0;
+ MPI_Aint ub = 0;
+ if(count>0){
+ lb=indices[0] + old_type->lb();
+ ub=indices[0] + block_lengths[0]*old_type->ub();
+ }
+ for (int i = 0; i < count; i++) {
+ if (block_lengths[i] < 0)
+ return MPI_ERR_ARG;
+ size += block_lengths[i];
+
+ if(indices[i]+old_type->lb()<lb)
+ lb = indices[i]+old_type->lb();
+ if(indices[i]+block_lengths[i]*old_type->ub()>ub)
+ ub = indices[i]+block_lengths[i]*old_type->ub();
+
+ if ( (i< count -1) && (indices[i]+block_lengths[i]*(static_cast<int>(old_type->size())) != indices[i+1]) )
+ contiguous=false;
+ }
+ if (old_type->flags_ & DT_FLAG_DERIVED || lb!=0)
+ contiguous=false;
+
+ if(!contiguous){
+ *new_type = new Type_Hindexed(size * old_type->size(),lb,ub,
+ DT_FLAG_DERIVED|DT_FLAG_DATA, count, block_lengths, indices, old_type);
+ }else{
+ Datatype::create_contiguous(size, old_type, lb, new_type);
+ }
+ return MPI_SUCCESS;
+}
+
+int Datatype::create_struct(int count, int* block_lengths, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* new_type){
+ size_t size = 0;
+ bool contiguous=true;
+ size = 0;
+ MPI_Aint lb = 0;
+ MPI_Aint ub = 0;
+ if(count>0){
+ lb=indices[0] + old_types[0]->lb();
+ ub=indices[0] + block_lengths[0]*old_types[0]->ub();
+ }
+ bool forced_lb=false;
+ bool forced_ub=false;
+ for (int i = 0; i < count; i++) {
+ if (block_lengths[i]<0)
+ return MPI_ERR_ARG;
+ if (old_types[i]->flags_ & DT_FLAG_DERIVED)
+ contiguous=false;
+
+ size += block_lengths[i]*old_types[i]->size();
+ if (old_types[i]==MPI_LB){
+ lb=indices[i];
+ forced_lb=true;
+ }
+ if (old_types[i]==MPI_UB){
+ ub=indices[i];
+ forced_ub=true;
+ }
+
+ if(!forced_lb && indices[i]+old_types[i]->lb()<lb)
+ lb = indices[i];
+ if(!forced_ub && indices[i]+block_lengths[i]*old_types[i]->ub()>ub)
+ ub = indices[i]+block_lengths[i]*old_types[i]->ub();
+
+ if ( (i< count -1) && (indices[i]+block_lengths[i]*static_cast<int>(old_types[i]->size()) != indices[i+1]) )
+ contiguous=false;
+ }
+ if(!contiguous){
+ *new_type = new Type_Struct(size, lb,ub, DT_FLAG_DERIVED|DT_FLAG_DATA,
+ count, block_lengths, indices, old_types);
+ }else{
+ Datatype::create_contiguous(size, MPI_CHAR, lb, new_type);
+ }
+ return MPI_SUCCESS;