Home | History | Annotate | Line # | Download | only in m4
      1      1.1  mrg dnl Support macro file for intrinsic functions.
      2      1.1  mrg dnl Contains the generic sections of the array functions.
      3      1.1  mrg dnl This file is part of the GNU Fortran Runtime Library (libgfortran)
      4      1.1  mrg dnl Distributed under the GNU GPL with exception.  See COPYING for details.
      5      1.1  mrg dnl
      6      1.1  mrg dnl Pass the implementation for a single section as the parameter to
      7      1.1  mrg dnl {MASK_}ARRAY_FUNCTION.
      8      1.1  mrg dnl The variables base, delta, and len describe the input section.
      9      1.1  mrg dnl For masked section the mask is described by mbase and mdelta.
     10      1.1  mrg dnl These should not be modified. The result should be stored in *dest.
     11      1.1  mrg dnl The names count, extent, sstride, dstride, base, dest, rank, dim
     12      1.1  mrg dnl retarray, array, pdim and mstride should not be used.
     13      1.1  mrg dnl The variable n is declared as index_type and may be used.
     14      1.1  mrg dnl Other variable declarations may be placed at the start of the code,
     15      1.1  mrg dnl The types of the array parameter and the return value are
     16      1.1  mrg dnl atype_name and rtype_name respectively.
     17      1.1  mrg dnl Execution should be allowed to continue to the end of the block.
     18      1.1  mrg dnl You should not return or break from the inner loop of the implementation.
     19      1.1  mrg dnl Care should also be taken to avoid using the names defined in iparm.m4
     20      1.1  mrg define(START_ARRAY_FUNCTION,
     21      1.1  mrg `
     22      1.1  mrg extern void name`'rtype_qual`_'atype_code (rtype * const restrict, 
     23      1.1  mrg 	atype` * const restrict, const 'index_type` * const restrict'back_arg`);
     24      1.1  mrg export_proto('name`'rtype_qual`_'atype_code);
     25      1.1  mrg 
     26      1.1  mrg void
     27      1.1  mrg name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
     28      1.1  mrg 	'atype` * const restrict array, 
     29      1.1  mrg 	const index_type * const restrict pdim'back_arg`)
     30      1.1  mrg {
     31      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     32      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     33      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     34      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
     35      1.1  mrg   const 'atype_name * restrict base;
     36      1.1  mrg   rtype_name * restrict dest;
     37      1.1  mrg   index_type rank;
     38      1.1  mrg   index_type n;
     39      1.1  mrg   index_type len;
     40      1.1  mrg   index_type delta;
     41      1.1  mrg   index_type dim;
     42      1.1  mrg   int continue_loop;
     43      1.1  mrg 
     44      1.1  mrg   /* Make dim zero based to avoid confusion.  */
     45      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
     46      1.1  mrg   dim = (*pdim) - 1;
     47      1.1  mrg 
     48      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
     49      1.1  mrg     {
     50      1.1  mrg       runtime_error ("Dim argument incorrect in u_name intrinsic: "
     51      1.1  mrg  		     "is %ld, should be between 1 and %ld",
     52      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
     53      1.1  mrg     }
     54      1.1  mrg 
     55      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
     56      1.1  mrg   if (len < 0)
     57      1.1  mrg     len = 0;
     58      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
     59      1.1  mrg 
     60      1.1  mrg   for (n = 0; n < dim; n++)
     61      1.1  mrg     {
     62      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
     63      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
     64      1.1  mrg 
     65      1.1  mrg       if (extent[n] < 0)
     66      1.1  mrg 	extent[n] = 0;
     67      1.1  mrg     }
     68      1.1  mrg   for (n = dim; n < rank; n++)
     69      1.1  mrg     {
     70      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
     71      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
     72      1.1  mrg 
     73      1.1  mrg       if (extent[n] < 0)
     74      1.1  mrg 	extent[n] = 0;
     75      1.1  mrg     }
     76      1.1  mrg 
     77      1.1  mrg   if (retarray->base_addr == NULL)
     78      1.1  mrg     {
     79      1.1  mrg       size_t alloc_size, str;
     80      1.1  mrg 
     81      1.1  mrg       for (n = 0; n < rank; n++)
     82      1.1  mrg 	{
     83      1.1  mrg 	  if (n == 0)
     84      1.1  mrg 	    str = 1;
     85      1.1  mrg 	  else
     86      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
     87      1.1  mrg 
     88      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
     89      1.1  mrg 
     90      1.1  mrg 	}
     91      1.1  mrg 
     92      1.1  mrg       retarray->offset = 0;
     93      1.1  mrg       retarray->dtype.rank = rank;
     94      1.1  mrg 
     95      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
     96      1.1  mrg 
     97      1.1  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
     98      1.1  mrg       if (alloc_size == 0)
     99  1.1.1.2  mrg 	return;
    100      1.1  mrg     }
    101      1.1  mrg   else
    102      1.1  mrg     {
    103      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    104      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    105      1.1  mrg 		       " u_name intrinsic: is %ld, should be %ld",
    106      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    107      1.1  mrg 		       (long int) rank);
    108      1.1  mrg 
    109      1.1  mrg       if (unlikely (compile_options.bounds_check))
    110      1.1  mrg 	bounds_ifunction_return ((array_t *) retarray, extent,
    111      1.1  mrg 				 "return value", "u_name");
    112      1.1  mrg     }
    113      1.1  mrg 
    114      1.1  mrg   for (n = 0; n < rank; n++)
    115      1.1  mrg     {
    116      1.1  mrg       count[n] = 0;
    117      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    118      1.1  mrg       if (extent[n] <= 0)
    119      1.1  mrg 	return;
    120      1.1  mrg     }
    121      1.1  mrg 
    122      1.1  mrg   base = array->base_addr;
    123      1.1  mrg   dest = retarray->base_addr;
    124      1.1  mrg 
    125      1.1  mrg   continue_loop = 1;
    126      1.1  mrg   while (continue_loop)
    127      1.1  mrg     {
    128      1.1  mrg       const atype_name * restrict src;
    129      1.1  mrg       rtype_name result;
    130      1.1  mrg       src = base;
    131      1.1  mrg       {
    132      1.1  mrg ')dnl
    133      1.1  mrg define(START_ARRAY_BLOCK,
    134      1.1  mrg `	if (len <= 0)
    135      1.1  mrg 	  *dest = '$1`;
    136      1.1  mrg 	else
    137      1.1  mrg 	  {
    138      1.1  mrg #if ! defined HAVE_BACK_ARG
    139      1.1  mrg 	    for (n = 0; n < len; n++, src += delta)
    140      1.1  mrg 	      {
    141      1.1  mrg #endif
    142      1.1  mrg ')dnl
    143      1.1  mrg define(FINISH_ARRAY_FUNCTION,
    144      1.1  mrg `	      }
    145      1.1  mrg 	    '$1`
    146      1.1  mrg 	    *dest = result;
    147      1.1  mrg 	  }
    148      1.1  mrg       }
    149      1.1  mrg       /* Advance to the next element.  */
    150      1.1  mrg       count[0]++;
    151      1.1  mrg       base += sstride[0];
    152      1.1  mrg       dest += dstride[0];
    153      1.1  mrg       n = 0;
    154      1.1  mrg       while (count[n] == extent[n])
    155      1.1  mrg 	{
    156      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    157      1.1  mrg 	     the next dimension.  */
    158      1.1  mrg 	  count[n] = 0;
    159      1.1  mrg 	  /* We could precalculate these products, but this is a less
    160      1.1  mrg 	     frequently used path so probably not worth it.  */
    161      1.1  mrg 	  base -= sstride[n] * extent[n];
    162      1.1  mrg 	  dest -= dstride[n] * extent[n];
    163      1.1  mrg 	  n++;
    164      1.1  mrg 	  if (n >= rank)
    165      1.1  mrg 	    {
    166      1.1  mrg 	      /* Break out of the loop.  */
    167      1.1  mrg 	      continue_loop = 0;
    168      1.1  mrg 	      break;
    169      1.1  mrg 	    }
    170      1.1  mrg 	  else
    171      1.1  mrg 	    {
    172      1.1  mrg 	      count[n]++;
    173      1.1  mrg 	      base += sstride[n];
    174      1.1  mrg 	      dest += dstride[n];
    175      1.1  mrg 	    }
    176      1.1  mrg 	}
    177      1.1  mrg     }
    178      1.1  mrg }')dnl
    179      1.1  mrg define(START_MASKED_ARRAY_FUNCTION,
    180      1.1  mrg `
    181      1.1  mrg extern void `m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict, 
    182      1.1  mrg 	'atype` * const restrict, const 'index_type` * const restrict,
    183      1.1  mrg 	gfc_array_l1 * const restrict'back_arg`);
    184      1.1  mrg export_proto(m'name`'rtype_qual`_'atype_code`);
    185      1.1  mrg 
    186      1.1  mrg void
    187      1.1  mrg m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
    188      1.1  mrg 	'atype` * const restrict array, 
    189      1.1  mrg 	const index_type * const restrict pdim, 
    190      1.1  mrg 	gfc_array_l1 * const restrict mask'back_arg`)
    191      1.1  mrg {
    192      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    193      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    194      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
    195      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    196      1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
    197      1.1  mrg   'rtype_name * restrict dest;
    198      1.1  mrg   const atype_name * restrict base;
    199      1.1  mrg   const GFC_LOGICAL_1 * restrict mbase;
    200      1.1  mrg   index_type rank;
    201      1.1  mrg   index_type dim;
    202      1.1  mrg   index_type n;
    203      1.1  mrg   index_type len;
    204      1.1  mrg   index_type delta;
    205      1.1  mrg   index_type mdelta;
    206      1.1  mrg   int mask_kind;
    207      1.1  mrg 
    208      1.1  mrg   if (mask == NULL)
    209      1.1  mrg     {
    210      1.1  mrg #ifdef HAVE_BACK_ARG
    211      1.1  mrg       name`'rtype_qual`_'atype_code (retarray, array, pdim, back);
    212      1.1  mrg #else
    213      1.1  mrg       name`'rtype_qual`_'atype_code (retarray, array, pdim);
    214      1.1  mrg #endif
    215      1.1  mrg       return;
    216      1.1  mrg     }
    217      1.1  mrg 
    218      1.1  mrg   dim = (*pdim) - 1;
    219      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    220      1.1  mrg 
    221      1.1  mrg 
    222      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    223      1.1  mrg     {
    224      1.1  mrg       runtime_error ("Dim argument incorrect in u_name intrinsic: "
    225      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    226      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    227      1.1  mrg     }
    228      1.1  mrg 
    229      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
    230  1.1.1.2  mrg   if (len < 0)
    231  1.1.1.2  mrg     len = 0;
    232      1.1  mrg 
    233      1.1  mrg   mbase = mask->base_addr;
    234      1.1  mrg 
    235      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    236      1.1  mrg 
    237      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    238      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    239      1.1  mrg       || mask_kind == 16
    240      1.1  mrg #endif
    241      1.1  mrg       )
    242      1.1  mrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    243      1.1  mrg   else
    244      1.1  mrg     runtime_error ("Funny sized logical array");
    245      1.1  mrg 
    246      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
    247      1.1  mrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
    248      1.1  mrg 
    249      1.1  mrg   for (n = 0; n < dim; n++)
    250      1.1  mrg     {
    251      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
    252      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    253      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    254      1.1  mrg 
    255      1.1  mrg       if (extent[n] < 0)
    256      1.1  mrg 	extent[n] = 0;
    257      1.1  mrg 
    258      1.1  mrg     }
    259      1.1  mrg   for (n = dim; n < rank; n++)
    260      1.1  mrg     {
    261      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
    262      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
    263      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
    264      1.1  mrg 
    265      1.1  mrg       if (extent[n] < 0)
    266      1.1  mrg 	extent[n] = 0;
    267      1.1  mrg     }
    268      1.1  mrg 
    269      1.1  mrg   if (retarray->base_addr == NULL)
    270      1.1  mrg     {
    271      1.1  mrg       size_t alloc_size, str;
    272      1.1  mrg 
    273      1.1  mrg       for (n = 0; n < rank; n++)
    274      1.1  mrg 	{
    275      1.1  mrg 	  if (n == 0)
    276      1.1  mrg 	    str = 1;
    277      1.1  mrg 	  else
    278      1.1  mrg 	    str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    279      1.1  mrg 
    280      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    281      1.1  mrg 
    282      1.1  mrg 	}
    283      1.1  mrg 
    284      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    285      1.1  mrg 
    286      1.1  mrg       retarray->offset = 0;
    287      1.1  mrg       retarray->dtype.rank = rank;
    288      1.1  mrg 
    289  1.1.1.2  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
    290      1.1  mrg       if (alloc_size == 0)
    291  1.1.1.2  mrg 	return;
    292      1.1  mrg     }
    293      1.1  mrg   else
    294      1.1  mrg     {
    295      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    296      1.1  mrg 	runtime_error ("rank of return array incorrect in u_name intrinsic");
    297      1.1  mrg 
    298      1.1  mrg       if (unlikely (compile_options.bounds_check))
    299      1.1  mrg 	{
    300      1.1  mrg 	  bounds_ifunction_return ((array_t *) retarray, extent,
    301      1.1  mrg 				   "return value", "u_name");
    302      1.1  mrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
    303      1.1  mrg 	  			"MASK argument", "u_name");
    304      1.1  mrg 	}
    305      1.1  mrg     }
    306      1.1  mrg 
    307      1.1  mrg   for (n = 0; n < rank; n++)
    308      1.1  mrg     {
    309      1.1  mrg       count[n] = 0;
    310      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    311      1.1  mrg       if (extent[n] <= 0)
    312      1.1  mrg 	return;
    313      1.1  mrg     }
    314      1.1  mrg 
    315      1.1  mrg   dest = retarray->base_addr;
    316      1.1  mrg   base = array->base_addr;
    317      1.1  mrg 
    318      1.1  mrg   while (base)
    319      1.1  mrg     {
    320      1.1  mrg       const atype_name * restrict src;
    321      1.1  mrg       const GFC_LOGICAL_1 * restrict msrc;
    322      1.1  mrg       rtype_name result;
    323      1.1  mrg       src = base;
    324      1.1  mrg       msrc = mbase;
    325      1.1  mrg       {
    326      1.1  mrg ')dnl
    327      1.1  mrg define(START_MASKED_ARRAY_BLOCK,
    328      1.1  mrg `	for (n = 0; n < len; n++, src += delta, msrc += mdelta)
    329      1.1  mrg 	  {
    330      1.1  mrg ')dnl
    331      1.1  mrg define(FINISH_MASKED_ARRAY_FUNCTION,
    332      1.1  mrg `	  }
    333      1.1  mrg 	*dest = result;
    334      1.1  mrg       }
    335      1.1  mrg       /* Advance to the next element.  */
    336      1.1  mrg       count[0]++;
    337      1.1  mrg       base += sstride[0];
    338      1.1  mrg       mbase += mstride[0];
    339      1.1  mrg       dest += dstride[0];
    340      1.1  mrg       n = 0;
    341      1.1  mrg       while (count[n] == extent[n])
    342      1.1  mrg 	{
    343      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    344      1.1  mrg 	     the next dimension.  */
    345      1.1  mrg 	  count[n] = 0;
    346      1.1  mrg 	  /* We could precalculate these products, but this is a less
    347      1.1  mrg 	     frequently used path so probably not worth it.  */
    348      1.1  mrg 	  base -= sstride[n] * extent[n];
    349      1.1  mrg 	  mbase -= mstride[n] * extent[n];
    350      1.1  mrg 	  dest -= dstride[n] * extent[n];
    351      1.1  mrg 	  n++;
    352      1.1  mrg 	  if (n >= rank)
    353      1.1  mrg 	    {
    354      1.1  mrg 	      /* Break out of the loop.  */
    355      1.1  mrg 	      base = NULL;
    356      1.1  mrg 	      break;
    357      1.1  mrg 	    }
    358      1.1  mrg 	  else
    359      1.1  mrg 	    {
    360      1.1  mrg 	      count[n]++;
    361      1.1  mrg 	      base += sstride[n];
    362      1.1  mrg 	      mbase += mstride[n];
    363      1.1  mrg 	      dest += dstride[n];
    364      1.1  mrg 	    }
    365      1.1  mrg 	}
    366      1.1  mrg     }
    367      1.1  mrg }')dnl
    368      1.1  mrg define(SCALAR_ARRAY_FUNCTION,
    369      1.1  mrg `
    370      1.1  mrg extern void `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict, 
    371      1.1  mrg 	'atype` * const restrict, const index_type * const restrict,
    372      1.1  mrg 	GFC_LOGICAL_4 *'back_arg`);
    373      1.1  mrg export_proto(s'name`'rtype_qual`_'atype_code);
    374      1.1  mrg 
    375      1.1  mrg void
    376      1.1  mrg `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
    377      1.1  mrg 	'atype` * const restrict array, 
    378      1.1  mrg 	const index_type * const restrict pdim, 
    379      1.1  mrg 	GFC_LOGICAL_4 * mask'back_arg`)
    380      1.1  mrg {
    381      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    382      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    383      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    384      1.1  mrg   'rtype_name * restrict dest;
    385      1.1  mrg   index_type rank;
    386      1.1  mrg   index_type n;
    387      1.1  mrg   index_type dim;
    388      1.1  mrg 
    389      1.1  mrg 
    390      1.1  mrg   if (mask == NULL || *mask)
    391      1.1  mrg     {
    392      1.1  mrg #ifdef HAVE_BACK_ARG
    393      1.1  mrg       name`'rtype_qual`_'atype_code (retarray, array, pdim, back);
    394      1.1  mrg #else
    395      1.1  mrg       name`'rtype_qual`_'atype_code (retarray, array, pdim);
    396      1.1  mrg #endif
    397      1.1  mrg       return;
    398      1.1  mrg     }
    399      1.1  mrg   /* Make dim zero based to avoid confusion.  */
    400      1.1  mrg   dim = (*pdim) - 1;
    401      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    402      1.1  mrg 
    403      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    404      1.1  mrg     {
    405      1.1  mrg       runtime_error ("Dim argument incorrect in u_name intrinsic: "
    406      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    407      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    408      1.1  mrg     }
    409      1.1  mrg 
    410      1.1  mrg   for (n = 0; n < dim; n++)
    411      1.1  mrg     {
    412      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    413      1.1  mrg 
    414      1.1  mrg       if (extent[n] <= 0)
    415      1.1  mrg 	extent[n] = 0;
    416      1.1  mrg     }
    417      1.1  mrg 
    418      1.1  mrg   for (n = dim; n < rank; n++)
    419      1.1  mrg     {
    420      1.1  mrg       extent[n] =
    421      1.1  mrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
    422      1.1  mrg 
    423      1.1  mrg       if (extent[n] <= 0)
    424      1.1  mrg 	extent[n] = 0;
    425      1.1  mrg     }
    426      1.1  mrg 
    427      1.1  mrg   if (retarray->base_addr == NULL)
    428      1.1  mrg     {
    429      1.1  mrg       size_t alloc_size, str;
    430      1.1  mrg 
    431      1.1  mrg       for (n = 0; n < rank; n++)
    432      1.1  mrg 	{
    433      1.1  mrg 	  if (n == 0)
    434      1.1  mrg 	    str = 1;
    435      1.1  mrg 	  else
    436      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    437      1.1  mrg 
    438      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    439      1.1  mrg 
    440      1.1  mrg 	}
    441      1.1  mrg 
    442      1.1  mrg       retarray->offset = 0;
    443      1.1  mrg       retarray->dtype.rank = rank;
    444      1.1  mrg 
    445      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    446      1.1  mrg 
    447  1.1.1.2  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
    448      1.1  mrg       if (alloc_size == 0)
    449  1.1.1.2  mrg 	return;
    450      1.1  mrg     }
    451      1.1  mrg   else
    452      1.1  mrg     {
    453      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    454      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    455      1.1  mrg 		       " u_name intrinsic: is %ld, should be %ld",
    456      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    457      1.1  mrg 		       (long int) rank);
    458      1.1  mrg 
    459      1.1  mrg       if (unlikely (compile_options.bounds_check))
    460      1.1  mrg 	{
    461      1.1  mrg 	  for (n=0; n < rank; n++)
    462      1.1  mrg 	    {
    463      1.1  mrg 	      index_type ret_extent;
    464      1.1  mrg 
    465      1.1  mrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
    466      1.1  mrg 	      if (extent[n] != ret_extent)
    467      1.1  mrg 		runtime_error ("Incorrect extent in return value of"
    468      1.1  mrg 			       " u_name intrinsic in dimension %ld:"
    469      1.1  mrg 			       " is %ld, should be %ld", (long int) n + 1,
    470      1.1  mrg 			       (long int) ret_extent, (long int) extent[n]);
    471      1.1  mrg 	    }
    472      1.1  mrg 	}
    473      1.1  mrg     }
    474      1.1  mrg 
    475      1.1  mrg   for (n = 0; n < rank; n++)
    476      1.1  mrg     {
    477      1.1  mrg       count[n] = 0;
    478      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    479      1.1  mrg     }
    480      1.1  mrg 
    481      1.1  mrg   dest = retarray->base_addr;
    482      1.1  mrg 
    483      1.1  mrg   while(1)
    484      1.1  mrg     {
    485      1.1  mrg       *dest = '$1`;
    486      1.1  mrg       count[0]++;
    487      1.1  mrg       dest += dstride[0];
    488      1.1  mrg       n = 0;
    489      1.1  mrg       while (count[n] == extent[n])
    490      1.1  mrg 	{
    491      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    492      1.1  mrg 	     the next dimension.  */
    493      1.1  mrg 	  count[n] = 0;
    494      1.1  mrg 	  /* We could precalculate these products, but this is a less
    495      1.1  mrg 	     frequently used path so probably not worth it.  */
    496      1.1  mrg 	  dest -= dstride[n] * extent[n];
    497      1.1  mrg 	  n++;
    498      1.1  mrg 	  if (n >= rank)
    499      1.1  mrg 	    return;
    500      1.1  mrg 	  else
    501      1.1  mrg 	    {
    502      1.1  mrg 	      count[n]++;
    503      1.1  mrg 	      dest += dstride[n];
    504      1.1  mrg 	    }
    505      1.1  mrg       	}
    506      1.1  mrg     }
    507      1.1  mrg }')dnl
    508      1.1  mrg define(ARRAY_FUNCTION,
    509      1.1  mrg `START_ARRAY_FUNCTION
    510      1.1  mrg $2
    511      1.1  mrg START_ARRAY_BLOCK($1)
    512      1.1  mrg $3
    513      1.1  mrg FINISH_ARRAY_FUNCTION($4)')dnl
    514      1.1  mrg define(MASKED_ARRAY_FUNCTION,
    515      1.1  mrg `START_MASKED_ARRAY_FUNCTION
    516      1.1  mrg $2
    517      1.1  mrg START_MASKED_ARRAY_BLOCK
    518      1.1  mrg $3
    519      1.1  mrg FINISH_MASKED_ARRAY_FUNCTION')dnl
    520