# vim: set ft=c:

MPI_Address:
    location: BUFFER, asynchronous=True, suppress=f08_intent, [location in caller memory]
    address: DISPLACEMENT, direction=out, [address of location]
    .desc: Gets the address of a location in memory
    .skip: global_cs
    .replace: removed with MPI_Get_address

MPI_Type_create_f90_integer:
    .desc: Return a predefined type that matches the specified range

MPI_Type_create_f90_real:
    .desc: Return a predefined type that matches the specified range

MPI_Type_create_f90_complex:
    .desc: Return a predefined type that matches the specified range

MPI_Get_address:
    .desc: Get the address of a location in memory
    .skip: global_cs
{ -- error_check -- location
    /* location can be NULL (MPI_BOTTOM) */
}

MPI_Get_count:
    .desc: Gets the number of "top level" elements
    .skip: global_cs
    .poly_impl: use_aint

MPI_Get_elements:
    .desc: Returns the number of basic elements
    .skip: global_cs
{
    MPI_Count count_x;
    MPI_Count byte_count = MPIR_STATUS_GET_COUNT(*status);
    mpi_errno = MPIR_Get_elements_x_impl(&byte_count, datatype, &count_x);
    if (mpi_errno) {
        goto fn_fail;
    }

    /* clip the value if it cannot be correctly returned to the user */
    *count = (count_x > INT_MAX) ? MPI_UNDEFINED : (int) count_x;

    if (byte_count != 0) {
        *count = MPI_UNDEFINED;
    }
}
{ -- large_count --
    MPI_Count byte_count = MPIR_STATUS_GET_COUNT(*status);
    mpi_errno = MPIR_Get_elements_x_impl(&byte_count, datatype, count);
    if (mpi_errno) {
        goto fn_fail;
    }

    if (byte_count != 0) {
        *count = MPI_UNDEFINED;
    }
}

MPI_Get_elements_x:
    .desc: Returns the number of basic elements
    .skip: global_cs
{
    MPI_Count byte_count = MPIR_STATUS_GET_COUNT(*status);
    mpi_errno = MPIR_Get_elements_x_impl(&byte_count, datatype, count);
    MPIR_ERR_CHECK(mpi_errno);

    if (byte_count != 0) {
        *count = MPI_UNDEFINED;
    }
}

MPI_Pack:
    .desc: Packs a datatype into contiguous memory
    .skip: global_cs
    .poly_impl: use_aint
{ -- error_check -- inbuf, outbuf
    /* MPI_BOTTOM cannot be used when count > 1 */
    if (incount > 1) {
        MPIR_ERRTEST_ARGNULL(inbuf, "inbuf", mpi_errno);
    }
}
{ -- early_return --
    MPI_Aint dt_size;
    MPIR_Datatype_get_size_macro(datatype, dt_size);
    if (dt_size == 0) {
        goto fn_exit;
    }
}

MPI_Pack_external:
    .desc: Packs a datatype into contiguous memory, using the external32 format
    .poly_impl: use_aint
{ -- early_return --
    if (incount == 0) {
        goto fn_exit;
    }
}

MPI_Pack_external_size:
    .desc: Returns the upper bound on the amount of space needed to pack a message using MPI_Pack_external.
    .poly_impl: use_aint

MPI_Pack_size:
    .desc: Returns the upper bound on the amount of space needed to pack a message
    .poly_impl: use_aint

MPI_Unpack:
    .desc: Unpack a buffer according to a datatype into contiguous memory
    .seealso: MPI_Pack, MPI_Pack_size
    .poly_impl: use_aint
{ -- error_check -- inbuf, outbuf
    /* MPI_BOTTOM cannot be used when count > 1 */
    if (outcount > 1) {
        MPIR_ERRTEST_ARGNULL(outbuf, "outbuf", mpi_errno);
    }
}
{ -- early_return --
    MPI_Aint dt_size;
    MPIR_Datatype_get_size_macro(datatype, dt_size);
    if (dt_size == 0) {
        goto fn_exit;
    }
}

MPI_Unpack_external:
    .desc: Unpack a buffer (packed with MPI_Pack_external) according to a datatype into contiguous memory
    .poly_impl: use_aint
{ -- early_return --
    if (insize == 0) {
        goto fn_exit;
    }
}

MPI_Status_set_elements:
    .desc: Set the number of elements in a status
{
    mpi_errno = MPIR_Status_set_elements_x_impl(status, datatype, (MPI_Count) count);
    if (mpi_errno) {
        goto fn_fail;
    }
}
{ -- large_count --
    mpi_errno = MPIR_Status_set_elements_x_impl(status, datatype, count);
    if (mpi_errno) {
        goto fn_fail;
    }
}

MPI_Status_set_elements_x:
    .desc: Set the number of elements in a status

MPI_Type_commit:
    .desc: Commits the datatype
{ -- early_return --
    if (MPIR_DATATYPE_IS_PREDEFINED(*datatype)) {
        goto fn_exit;
    }
}

