Home | History | Annotate | Line # | Download | only in generated
      1      1.1  mrg /* Implementation of the SUM intrinsic
      2  1.1.1.4  mrg    Copyright (C) 2002-2024 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Paul Brook <paul (at) nowt.org>
      4      1.1  mrg 
      5      1.1  mrg This file is part of the GNU Fortran 95 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_COMPLEX_8) && defined (HAVE_GFC_COMPLEX_8)
     30      1.1  mrg 
     31      1.1  mrg 
     32      1.1  mrg extern void sum_c8 (gfc_array_c8 * const restrict,
     33      1.1  mrg 	gfc_array_c8 * const restrict, const index_type * const restrict);
     34      1.1  mrg export_proto(sum_c8);
     35      1.1  mrg 
     36      1.1  mrg void
     37      1.1  mrg sum_c8 (gfc_array_c8 * const restrict retarray,
     38      1.1  mrg 	gfc_array_c8 * 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_COMPLEX_8 * restrict base;
     46      1.1  mrg   GFC_COMPLEX_8 * 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 SUM 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_COMPLEX_8));
    108      1.1  mrg       if (alloc_size == 0)
    109  1.1.1.4  mrg 	return;
    110      1.1  mrg     }
    111      1.1  mrg   else
    112      1.1  mrg     {
    113      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    114      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    115      1.1  mrg 		       " SUM intrinsic: is %ld, should be %ld",
    116      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    117      1.1  mrg 		       (long int) rank);
    118      1.1  mrg 
    119      1.1  mrg       if (unlikely (compile_options.bounds_check))
    120      1.1  mrg 	bounds_ifunction_return ((array_t *) retarray, extent,
    121      1.1  mrg 				 "return value", "SUM");
    122      1.1  mrg     }
    123      1.1  mrg 
    124      1.1  mrg   for (n = 0; n < rank; n++)
    125      1.1  mrg     {
    126      1.1  mrg       count[n] = 0;
    127      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    128      1.1  mrg       if (extent[n] <= 0)
    129      1.1  mrg 	return;
    130      1.1  mrg     }
    131      1.1  mrg 
    132      1.1  mrg   base = array->base_addr;
    133      1.1  mrg   dest = retarray->base_addr;
    134      1.1  mrg 
    135      1.1  mrg   continue_loop = 1;
    136      1.1  mrg   while (continue_loop)
    137      1.1  mrg     {
    138      1.1  mrg       const GFC_COMPLEX_8 * restrict src;
    139      1.1  mrg       GFC_COMPLEX_8 result;
    140      1.1  mrg       src = base;
    141      1.1  mrg       {
    142      1.1  mrg 
    143      1.1  mrg   result = 0;
    144      1.1  mrg 	if (len <= 0)
    145      1.1  mrg 	  *dest = 0;
    146      1.1  mrg 	else
    147      1.1  mrg 	  {
    148      1.1  mrg #if ! defined HAVE_BACK_ARG
    149      1.1  mrg 	    for (n = 0; n < len; n++, src += delta)
    150      1.1  mrg 	      {
    151      1.1  mrg #endif
    152      1.1  mrg 
    153      1.1  mrg   result += *src;
    154      1.1  mrg 	      }
    155      1.1  mrg 
    156      1.1  mrg 	    *dest = result;
    157      1.1  mrg 	  }
    158      1.1  mrg       }
    159      1.1  mrg       /* Advance to the next element.  */
    160      1.1  mrg       count[0]++;
    161      1.1  mrg       base += sstride[0];
    162      1.1  mrg       dest += dstride[0];
    163      1.1  mrg       n = 0;
    164      1.1  mrg       while (count[n] == extent[n])
    165      1.1  mrg 	{
    166      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    167      1.1  mrg 	     the next dimension.  */
    168      1.1  mrg 	  count[n] = 0;
    169      1.1  mrg 	  /* We could precalculate these products, but this is a less
    170      1.1  mrg 	     frequently used path so probably not worth it.  */
    171      1.1  mrg 	  base -= sstride[n] * extent[n];
    172      1.1  mrg 	  dest -= dstride[n] * extent[n];
    173      1.1  mrg 	  n++;
    174      1.1  mrg 	  if (n >= rank)
    175      1.1  mrg 	    {
    176      1.1  mrg 	      /* Break out of the loop.  */
    177      1.1  mrg 	      continue_loop = 0;
    178      1.1  mrg 	      break;
    179      1.1  mrg 	    }
    180      1.1  mrg 	  else
    181      1.1  mrg 	    {
    182      1.1  mrg 	      count[n]++;
    183      1.1  mrg 	      base += sstride[n];
    184      1.1  mrg 	      dest += dstride[n];
    185      1.1  mrg 	    }
    186      1.1  mrg 	}
    187      1.1  mrg     }
    188      1.1  mrg }
    189      1.1  mrg 
    190      1.1  mrg 
    191      1.1  mrg extern void msum_c8 (gfc_array_c8 * const restrict,
    192      1.1  mrg 	gfc_array_c8 * const restrict, const index_type * const restrict,
    193      1.1  mrg 	gfc_array_l1 * const restrict);
    194      1.1  mrg export_proto(msum_c8);
    195      1.1  mrg 
    196      1.1  mrg void
    197      1.1  mrg msum_c8 (gfc_array_c8 * const restrict retarray,
    198      1.1  mrg 	gfc_array_c8 * const restrict array,
    199      1.1  mrg 	const index_type * const restrict pdim,
    200      1.1  mrg 	gfc_array_l1 * const restrict mask)
    201      1.1  mrg {
    202      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    203      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    204      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
    205      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    206      1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
    207      1.1  mrg   GFC_COMPLEX_8 * restrict dest;
    208      1.1  mrg   const GFC_COMPLEX_8 * restrict base;
    209      1.1  mrg   const GFC_LOGICAL_1 * restrict mbase;
    210      1.1  mrg   index_type rank;
    211      1.1  mrg   index_type dim;
    212      1.1  mrg   index_type n;
    213      1.1  mrg   index_type len;
    214      1.1  mrg   index_type delta;
    215      1.1  mrg   index_type mdelta;
    216      1.1  mrg   int mask_kind;
    217      1.1  mrg 
    218      1.1  mrg   if (mask == NULL)
    219      1.1  mrg     {
    220      1.1  mrg #ifdef HAVE_BACK_ARG
    221      1.1  mrg       sum_c8 (retarray, array, pdim, back);
    222      1.1  mrg #else
    223      1.1  mrg       sum_c8 (retarray, array, pdim);
    224      1.1  mrg #endif
    225      1.1  mrg       return;
    226      1.1  mrg     }
    227      1.1  mrg 
    228      1.1  mrg   dim = (*pdim) - 1;
    229      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    230      1.1  mrg 
    231      1.1  mrg 
    232      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    233      1.1  mrg     {
    234      1.1  mrg       runtime_error ("Dim argument incorrect in SUM intrinsic: "
    235      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    236      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    237      1.1  mrg     }
    238      1.1  mrg 
    239      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
    240  1.1.1.4  mrg   if (len < 0)
    241  1.1.1.4  mrg     len = 0;
    242      1.1  mrg 
    243      1.1  mrg   mbase = mask->base_addr;
    244      1.1  mrg 
    245      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    246      1.1  mrg 
    247      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    248      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    249      1.1  mrg       || mask_kind == 16
    250      1.1  mrg #endif
    251      1.1  mrg       )
    252      1.1  mrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    253      1.1  mrg   else
    254      1.1  mrg     runtime_error ("Funny sized logical array");
    255      1.1  mrg 
    256      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
    257      1.1  mrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
    258      1.1  mrg 
    259      1.1  mrg   for (n = 0; n < dim; n++)
    260      1.1  mrg     {
    261      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
    262      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    263      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    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   for (n = dim; n < rank; n++)
    270      1.1  mrg     {
    271      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
    272      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
    273      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
    274      1.1  mrg 
    275      1.1  mrg       if (extent[n] < 0)
    276      1.1  mrg 	extent[n] = 0;
    277      1.1  mrg     }
    278      1.1  mrg 
    279      1.1  mrg   if (retarray->base_addr == NULL)
    280      1.1  mrg     {
    281      1.1  mrg       size_t alloc_size, str;
    282      1.1  mrg 
    283      1.1  mrg       for (n = 0; n < rank; n++)
    284      1.1  mrg 	{
    285      1.1  mrg 	  if (n == 0)
    286      1.1  mrg 	    str = 1;
    287      1.1  mrg 	  else
    288      1.1  mrg 	    str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    289      1.1  mrg 
    290      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    291      1.1  mrg 
    292      1.1  mrg 	}
    293      1.1  mrg 
    294      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    295      1.1  mrg 
    296      1.1  mrg       retarray->offset = 0;
    297      1.1  mrg       retarray->dtype.rank = rank;
    298      1.1  mrg 
    299  1.1.1.4  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_COMPLEX_8));
    300      1.1  mrg       if (alloc_size == 0)
    301  1.1.1.4  mrg 	return;
    302      1.1  mrg     }
    303      1.1  mrg   else
    304      1.1  mrg     {
    305      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    306      1.1  mrg 	runtime_error ("rank of return array incorrect in SUM intrinsic");
    307      1.1  mrg 
    308      1.1  mrg       if (unlikely (compile_options.bounds_check))
    309      1.1  mrg 	{
    310      1.1  mrg 	  bounds_ifunction_return ((array_t *) retarray, extent,
    311      1.1  mrg 				   "return value", "SUM");
    312      1.1  mrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
    313      1.1  mrg 	  			"MASK argument", "SUM");
    314      1.1  mrg 	}
    315      1.1  mrg     }
    316      1.1  mrg 
    317      1.1  mrg   for (n = 0; n < rank; n++)
    318      1.1  mrg     {
    319      1.1  mrg       count[n] = 0;
    320      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    321      1.1  mrg       if (extent[n] <= 0)
    322      1.1  mrg 	return;
    323      1.1  mrg     }
    324      1.1  mrg 
    325      1.1  mrg   dest = retarray->base_addr;
    326      1.1  mrg   base = array->base_addr;
    327      1.1  mrg 
    328      1.1  mrg   while (base)
    329      1.1  mrg     {
    330      1.1  mrg       const GFC_COMPLEX_8 * restrict src;
    331      1.1  mrg       const GFC_LOGICAL_1 * restrict msrc;
    332      1.1  mrg       GFC_COMPLEX_8 result;
    333      1.1  mrg       src = base;
    334      1.1  mrg       msrc = mbase;
    335      1.1  mrg       {
    336      1.1  mrg 
    337      1.1  mrg   result = 0;
    338      1.1  mrg 	for (n = 0; n < len; n++, src += delta, msrc += mdelta)
    339      1.1  mrg 	  {
    340      1.1  mrg 
    341      1.1  mrg   if (*msrc)
    342      1.1  mrg     result += *src;
    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 }
    379      1.1  mrg 
    380      1.1  mrg 
    381      1.1  mrg extern void ssum_c8 (gfc_array_c8 * const restrict,
    382      1.1  mrg 	gfc_array_c8 * const restrict, const index_type * const restrict,
    383      1.1  mrg 	GFC_LOGICAL_4 *);
    384      1.1  mrg export_proto(ssum_c8);
    385      1.1  mrg 
    386      1.1  mrg void
    387      1.1  mrg ssum_c8 (gfc_array_c8 * const restrict retarray,
    388      1.1  mrg 	gfc_array_c8 * const restrict array,
    389      1.1  mrg 	const index_type * const restrict pdim,
    390      1.1  mrg 	GFC_LOGICAL_4 * mask)
    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   GFC_COMPLEX_8 * 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       sum_c8 (retarray, array, pdim, back);
    405      1.1  mrg #else
    406      1.1  mrg       sum_c8 (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 SUM 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.1.4  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_COMPLEX_8));
    459      1.1  mrg       if (alloc_size == 0)
    460  1.1.1.4  mrg 	return;
    461      1.1  mrg     }
    462      1.1  mrg   else
    463      1.1  mrg     {
    464      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    465      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    466      1.1  mrg 		       " SUM intrinsic: is %ld, should be %ld",
    467      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    468      1.1  mrg 		       (long int) rank);
    469      1.1  mrg 
    470      1.1  mrg       if (unlikely (compile_options.bounds_check))
    471      1.1  mrg 	{
    472      1.1  mrg 	  for (n=0; n < rank; n++)
    473      1.1  mrg 	    {
    474      1.1  mrg 	      index_type ret_extent;
    475      1.1  mrg 
    476      1.1  mrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
    477      1.1  mrg 	      if (extent[n] != ret_extent)
    478      1.1  mrg 		runtime_error ("Incorrect extent in return value of"
    479      1.1  mrg 			       " SUM intrinsic in dimension %ld:"
    480      1.1  mrg 			       " is %ld, should be %ld", (long int) n + 1,
    481      1.1  mrg 			       (long int) ret_extent, (long int) extent[n]);
    482      1.1  mrg 	    }
    483      1.1  mrg 	}
    484      1.1  mrg     }
    485      1.1  mrg 
    486      1.1  mrg   for (n = 0; n < rank; n++)
    487      1.1  mrg     {
    488      1.1  mrg       count[n] = 0;
    489      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    490      1.1  mrg     }
    491      1.1  mrg 
    492      1.1  mrg   dest = retarray->base_addr;
    493      1.1  mrg 
    494      1.1  mrg   while(1)
    495      1.1  mrg     {
    496      1.1  mrg       *dest = 0;
    497      1.1  mrg       count[0]++;
    498      1.1  mrg       dest += dstride[0];
    499      1.1  mrg       n = 0;
    500      1.1  mrg       while (count[n] == extent[n])
    501      1.1  mrg 	{
    502      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    503      1.1  mrg 	     the next dimension.  */
    504      1.1  mrg 	  count[n] = 0;
    505      1.1  mrg 	  /* We could precalculate these products, but this is a less
    506      1.1  mrg 	     frequently used path so probably not worth it.  */
    507      1.1  mrg 	  dest -= dstride[n] * extent[n];
    508      1.1  mrg 	  n++;
    509      1.1  mrg 	  if (n >= rank)
    510      1.1  mrg 	    return;
    511      1.1  mrg 	  else
    512      1.1  mrg 	    {
    513      1.1  mrg 	      count[n]++;
    514      1.1  mrg 	      dest += dstride[n];
    515      1.1  mrg 	    }
    516      1.1  mrg       	}
    517      1.1  mrg     }
    518      1.1  mrg }
    519      1.1  mrg 
    520      1.1  mrg #endif
    521