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