Home | History | Annotate | Line # | Download | only in generated
      1      1.1  mrg /* Implementation of the IPARITY intrinsic
      2  1.1.1.3  mrg    Copyright (C) 2010-2022 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Tobias Burnus <burnus (at) net-b.de>
      4      1.1  mrg 
      5      1.1  mrg This file is part of the GNU Fortran runtime library (libgfortran).
      6      1.1  mrg 
      7      1.1  mrg Libgfortran is free software; you can redistribute it and/or
      8      1.1  mrg modify it under the terms of the GNU General Public
      9      1.1  mrg License as published by the Free Software Foundation; either
     10      1.1  mrg version 3 of the License, or (at your option) any later version.
     11      1.1  mrg 
     12      1.1  mrg Libgfortran is distributed in the hope that it will be useful,
     13      1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1  mrg GNU General Public License for more details.
     16      1.1  mrg 
     17      1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     18      1.1  mrg permissions described in the GCC Runtime Library Exception, version
     19      1.1  mrg 3.1, as published by the Free Software Foundation.
     20      1.1  mrg 
     21      1.1  mrg You should have received a copy of the GNU General Public License and
     22      1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     23      1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24      1.1  mrg <http://www.gnu.org/licenses/>.  */
     25      1.1  mrg 
     26      1.1  mrg #include "libgfortran.h"
     27      1.1  mrg 
     28      1.1  mrg 
     29      1.1  mrg #if defined (HAVE_GFC_INTEGER_2) && defined (HAVE_GFC_INTEGER_2)
     30      1.1  mrg 
     31      1.1  mrg 
     32      1.1  mrg extern void iparity_i2 (gfc_array_i2 * const restrict,
     33      1.1  mrg 	gfc_array_i2 * const restrict, const index_type * const restrict);
     34      1.1  mrg export_proto(iparity_i2);
     35      1.1  mrg 
     36      1.1  mrg void
     37      1.1  mrg iparity_i2 (gfc_array_i2 * const restrict retarray,
     38      1.1  mrg 	gfc_array_i2 * const restrict array,
     39      1.1  mrg 	const index_type * const restrict pdim)
     40      1.1  mrg {
     41      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     42      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     43      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     44      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
     45      1.1  mrg   const GFC_INTEGER_2 * restrict base;
     46      1.1  mrg   GFC_INTEGER_2 * restrict dest;
     47      1.1  mrg   index_type rank;
     48      1.1  mrg   index_type n;
     49      1.1  mrg   index_type len;
     50      1.1  mrg   index_type delta;
     51      1.1  mrg   index_type dim;
     52      1.1  mrg   int continue_loop;
     53      1.1  mrg 
     54      1.1  mrg   /* Make dim zero based to avoid confusion.  */
     55      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
     56      1.1  mrg   dim = (*pdim) - 1;
     57      1.1  mrg 
     58      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
     59      1.1  mrg     {
     60      1.1  mrg       runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
     61      1.1  mrg  		     "is %ld, should be between 1 and %ld",
     62      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
     63      1.1  mrg     }
     64      1.1  mrg 
     65      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
     66      1.1  mrg   if (len < 0)
     67      1.1  mrg     len = 0;
     68      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
     69      1.1  mrg 
     70      1.1  mrg   for (n = 0; n < dim; n++)
     71      1.1  mrg     {
     72      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
     73      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
     74      1.1  mrg 
     75      1.1  mrg       if (extent[n] < 0)
     76      1.1  mrg 	extent[n] = 0;
     77      1.1  mrg     }
     78      1.1  mrg   for (n = dim; n < rank; n++)
     79      1.1  mrg     {
     80      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
     81      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
     82      1.1  mrg 
     83      1.1  mrg       if (extent[n] < 0)
     84      1.1  mrg 	extent[n] = 0;
     85      1.1  mrg     }
     86      1.1  mrg 
     87      1.1  mrg   if (retarray->base_addr == NULL)
     88      1.1  mrg     {
     89      1.1  mrg       size_t alloc_size, str;
     90      1.1  mrg 
     91      1.1  mrg       for (n = 0; n < rank; n++)
     92      1.1  mrg 	{
     93      1.1  mrg 	  if (n == 0)
     94      1.1  mrg 	    str = 1;
     95      1.1  mrg 	  else
     96      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
     97      1.1  mrg 
     98      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
     99      1.1  mrg 
    100      1.1  mrg 	}
    101      1.1  mrg 
    102      1.1  mrg       retarray->offset = 0;
    103      1.1  mrg       retarray->dtype.rank = rank;
    104      1.1  mrg 
    105      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    106      1.1  mrg 
    107      1.1  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_2));
    108      1.1  mrg       if (alloc_size == 0)
    109      1.1  mrg 	{
    110      1.1  mrg 	  /* Make sure we have a zero-sized array.  */
    111      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
    112      1.1  mrg 	  return;
    113      1.1  mrg 
    114      1.1  mrg 	}
    115      1.1  mrg     }
    116      1.1  mrg   else
    117      1.1  mrg     {
    118      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    119      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    120      1.1  mrg 		       " IPARITY intrinsic: is %ld, should be %ld",
    121      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    122      1.1  mrg 		       (long int) rank);
    123      1.1  mrg 
    124      1.1  mrg       if (unlikely (compile_options.bounds_check))
    125      1.1  mrg 	bounds_ifunction_return ((array_t *) retarray, extent,
    126      1.1  mrg 				 "return value", "IPARITY");
    127      1.1  mrg     }
    128      1.1  mrg 
    129      1.1  mrg   for (n = 0; n < rank; n++)
    130      1.1  mrg     {
    131      1.1  mrg       count[n] = 0;
    132      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    133      1.1  mrg       if (extent[n] <= 0)
    134      1.1  mrg 	return;
    135      1.1  mrg     }
    136      1.1  mrg 
    137      1.1  mrg   base = array->base_addr;
    138      1.1  mrg   dest = retarray->base_addr;
    139      1.1  mrg 
    140      1.1  mrg   continue_loop = 1;
    141      1.1  mrg   while (continue_loop)
    142      1.1  mrg     {
    143      1.1  mrg       const GFC_INTEGER_2 * restrict src;
    144      1.1  mrg       GFC_INTEGER_2 result;
    145      1.1  mrg       src = base;
    146      1.1  mrg       {
    147      1.1  mrg 
    148      1.1  mrg   result = 0;
    149      1.1  mrg 	if (len <= 0)
    150      1.1  mrg 	  *dest = 0;
    151      1.1  mrg 	else
    152      1.1  mrg 	  {
    153      1.1  mrg #if ! defined HAVE_BACK_ARG
    154      1.1  mrg 	    for (n = 0; n < len; n++, src += delta)
    155      1.1  mrg 	      {
    156      1.1  mrg #endif
    157      1.1  mrg 
    158      1.1  mrg   result ^= *src;
    159      1.1  mrg 	      }
    160      1.1  mrg 
    161      1.1  mrg 	    *dest = result;
    162      1.1  mrg 	  }
    163      1.1  mrg       }
    164      1.1  mrg       /* Advance to the next element.  */
    165      1.1  mrg       count[0]++;
    166      1.1  mrg       base += sstride[0];
    167      1.1  mrg       dest += dstride[0];
    168      1.1  mrg       n = 0;
    169      1.1  mrg       while (count[n] == extent[n])
    170      1.1  mrg 	{
    171      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    172      1.1  mrg 	     the next dimension.  */
    173      1.1  mrg 	  count[n] = 0;
    174      1.1  mrg 	  /* We could precalculate these products, but this is a less
    175      1.1  mrg 	     frequently used path so probably not worth it.  */
    176      1.1  mrg 	  base -= sstride[n] * extent[n];
    177      1.1  mrg 	  dest -= dstride[n] * extent[n];
    178      1.1  mrg 	  n++;
    179      1.1  mrg 	  if (n >= rank)
    180      1.1  mrg 	    {
    181      1.1  mrg 	      /* Break out of the loop.  */
    182      1.1  mrg 	      continue_loop = 0;
    183      1.1  mrg 	      break;
    184      1.1  mrg 	    }
    185      1.1  mrg 	  else
    186      1.1  mrg 	    {
    187      1.1  mrg 	      count[n]++;
    188      1.1  mrg 	      base += sstride[n];
    189      1.1  mrg 	      dest += dstride[n];
    190      1.1  mrg 	    }
    191      1.1  mrg 	}
    192      1.1  mrg     }
    193      1.1  mrg }
    194      1.1  mrg 
    195      1.1  mrg 
    196      1.1  mrg extern void miparity_i2 (gfc_array_i2 * const restrict,
    197      1.1  mrg 	gfc_array_i2 * const restrict, const index_type * const restrict,
    198      1.1  mrg 	gfc_array_l1 * const restrict);
    199      1.1  mrg export_proto(miparity_i2);
    200      1.1  mrg 
    201      1.1  mrg void
    202      1.1  mrg miparity_i2 (gfc_array_i2 * const restrict retarray,
    203      1.1  mrg 	gfc_array_i2 * const restrict array,
    204      1.1  mrg 	const index_type * const restrict pdim,
    205      1.1  mrg 	gfc_array_l1 * const restrict mask)
    206      1.1  mrg {
    207      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    208      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    209      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
    210      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    211      1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
    212      1.1  mrg   GFC_INTEGER_2 * restrict dest;
    213      1.1  mrg   const GFC_INTEGER_2 * restrict base;
    214      1.1  mrg   const GFC_LOGICAL_1 * restrict mbase;
    215      1.1  mrg   index_type rank;
    216      1.1  mrg   index_type dim;
    217      1.1  mrg   index_type n;
    218      1.1  mrg   index_type len;
    219      1.1  mrg   index_type delta;
    220      1.1  mrg   index_type mdelta;
    221      1.1  mrg   int mask_kind;
    222      1.1  mrg 
    223      1.1  mrg   if (mask == NULL)
    224      1.1  mrg     {
    225      1.1  mrg #ifdef HAVE_BACK_ARG
    226      1.1  mrg       iparity_i2 (retarray, array, pdim, back);
    227      1.1  mrg #else
    228      1.1  mrg       iparity_i2 (retarray, array, pdim);
    229      1.1  mrg #endif
    230      1.1  mrg       return;
    231      1.1  mrg     }
    232      1.1  mrg 
    233      1.1  mrg   dim = (*pdim) - 1;
    234      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    235      1.1  mrg 
    236      1.1  mrg 
    237      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    238      1.1  mrg     {
    239      1.1  mrg       runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
    240      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    241      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    242      1.1  mrg     }
    243      1.1  mrg 
    244      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
    245      1.1  mrg   if (len <= 0)
    246      1.1  mrg     return;
    247      1.1  mrg 
    248      1.1  mrg   mbase = mask->base_addr;
    249      1.1  mrg 
    250      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    251      1.1  mrg 
    252      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    253      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    254      1.1  mrg       || mask_kind == 16
    255      1.1  mrg #endif
    256      1.1  mrg       )
    257      1.1  mrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    258      1.1  mrg   else
    259      1.1  mrg     runtime_error ("Funny sized logical array");
    260      1.1  mrg 
    261      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
    262      1.1  mrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
    263      1.1  mrg 
    264      1.1  mrg   for (n = 0; n < dim; n++)
    265      1.1  mrg     {
    266      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
    267      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    268      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    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   for (n = dim; n < rank; n++)
    275      1.1  mrg     {
    276      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
    277      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
    278      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
    279      1.1  mrg 
    280      1.1  mrg       if (extent[n] < 0)
    281      1.1  mrg 	extent[n] = 0;
    282      1.1  mrg     }
    283      1.1  mrg 
    284      1.1  mrg   if (retarray->base_addr == NULL)
    285      1.1  mrg     {
    286      1.1  mrg       size_t alloc_size, str;
    287      1.1  mrg 
    288      1.1  mrg       for (n = 0; n < rank; n++)
    289      1.1  mrg 	{
    290      1.1  mrg 	  if (n == 0)
    291      1.1  mrg 	    str = 1;
    292      1.1  mrg 	  else
    293      1.1  mrg 	    str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    294      1.1  mrg 
    295      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    296      1.1  mrg 
    297      1.1  mrg 	}
    298      1.1  mrg 
    299      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    300      1.1  mrg 
    301      1.1  mrg       retarray->offset = 0;
    302      1.1  mrg       retarray->dtype.rank = rank;
    303      1.1  mrg 
    304      1.1  mrg       if (alloc_size == 0)
    305      1.1  mrg 	{
    306      1.1  mrg 	  /* Make sure we have a zero-sized array.  */
    307      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
    308      1.1  mrg 	  return;
    309      1.1  mrg 	}
    310      1.1  mrg       else
    311      1.1  mrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_2));
    312      1.1  mrg 
    313      1.1  mrg     }
    314      1.1  mrg   else
    315      1.1  mrg     {
    316      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    317      1.1  mrg 	runtime_error ("rank of return array incorrect in IPARITY intrinsic");
    318      1.1  mrg 
    319      1.1  mrg       if (unlikely (compile_options.bounds_check))
    320      1.1  mrg 	{
    321      1.1  mrg 	  bounds_ifunction_return ((array_t *) retarray, extent,
    322      1.1  mrg 				   "return value", "IPARITY");
    323      1.1  mrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
    324      1.1  mrg 	  			"MASK argument", "IPARITY");
    325      1.1  mrg 	}
    326      1.1  mrg     }
    327      1.1  mrg 
    328      1.1  mrg   for (n = 0; n < rank; n++)
    329      1.1  mrg     {
    330      1.1  mrg       count[n] = 0;
    331      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    332      1.1  mrg       if (extent[n] <= 0)
    333      1.1  mrg 	return;
    334      1.1  mrg     }
    335      1.1  mrg 
    336      1.1  mrg   dest = retarray->base_addr;
    337      1.1  mrg   base = array->base_addr;
    338      1.1  mrg 
    339      1.1  mrg   while (base)
    340      1.1  mrg     {
    341      1.1  mrg       const GFC_INTEGER_2 * restrict src;
    342      1.1  mrg       const GFC_LOGICAL_1 * restrict msrc;
    343      1.1  mrg       GFC_INTEGER_2 result;
    344      1.1  mrg       src = base;
    345      1.1  mrg       msrc = mbase;
    346      1.1  mrg       {
    347      1.1  mrg 
    348      1.1  mrg   result = 0;
    349      1.1  mrg 	for (n = 0; n < len; n++, src += delta, msrc += mdelta)
    350      1.1  mrg 	  {
    351      1.1  mrg 
    352      1.1  mrg   if (*msrc)
    353      1.1  mrg     result ^= *src;
    354      1.1  mrg 	  }
    355      1.1  mrg 	*dest = result;
    356      1.1  mrg       }
    357      1.1  mrg       /* Advance to the next element.  */
    358      1.1  mrg       count[0]++;
    359      1.1  mrg       base += sstride[0];
    360      1.1  mrg       mbase += mstride[0];
    361      1.1  mrg       dest += dstride[0];
    362      1.1  mrg       n = 0;
    363      1.1  mrg       while (count[n] == extent[n])
    364      1.1  mrg 	{
    365      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    366      1.1  mrg 	     the next dimension.  */
    367      1.1  mrg 	  count[n] = 0;
    368      1.1  mrg 	  /* We could precalculate these products, but this is a less
    369      1.1  mrg 	     frequently used path so probably not worth it.  */
    370      1.1  mrg 	  base -= sstride[n] * extent[n];
    371      1.1  mrg 	  mbase -= mstride[n] * extent[n];
    372      1.1  mrg 	  dest -= dstride[n] * extent[n];
    373      1.1  mrg 	  n++;
    374      1.1  mrg 	  if (n >= rank)
    375      1.1  mrg 	    {
    376      1.1  mrg 	      /* Break out of the loop.  */
    377      1.1  mrg 	      base = NULL;
    378      1.1  mrg 	      break;
    379      1.1  mrg 	    }
    380      1.1  mrg 	  else
    381      1.1  mrg 	    {
    382      1.1  mrg 	      count[n]++;
    383      1.1  mrg 	      base += sstride[n];
    384      1.1  mrg 	      mbase += mstride[n];
    385      1.1  mrg 	      dest += dstride[n];
    386      1.1  mrg 	    }
    387      1.1  mrg 	}
    388      1.1  mrg     }
    389      1.1  mrg }
    390      1.1  mrg 
    391      1.1  mrg 
    392      1.1  mrg extern void siparity_i2 (gfc_array_i2 * const restrict,
    393      1.1  mrg 	gfc_array_i2 * const restrict, const index_type * const restrict,
    394      1.1  mrg 	GFC_LOGICAL_4 *);
    395      1.1  mrg export_proto(siparity_i2);
    396      1.1  mrg 
    397      1.1  mrg void
    398      1.1  mrg siparity_i2 (gfc_array_i2 * const restrict retarray,
    399      1.1  mrg 	gfc_array_i2 * const restrict array,
    400      1.1  mrg 	const index_type * const restrict pdim,
    401      1.1  mrg 	GFC_LOGICAL_4 * mask)
    402      1.1  mrg {
    403      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    404      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    405      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    406      1.1  mrg   GFC_INTEGER_2 * restrict dest;
    407      1.1  mrg   index_type rank;
    408      1.1  mrg   index_type n;
    409      1.1  mrg   index_type dim;
    410      1.1  mrg 
    411      1.1  mrg 
    412      1.1  mrg   if (mask == NULL || *mask)
    413      1.1  mrg     {
    414      1.1  mrg #ifdef HAVE_BACK_ARG
    415      1.1  mrg       iparity_i2 (retarray, array, pdim, back);
    416      1.1  mrg #else
    417      1.1  mrg       iparity_i2 (retarray, array, pdim);
    418      1.1  mrg #endif
    419      1.1  mrg       return;
    420      1.1  mrg     }
    421      1.1  mrg   /* Make dim zero based to avoid confusion.  */
    422      1.1  mrg   dim = (*pdim) - 1;
    423      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    424      1.1  mrg 
    425      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    426      1.1  mrg     {
    427      1.1  mrg       runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
    428      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    429      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    430      1.1  mrg     }
    431      1.1  mrg 
    432      1.1  mrg   for (n = 0; n < dim; n++)
    433      1.1  mrg     {
    434      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    435      1.1  mrg 
    436      1.1  mrg       if (extent[n] <= 0)
    437      1.1  mrg 	extent[n] = 0;
    438      1.1  mrg     }
    439      1.1  mrg 
    440      1.1  mrg   for (n = dim; n < rank; n++)
    441      1.1  mrg     {
    442      1.1  mrg       extent[n] =
    443      1.1  mrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
    444      1.1  mrg 
    445      1.1  mrg       if (extent[n] <= 0)
    446      1.1  mrg 	extent[n] = 0;
    447      1.1  mrg     }
    448      1.1  mrg 
    449      1.1  mrg   if (retarray->base_addr == NULL)
    450      1.1  mrg     {
    451      1.1  mrg       size_t alloc_size, str;
    452      1.1  mrg 
    453      1.1  mrg       for (n = 0; n < rank; n++)
    454      1.1  mrg 	{
    455      1.1  mrg 	  if (n == 0)
    456      1.1  mrg 	    str = 1;
    457      1.1  mrg 	  else
    458      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    459      1.1  mrg 
    460      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    461      1.1  mrg 
    462      1.1  mrg 	}
    463      1.1  mrg 
    464      1.1  mrg       retarray->offset = 0;
    465      1.1  mrg       retarray->dtype.rank = rank;
    466      1.1  mrg 
    467      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    468      1.1  mrg 
    469      1.1  mrg       if (alloc_size == 0)
    470      1.1  mrg 	{
    471      1.1  mrg 	  /* Make sure we have a zero-sized array.  */
    472      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
    473      1.1  mrg 	  return;
    474      1.1  mrg 	}
    475      1.1  mrg       else
    476      1.1  mrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_2));
    477      1.1  mrg     }
    478      1.1  mrg   else
    479      1.1  mrg     {
    480      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    481      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    482      1.1  mrg 		       " IPARITY intrinsic: is %ld, should be %ld",
    483      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    484      1.1  mrg 		       (long int) rank);
    485      1.1  mrg 
    486      1.1  mrg       if (unlikely (compile_options.bounds_check))
    487      1.1  mrg 	{
    488      1.1  mrg 	  for (n=0; n < rank; n++)
    489      1.1  mrg 	    {
    490      1.1  mrg 	      index_type ret_extent;
    491      1.1  mrg 
    492      1.1  mrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
    493      1.1  mrg 	      if (extent[n] != ret_extent)
    494      1.1  mrg 		runtime_error ("Incorrect extent in return value of"
    495      1.1  mrg 			       " IPARITY intrinsic in dimension %ld:"
    496      1.1  mrg 			       " is %ld, should be %ld", (long int) n + 1,
    497      1.1  mrg 			       (long int) ret_extent, (long int) extent[n]);
    498      1.1  mrg 	    }
    499      1.1  mrg 	}
    500      1.1  mrg     }
    501      1.1  mrg 
    502      1.1  mrg   for (n = 0; n < rank; n++)
    503      1.1  mrg     {
    504      1.1  mrg       count[n] = 0;
    505      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    506      1.1  mrg     }
    507      1.1  mrg 
    508      1.1  mrg   dest = retarray->base_addr;
    509      1.1  mrg 
    510      1.1  mrg   while(1)
    511      1.1  mrg     {
    512      1.1  mrg       *dest = 0;
    513      1.1  mrg       count[0]++;
    514      1.1  mrg       dest += dstride[0];
    515      1.1  mrg       n = 0;
    516      1.1  mrg       while (count[n] == extent[n])
    517      1.1  mrg 	{
    518      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    519      1.1  mrg 	     the next dimension.  */
    520      1.1  mrg 	  count[n] = 0;
    521      1.1  mrg 	  /* We could precalculate these products, but this is a less
    522      1.1  mrg 	     frequently used path so probably not worth it.  */
    523      1.1  mrg 	  dest -= dstride[n] * extent[n];
    524      1.1  mrg 	  n++;
    525      1.1  mrg 	  if (n >= rank)
    526      1.1  mrg 	    return;
    527      1.1  mrg 	  else
    528      1.1  mrg 	    {
    529      1.1  mrg 	      count[n]++;
    530      1.1  mrg 	      dest += dstride[n];
    531      1.1  mrg 	    }
    532      1.1  mrg       	}
    533      1.1  mrg     }
    534      1.1  mrg }
    535      1.1  mrg 
    536      1.1  mrg #endif
    537