MPI_Type_free:
    .desc: Frees the datatype
{ -- error_check --
    if (MPIR_DATATYPE_IS_PREDEFINED(*datatype)) {
        mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
                                         __func__, __LINE__, MPI_ERR_TYPE,
                                         "**dtypeperm", 0);
        goto fn_fail;
    }
}

MPI_Type_extent:
    datatype: DATATYPE, [datatype to get information on]
    extent: DISPLACEMENT_AINT_COUNT_SMALL, direction=out, [extent of datatype]
    .desc: Returns the extent of a datatype
    .skip: global_cs
    .replace: removed with MPI_Type_get_extent
{
    MPI_Aint lb;
    mpi_errno = MPIR_Type_get_extent_impl(datatype, &lb, extent);
    if (mpi_errno) {
        goto fn_fail;
    }
}

MPI_Type_lb:
    datatype: DATATYPE, [datatype to get information on]
    displacement: DISPLACEMENT_AINT_COUNT_SMALL, direction=out, [displacement of lower bound from origin, in bytes]
    .desc: Returns the lower-bound of a datatype
    .skip: global_cs
    .replace: removed with MPI_Type_get_extent
{
    MPI_Aint extent;
    mpi_errno = MPIR_Type_get_extent_impl(datatype, displacement, &extent);
    if (mpi_errno) {
        goto fn_fail;
    }
}

MPI_Type_ub:
    datatype: DATATYPE, [datatype to get information on]
    displacement: DISPLACEMENT_AINT_COUNT_SMALL, direction=out, [displacement of upper bound from origin, in bytes]
    .desc: Returns the upper bound of a datatype
    .skip: global_cs
    .replace: removed with MPI_Type_get_extent
{
    MPI_Aint lb, extent;
    mpi_errno = MPIR_Type_get_extent_impl(datatype, &lb, &extent);
    if (mpi_errno) {
        goto fn_fail;
    }
    *displacement = lb + extent;
}

MPI_Type_get_contents:
    .desc: get type contents
    .skip: ThreadSafe
{ -- error_check --
    if (MPIR_DATATYPE_IS_PREDEFINED(datatype)) {
        mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_TYPE, "**contentspredef", 0);
        goto fn_fail;
    }
}

MPI_Type_get_envelope:
    .desc: get type envelope
    .skip: global_cs

MPI_Type_get_extent:
    .desc: Get the lower bound and extent for a Datatype
    .skip: global_cs
    .poly_impl: use_aint

MPI_Type_get_extent_x:
    .desc: Get the lower bound and extent as MPI_Count values for a datatype
    .skip: global_cs

MPI_Type_get_true_extent:
    .desc: Get the true lower bound and extent for a datatype
    .skip: global_cs
    .poly_impl: use_aint

MPI_Type_get_true_extent_x:
    .desc: Get the true lower bound and extent as MPI_Count values for a datatype
    .skip: global_cs

MPI_Type_get_value_index:
    .desc: returns a handle to a predefined datatype suitable for the use with MPI_MINLOC and MPI_MAXLOC if such a predefined type exists

MPI_Type_size:
    .desc: Return the number of bytes occupied by entries in the datatype
    .skip: global_cs
    .poly_impl: use_aint

MPI_Type_size_x:
    .desc: Return the number of bytes occupied by entries in the datatype
    .skip: global_cs

MPI_Type_set_name:
    .desc: set datatype name
    .skip: ThreadSafe

MPI_Type_get_name:
    .desc: Get the print name for a datatype
    .docnotes: ThreadSafeNoUpdate, NULL

MPI_Type_contiguous:
    .desc: Creates a contiguous datatype

MPI_Type_create_darray:
    .desc: Create a datatype representing a distributed array
    .skip: validate-ORDER, validate-RANK_NNI
{ -- error_check --
    CHECKENUM: order, storageorder, MPI_ORDER_C MPI_ORDER_FORTRAN
    MPIR_ERR_CHKANDJUMP3((rank < 0 || rank >= size), mpi_errno, MPI_ERR_RANK,
                          "**argrange", "**argrange %s %d %d", "rank", rank, (size - 1));
}

MPI_Type_create_subarray:
    .desc: Create a datatype for a subarray of a regular, multidimensional array
    .skip: validate-ORDER
{ -- error_check --
    CHECKENUM: order, storageorder, MPI_ORDER_C MPI_ORDER_FORTRAN
}

MPI_Type_create_hindexed:
    .desc: Create a datatype for an indexed datatype with displacements in bytes

MPI_Type_create_hindexed_block:
    .desc: Create an hindexed datatype with constant-sized blocks

MPI_Type_create_hvector:
    .desc: Create a datatype with a constant stride given in bytes

MPI_Type_create_indexed_block:
    .desc: Create an indexed datatype with constant-sized blocks

MPI_Type_create_resized:
    .desc: Create a datatype with a new lower bound and extent from an existing datatype

