To: J3 11-103r1 From: Craig Rasmussen/Nick Maclaren Subject: Copy to Contiguous Example using C Descriptor Date: 2011 January 17 References: N1838-2 Discussion: In N1838-2 there is an example of how to use the CFI_cdesc_t type in a C implementation of a BIND(C) interface. This paper provides another example of using the CFI_cdesc_t type in C. This new example provides code to copy an array (possibly noncontiguous) into a contiguous buffer. Edits to N1838-2: [21:33] At the end of A.2, append the following text: The following example provides functions that can be used to copy an array described by a CFI_cdesc_t descriptor to a contiguous buffer. The input array need not be contiguous. The C functions are: #include "ISO_Fortran_binding.h" /* * Returns the number of elements in the array described by desc. * The array need not be contiguous and may have zero size. */ size_t numElements(const CFI_cdesc_t * desc) { CFI_rank_t r; size_t num = 1; for (r = 0; r < desc->rank; r++) { num *= desc->dim[r].extent; } return num; } /* * Auxiliary routine to loop over a particular rank. */ static void * _copyToContiguous (const CFI_cdesc_t * desc void * output, const void * input, CFI_rank_t rank) { CFI_index_t e; if (rank == 0) { /* copy scalar element */ memcpy (output, input, desc->elem_len); output = (void *)((char *)output + desc->elem_len); } else { for (e = 0; e < desc->dim[rank-1].extent; e++) { /* recurse on subarrays of lesser rank */ output = _copyToContiguous (desc, output, input, rank-1); input = (void *) ((char *)input + desc->dim[rank].sm); } } return output; } /* * General routine to copy the elements in the array described by desc * to buffer, as done by sequence association. The array itself may * be non-contiguous. This is not the most efficient approach. */ void copyToContiguous (void * buffer, const CFI_cdesc_t * desc) { _copyToContiguous (desc, buffer, desc->base_addr, desc->rank); } /* * Send the data referenced by desc using the function send_contig, which * requires a contiguous buffer. If needed, copy the data to a contiguous * buffer before calling send_contig. */ int send_desc_data (CFI_cdesc_t * desc) { if (isContiguous(desc)) { // the data referenced by desc is already contiguous, just send it send_contig(desc->base_addr, numElements(desc)*desc->elem_len); } else { void * buffer = malloc(numElements(desc)*desc->elem_len); copyToContiguous(buffer, desc); // send the contiguous copy of the data from desc send(buffer, numElements(desc)*desc->elem_len); free(buffer); } }