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