MPI_Type_create_struct:
    .desc: Create an MPI datatype from a general set of datatypes, displacements, and block sizes

MPI_Type_dup:
    .desc: Duplicate a datatype

MPI_Type_hindexed:
    count: DTYPE_NUM_ELEM_NNI_SMALL, [number of blocks -- also number of entries in array_of_displacements and array_of_blocklengths]
    array_of_blocklengths: DTYPE_NUM_ELEM_NNI_SMALL, length=count, [number of elements in each block]
    array_of_displacements: DISPLACEMENT_AINT_COUNT_SMALL, length=count, [byte displacement of each block]
    oldtype: DATATYPE, [old datatype]
    newtype: DATATYPE, direction=out, [new datatype]
    .desc: Creates an indexed datatype with offsets in bytes
    .replace: removed with MPI_Type_create_hindexed

MPI_Type_hvector:
    count: DTYPE_NUM_ELEM_NNI_SMALL, [number of blocks]
    blocklength: DTYPE_NUM_ELEM_NNI_SMALL, [number of elements in each block]
    stride: DTYPE_STRIDE_BYTES_SMALL, [number of bytes between start of each block]
    oldtype: DATATYPE, [old datatype]
    newtype: DATATYPE, direction=out, [new datatype]
    .desc: type_hvector
    .replace: removed with MPI_Type_create_hvector
    .skip: validate-DTYPE_STRIDE_BYTES_SMALL

MPI_Type_indexed:
    .desc: Creates an indexed datatype

MPI_Type_struct:
    count: DTYPE_NUM_ELEM_NNI_SMALL, [number of blocks also number of entries in arrays array_of_types, array_of_displacements, and array_of_blocklengths]
    array_of_blocklengths: DTYPE_NUM_ELEM_NNI_SMALL, length=count, [number of elements in each block]
    array_of_displacements: DISPLACEMENT_AINT_COUNT_SMALL, length=count, [byte displacement of each block]
    array_of_types: DATATYPE, length=count, [types of elements in each block]
    newtype: DATATYPE, direction=out, [new datatype]
    .desc: Creates a struct datatype
    .replace: removed with MPI_Type_create_struct

MPI_Type_vector:
    .desc: Creates a vector (strided) datatype

MPI_Type_match_size:
    .desc: Find an MPI datatype matching a specified size
    .skip: validate-TYPECLASS, validate-TYPECLASS_SIZE

MPIX_Type_iov_len:
    datatype: DATATYPE
    max_iov_bytes: DISPLACEMENT_COUNT, [maximum number bytes in the iovs]
    iov_len: DISPLACEMENT_COUNT, direction=out, [number of iovs within max_iov_bytes]
    actual_iov_bytes: DISPLACEMENT_COUNT, direction=out, [actual number of bytes in the iovs]
    .desc: Return the number of contiguous segments within max_iov_bytes
{
    MPI_Aint max_iov_bytes_i, iov_len_i, actual_iov_bytes_i;

    max_iov_bytes_i = (MPI_Aint) max_iov_bytes;
    MPIR_Assert(max_iov_bytes_i == max_iov_bytes);

    mpi_errno = MPIR_Typerep_iov_len(1, datatype, max_iov_bytes_i, &iov_len_i, &actual_iov_bytes_i);
    if (mpi_errno) {
        goto fn_fail;
    }

    *iov_len = iov_len_i;
    MPIR_Assert(*iov_len == iov_len_i);
    *actual_iov_bytes = actual_iov_bytes_i;
    MPIR_Assert(*actual_iov_bytes == actual_iov_bytes_i);
}

MPIX_Type_iov:
    datatype: DATATYPE
    iov_offset: DISPLACEMENT_COUNT, [number of contiguous segments to skip]
    iov: IOVEC, direction=out, [contiguous segments array for output]
    max_iov_len: DISPLACEMENT_COUNT, [capacity for the segments array]
    actual_iov_len: DISPLACEMENT_COUNT, direction=out, [actual number of segments in output]
    .desc: Return contiguous segments starting from an iov offset
{
    MPI_Aint iov_offset_i, max_iov_len_i, actual_iov_len_i;

    iov_offset_i = iov_offset;
    MPIR_Assert(iov_offset_i == iov_offset);
    max_iov_len_i = max_iov_len;
    MPIR_Assert(max_iov_len_i == max_iov_len);

    /* make sure MPIX_Iov is compatible with struct iovec */
    MPIR_Assert(sizeof(MPI_Aint) == sizeof(size_t));
    mpi_errno = MPIR_Typerep_to_iov_offset(NULL, 1, datatype, iov_offset_i, (struct iovec *) iov, max_iov_len_i, &actual_iov_len_i);
    if (mpi_errno) {
        goto fn_fail;
    }

    *actual_iov_len = actual_iov_len_i;
    MPIR_Assert(*actual_iov_len == actual_iov_len_i);
}
