1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3 * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
4 * University Research and Technology
5 * Corporation. All rights reserved.
6 * Copyright (c) 2004-2016 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart,
10 * University of Stuttgart. All rights reserved.
11 * Copyright (c) 2004-2006 The Regents of the University of California.
12 * All rights reserved.
13 * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
14 * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved.
15 * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
16 * Copyright (c) 2014-2015 Research Organization for Information Science
17 * and Technology (RIST). All rights reserved.
18 * $COPYRIGHT$
19 *
20 * Additional copyrights may follow
21 *
22 * $HEADER$
23 */
24
25 #include "ompi_config.h"
26
27 #include <stddef.h>
28
29 #include "ompi/datatype/ompi_datatype.h"
30
31 int32_t ompi_datatype_create_subarray(int ndims,
32 int const* size_array,
33 int const* subsize_array,
34 int const* start_array,
35 int order,
36 const ompi_datatype_t* oldtype,
37 ompi_datatype_t** newtype)
38 {
39 ompi_datatype_t *last_type;
40 int32_t i, step, end_loop;
41 MPI_Aint size, displ, extent;
42
43 /**
44 * If the oldtype contains the original MPI_LB and MPI_UB markers then we
45 * are forced to follow the MPI standard suggestion and reset these 2
46 * markers (MPI 3.0 page 96 line 37). Otherwise we can simply resize the
47 * datatype.
48 */
49 ompi_datatype_type_extent( oldtype, &extent );
50
51 /* If the ndims is zero then return the NULL datatype */
52 if( ndims < 2 ) {
53 if( 0 == ndims ) {
54 ompi_datatype_duplicate(&ompi_mpi_datatype_null.dt, newtype);
55 return MPI_SUCCESS;
56 }
57 ompi_datatype_create_contiguous( subsize_array[0], oldtype, &last_type );
58 size = size_array[0];
59 displ = start_array[0];
60 goto replace_subarray_type;
61 }
62
63 if( MPI_ORDER_C == order ) {
64 i = ndims - 1;
65 step = -1;
66 end_loop = -1;
67 } else {
68 i = 0;
69 step = 1;
70 end_loop = ndims;
71 }
72
73 /* As we know that the ndims is at least 1 we can start by creating the
74 * first dimension data outside the loop, such that we dont have to create
75 * a duplicate of the oldtype just to be able to free it.
76 */
77 ompi_datatype_create_vector( subsize_array[i+step], subsize_array[i], size_array[i],
78 oldtype, newtype );
79
80 last_type = *newtype;
81 size = (MPI_Aint)size_array[i] * (MPI_Aint)size_array[i+step];
82 displ = (MPI_Aint)start_array[i] + (MPI_Aint)start_array[i+step] * (MPI_Aint)size_array[i];
83 for( i += 2 * step; i != end_loop; i += step ) {
84 ompi_datatype_create_hvector( subsize_array[i], 1, size * extent,
85 last_type, newtype );
86 ompi_datatype_destroy( &last_type );
87
88 displ += size * start_array[i];
89 size *= size_array[i];
90 last_type = *newtype;
91 }
92
93 replace_subarray_type:
94 /**
95 * We need to shift the content (useful data) of the datatype, so
96 * we need to force the displacement to be moved. Therefore, we
97 * cannot use resize as it will only set the soft lb and ub
98 * markers without moving the data. Instead, we have to create a
99 * new data, and insert the last_Type with the correct
100 * displacement.
101 */
102 *newtype = ompi_datatype_create( last_type->super.desc.used );
103 ompi_datatype_add( *newtype, last_type, 1, displ * extent, size * extent);
104 ompi_datatype_destroy( &last_type );
105 opal_datatype_resize( &(*newtype)->super, 0, size * extent );
106
107 return OMPI_SUCCESS;
108 }