198186Sgordon/* Implementation of the SUM intrinsic
298186Sgordon   Copyright (C) 2002-2022 Free Software Foundation, Inc.
378344Sobrien   Contributed by Paul Brook <paul@nowt.org>
498186Sgordon
578344SobrienThis file is part of the GNU Fortran 95 runtime library (libgfortran).
678344Sobrien
778344SobrienLibgfortran is free software; you can redistribute it and/or
878344Sobrienmodify it under the terms of the GNU General Public
978344SobrienLicense as published by the Free Software Foundation; either
1078344Sobrienversion 3 of the License, or (at your option) any later version.
1178344Sobrien
1278344SobrienLibgfortran is distributed in the hope that it will be useful,
1378344Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1478344SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1578344SobrienGNU General Public License for more details.
1678344Sobrien
1778344SobrienUnder Section 7 of GPL version 3, you are granted additional
1878344Sobrienpermissions described in the GCC Runtime Library Exception, version
1978344Sobrien3.1, as published by the Free Software Foundation.
2078344Sobrien
2178344SobrienYou should have received a copy of the GNU General Public License and
2278344Sobriena copy of the GCC Runtime Library Exception along with this program;
2378344Sobriensee the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2478344Sobrien<http://www.gnu.org/licenses/>.  */
2578344Sobrien
2678344Sobrien#include "libgfortran.h"
2778344Sobrien
2878344Sobrien
2978344Sobrien#if defined (HAVE_GFC_REAL_16) && defined (HAVE_GFC_REAL_16)
3078344Sobrien
3178344Sobrien
3278344Sobrienextern void sum_r16 (gfc_array_r16 * const restrict,
3378344Sobrien	gfc_array_r16 * const restrict, const index_type * const restrict);
3478344Sobrienexport_proto(sum_r16);
3578344Sobrien
3678344Sobrienvoid
3778344Sobriensum_r16 (gfc_array_r16 * const restrict retarray,
3878344Sobrien	gfc_array_r16 * const restrict array,
3978344Sobrien	const index_type * const restrict pdim)
4078344Sobrien{
4178344Sobrien  index_type count[GFC_MAX_DIMENSIONS];
4278344Sobrien  index_type extent[GFC_MAX_DIMENSIONS];
4398186Sgordon  index_type sstride[GFC_MAX_DIMENSIONS];
4498186Sgordon  index_type dstride[GFC_MAX_DIMENSIONS];
4598186Sgordon  const GFC_REAL_16 * restrict base;
4698186Sgordon  GFC_REAL_16 * restrict dest;
4798186Sgordon  index_type rank;
4898186Sgordon  index_type n;
49103018Sgordon  index_type len;
50124832Smtm  index_type delta;
51124832Smtm  index_type dim;
5298186Sgordon  int continue_loop;
53103018Sgordon
5498186Sgordon  /* Make dim zero based to avoid confusion.  */
5598186Sgordon  rank = GFC_DESCRIPTOR_RANK (array) - 1;
5698186Sgordon  dim = (*pdim) - 1;
5798186Sgordon
5898186Sgordon  if (unlikely (dim < 0 || dim > rank))
5998186Sgordon    {
6098186Sgordon      runtime_error ("Dim argument incorrect in SUM intrinsic: "
6198186Sgordon 		     "is %ld, should be between 1 and %ld",
6298186Sgordon		     (long int) dim + 1, (long int) rank + 1);
6378344Sobrien    }
6478344Sobrien
6578344Sobrien  len = GFC_DESCRIPTOR_EXTENT(array,dim);
6678344Sobrien  if (len < 0)
6798186Sgordon    len = 0;
6898186Sgordon  delta = GFC_DESCRIPTOR_STRIDE(array,dim);
6998186Sgordon
7098186Sgordon  for (n = 0; n < dim; n++)
7198186Sgordon    {
7298186Sgordon      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
7398186Sgordon      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
7498186Sgordon
7598186Sgordon      if (extent[n] < 0)
7698186Sgordon	extent[n] = 0;
7798186Sgordon    }
7898186Sgordon  for (n = dim; n < rank; n++)
7998186Sgordon    {
8098186Sgordon      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
8198186Sgordon      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
8298186Sgordon
8398186Sgordon      if (extent[n] < 0)
84103018Sgordon	extent[n] = 0;
8598186Sgordon    }
8698186Sgordon
8798186Sgordon  if (retarray->base_addr == NULL)
8898186Sgordon    {
8998186Sgordon      size_t alloc_size, str;
9098186Sgordon
9198186Sgordon      for (n = 0; n < rank; n++)
9298186Sgordon	{
9398186Sgordon	  if (n == 0)
9498186Sgordon	    str = 1;
9598186Sgordon	  else
9698186Sgordon	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
9798186Sgordon
9898186Sgordon	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
9998186Sgordon
10098186Sgordon	}
10198186Sgordon
10298186Sgordon      retarray->offset = 0;
10398186Sgordon      retarray->dtype.rank = rank;
10498186Sgordon
10598186Sgordon      alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
10698186Sgordon
10798186Sgordon      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_REAL_16));
10898186Sgordon      if (alloc_size == 0)
10998186Sgordon	{
11098186Sgordon	  /* Make sure we have a zero-sized array.  */
11198186Sgordon	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
11298186Sgordon	  return;
11398186Sgordon
11498186Sgordon	}
11598186Sgordon    }
11698186Sgordon  else
11778344Sobrien    {
11878344Sobrien      if (rank != GFC_DESCRIPTOR_RANK (retarray))
11978344Sobrien	runtime_error ("rank of return array incorrect in"
12078344Sobrien		       " SUM intrinsic: is %ld, should be %ld",
12178344Sobrien		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
12278344Sobrien		       (long int) rank);
12378344Sobrien
12498186Sgordon      if (unlikely (compile_options.bounds_check))
12578344Sobrien	bounds_ifunction_return ((array_t *) retarray, extent,
12678344Sobrien				 "return value", "SUM");
12778344Sobrien    }
12878344Sobrien
12978344Sobrien  for (n = 0; n < rank; n++)
13078344Sobrien    {
13178344Sobrien      count[n] = 0;
13278344Sobrien      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
13378344Sobrien      if (extent[n] <= 0)
13478344Sobrien	return;
13578344Sobrien    }
13678344Sobrien
137106643Sgordon  base = array->base_addr;
13878344Sobrien  dest = retarray->base_addr;
13978344Sobrien
14078344Sobrien  continue_loop = 1;
14178344Sobrien  while (continue_loop)
14278344Sobrien    {
14398186Sgordon      const GFC_REAL_16 * restrict src;
14498186Sgordon      GFC_REAL_16 result;
14578344Sobrien      src = base;
14698186Sgordon      {
14798186Sgordon
14898186Sgordon  result = 0;
149126286Smtm	if (len <= 0)
15098186Sgordon	  *dest = 0;
15198186Sgordon	else
15298186Sgordon	  {
15398186Sgordon#if ! defined HAVE_BACK_ARG
15498186Sgordon	    for (n = 0; n < len; n++, src += delta)
15578344Sobrien	      {
15698186Sgordon#endif
15798186Sgordon
15898186Sgordon  result += *src;
15998186Sgordon	      }
16098186Sgordon
16178344Sobrien	    *dest = result;
16278344Sobrien	  }
16398186Sgordon      }
16478344Sobrien      /* Advance to the next element.  */
16578344Sobrien      count[0]++;
166126285Smtm      base += sstride[0];
16778344Sobrien      dest += dstride[0];
16878344Sobrien      n = 0;
169126285Smtm      while (count[n] == extent[n])
17078344Sobrien	{
17178344Sobrien	  /* When we get to the end of a dimension, reset it and increment
172126285Smtm	     the next dimension.  */
173126285Smtm	  count[n] = 0;
174126285Smtm	  /* We could precalculate these products, but this is a less
17578344Sobrien	     frequently used path so probably not worth it.  */
17678344Sobrien	  base -= sstride[n] * extent[n];
17798186Sgordon	  dest -= dstride[n] * extent[n];
17878344Sobrien	  n++;
17978344Sobrien	  if (n >= rank)
18078344Sobrien	    {
18178344Sobrien	      /* Break out of the loop.  */
18298186Sgordon	      continue_loop = 0;
18398186Sgordon	      break;
18478344Sobrien	    }
18598186Sgordon	  else
18698186Sgordon	    {
18778344Sobrien	      count[n]++;
18878344Sobrien	      base += sstride[n];
18978344Sobrien	      dest += dstride[n];
19078344Sobrien	    }
19178344Sobrien	}
19298186Sgordon    }
19378344Sobrien}
19498186Sgordon
19578344Sobrien
19678344Sobrienextern void msum_r16 (gfc_array_r16 * const restrict,
19798186Sgordon	gfc_array_r16 * const restrict, const index_type * const restrict,
19878344Sobrien	gfc_array_l1 * const restrict);
19978344Sobrienexport_proto(msum_r16);
20078344Sobrien
20178344Sobrienvoid
20298186Sgordonmsum_r16 (gfc_array_r16 * const restrict retarray,
20378344Sobrien	gfc_array_r16 * const restrict array,
20478344Sobrien	const index_type * const restrict pdim,
20598186Sgordon	gfc_array_l1 * const restrict mask)
20678344Sobrien{
20778344Sobrien  index_type count[GFC_MAX_DIMENSIONS];
20878344Sobrien  index_type extent[GFC_MAX_DIMENSIONS];
20998186Sgordon  index_type sstride[GFC_MAX_DIMENSIONS];
21078344Sobrien  index_type dstride[GFC_MAX_DIMENSIONS];
21198186Sgordon  index_type mstride[GFC_MAX_DIMENSIONS];
21298186Sgordon  GFC_REAL_16 * restrict dest;
21378344Sobrien  const GFC_REAL_16 * restrict base;
21478344Sobrien  const GFC_LOGICAL_1 * restrict mbase;
21578344Sobrien  index_type rank;
21678344Sobrien  index_type dim;
21798186Sgordon  index_type n;
21878344Sobrien  index_type len;
21998186Sgordon  index_type delta;
22078344Sobrien  index_type mdelta;
22198186Sgordon  int mask_kind;
22298186Sgordon
22398186Sgordon  if (mask == NULL)
22498186Sgordon    {
22598186Sgordon#ifdef HAVE_BACK_ARG
22698186Sgordon      sum_r16 (retarray, array, pdim, back);
22798186Sgordon#else
22898186Sgordon      sum_r16 (retarray, array, pdim);
22998186Sgordon#endif
23098186Sgordon      return;
23198186Sgordon    }
23298186Sgordon
23398186Sgordon  dim = (*pdim) - 1;
23498186Sgordon  rank = GFC_DESCRIPTOR_RANK (array) - 1;
23598186Sgordon
23698186Sgordon
23798186Sgordon  if (unlikely (dim < 0 || dim > rank))
23898186Sgordon    {
23998186Sgordon      runtime_error ("Dim argument incorrect in SUM intrinsic: "
24098186Sgordon 		     "is %ld, should be between 1 and %ld",
24198186Sgordon		     (long int) dim + 1, (long int) rank + 1);
24298186Sgordon    }
24398186Sgordon
24498186Sgordon  len = GFC_DESCRIPTOR_EXTENT(array,dim);
24598186Sgordon  if (len <= 0)
24698186Sgordon    return;
24798186Sgordon
24898186Sgordon  mbase = mask->base_addr;
24998186Sgordon
25078344Sobrien  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
25198186Sgordon
25298186Sgordon  if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
25398186Sgordon#ifdef HAVE_GFC_LOGICAL_16
25498186Sgordon      || mask_kind == 16
25598186Sgordon#endif
25698186Sgordon      )
25778344Sobrien    mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
25898186Sgordon  else
25998186Sgordon    runtime_error ("Funny sized logical array");
26098186Sgordon
26198186Sgordon  delta = GFC_DESCRIPTOR_STRIDE(array,dim);
26298186Sgordon  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
26398186Sgordon
26498186Sgordon  for (n = 0; n < dim; n++)
26598186Sgordon    {
26698186Sgordon      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
26798186Sgordon      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
26898186Sgordon      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
26998186Sgordon
27098186Sgordon      if (extent[n] < 0)
27198186Sgordon	extent[n] = 0;
27298186Sgordon
27398186Sgordon    }
27498186Sgordon  for (n = dim; n < rank; n++)
27598186Sgordon    {
27698186Sgordon      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
27798186Sgordon      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
27898186Sgordon      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
27998186Sgordon
28098186Sgordon      if (extent[n] < 0)
28198186Sgordon	extent[n] = 0;
282114272Smtm    }
28398186Sgordon
28498186Sgordon  if (retarray->base_addr == NULL)
28598186Sgordon    {
28698186Sgordon      size_t alloc_size, str;
28798186Sgordon
28898186Sgordon      for (n = 0; n < rank; n++)
28998186Sgordon	{
29098186Sgordon	  if (n == 0)
29198186Sgordon	    str = 1;
292126286Smtm	  else
29398186Sgordon	    str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
29498186Sgordon
29598186Sgordon	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
29698186Sgordon
29798186Sgordon	}
29898186Sgordon
29998186Sgordon      alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
30098186Sgordon
30198186Sgordon      retarray->offset = 0;
30298186Sgordon      retarray->dtype.rank = rank;
30398186Sgordon
30498186Sgordon      if (alloc_size == 0)
30598186Sgordon	{
30678344Sobrien	  /* Make sure we have a zero-sized array.  */
30798186Sgordon	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
30898186Sgordon	  return;
30998186Sgordon	}
31098186Sgordon      else
31178344Sobrien	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_REAL_16));
31298186Sgordon
31398186Sgordon    }
31498186Sgordon  else
31578344Sobrien    {
31678344Sobrien      if (rank != GFC_DESCRIPTOR_RANK (retarray))
31778344Sobrien	runtime_error ("rank of return array incorrect in SUM intrinsic");
31898186Sgordon
31998186Sgordon      if (unlikely (compile_options.bounds_check))
32098186Sgordon	{
32198186Sgordon	  bounds_ifunction_return ((array_t *) retarray, extent,
32298186Sgordon				   "return value", "SUM");
32378344Sobrien	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
32498186Sgordon	  			"MASK argument", "SUM");
32598186Sgordon	}
32678344Sobrien    }
32798186Sgordon
32898186Sgordon  for (n = 0; n < rank; n++)
32978344Sobrien    {
33078344Sobrien      count[n] = 0;
33178344Sobrien      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
33298186Sgordon      if (extent[n] <= 0)
33398186Sgordon	return;
33478344Sobrien    }
33578344Sobrien
33678344Sobrien  dest = retarray->base_addr;
33798186Sgordon  base = array->base_addr;
33878344Sobrien
33978344Sobrien  while (base)
34078344Sobrien    {
34178344Sobrien      const GFC_REAL_16 * restrict src;
34298186Sgordon      const GFC_LOGICAL_1 * restrict msrc;
34398186Sgordon      GFC_REAL_16 result;
34498186Sgordon      src = base;
34578344Sobrien      msrc = mbase;
34678344Sobrien      {
34798186Sgordon
34898186Sgordon  result = 0;
34998186Sgordon	for (n = 0; n < len; n++, src += delta, msrc += mdelta)
35078344Sobrien	  {
35198186Sgordon
35298186Sgordon  if (*msrc)
35378344Sobrien    result += *src;
35478344Sobrien	  }
35578344Sobrien	*dest = result;
35678344Sobrien      }
35798186Sgordon      /* Advance to the next element.  */
35878344Sobrien      count[0]++;
35978344Sobrien      base += sstride[0];
36078344Sobrien      mbase += mstride[0];
36178344Sobrien      dest += dstride[0];
36278344Sobrien      n = 0;
36378344Sobrien      while (count[n] == extent[n])
36478344Sobrien	{
36578344Sobrien	  /* When we get to the end of a dimension, reset it and increment
36678344Sobrien	     the next dimension.  */
36778344Sobrien	  count[n] = 0;
36878344Sobrien	  /* We could precalculate these products, but this is a less
36978344Sobrien	     frequently used path so probably not worth it.  */
37098186Sgordon	  base -= sstride[n] * extent[n];
37178344Sobrien	  mbase -= mstride[n] * extent[n];
37278344Sobrien	  dest -= dstride[n] * extent[n];
37398186Sgordon	  n++;
37478344Sobrien	  if (n >= rank)
37598186Sgordon	    {
37698186Sgordon	      /* Break out of the loop.  */
37798186Sgordon	      base = NULL;
37878344Sobrien	      break;
37998186Sgordon	    }
38078344Sobrien	  else
38178344Sobrien	    {
38298186Sgordon	      count[n]++;
38398186Sgordon	      base += sstride[n];
38498186Sgordon	      mbase += mstride[n];
38598186Sgordon	      dest += dstride[n];
38678344Sobrien	    }
38798186Sgordon	}
38878344Sobrien    }
38998186Sgordon}
39098186Sgordon
39198186Sgordon
39298186Sgordonextern void ssum_r16 (gfc_array_r16 * const restrict,
39378344Sobrien	gfc_array_r16 * const restrict, const index_type * const restrict,
39478344Sobrien	GFC_LOGICAL_4 *);
39578344Sobrienexport_proto(ssum_r16);
39678344Sobrien
39778344Sobrienvoid
39878344Sobrienssum_r16 (gfc_array_r16 * const restrict retarray,
39978344Sobrien	gfc_array_r16 * const restrict array,
40078344Sobrien	const index_type * const restrict pdim,
40178344Sobrien	GFC_LOGICAL_4 * mask)
40278344Sobrien{
40378344Sobrien  index_type count[GFC_MAX_DIMENSIONS];
40478344Sobrien  index_type extent[GFC_MAX_DIMENSIONS];
40598186Sgordon  index_type dstride[GFC_MAX_DIMENSIONS];
40698186Sgordon  GFC_REAL_16 * restrict dest;
40778344Sobrien  index_type rank;
40898186Sgordon  index_type n;
40998186Sgordon  index_type dim;
41078344Sobrien
41178344Sobrien
41278344Sobrien  if (mask == NULL || *mask)
41378344Sobrien    {
41498186Sgordon#ifdef HAVE_BACK_ARG
41578344Sobrien      sum_r16 (retarray, array, pdim, back);
41698186Sgordon#else
41798186Sgordon      sum_r16 (retarray, array, pdim);
41898186Sgordon#endif
41998186Sgordon      return;
42078344Sobrien    }
42198186Sgordon  /* Make dim zero based to avoid confusion.  */
42298186Sgordon  dim = (*pdim) - 1;
42378344Sobrien  rank = GFC_DESCRIPTOR_RANK (array) - 1;
42478344Sobrien
42578344Sobrien  if (unlikely (dim < 0 || dim > rank))
42678344Sobrien    {
42798186Sgordon      runtime_error ("Dim argument incorrect in SUM intrinsic: "
42878344Sobrien 		     "is %ld, should be between 1 and %ld",
42998186Sgordon		     (long int) dim + 1, (long int) rank + 1);
43098186Sgordon    }
43198186Sgordon
43298186Sgordon  for (n = 0; n < dim; n++)
43398186Sgordon    {
43498186Sgordon      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
43598186Sgordon
43698186Sgordon      if (extent[n] <= 0)
43798186Sgordon	extent[n] = 0;
43898186Sgordon    }
43998186Sgordon
44098186Sgordon  for (n = dim; n < rank; n++)
44198186Sgordon    {
44298186Sgordon      extent[n] =
44398186Sgordon	GFC_DESCRIPTOR_EXTENT(array,n + 1);
44498186Sgordon
44598186Sgordon      if (extent[n] <= 0)
44698186Sgordon	extent[n] = 0;
44798186Sgordon    }
44898186Sgordon
44998186Sgordon  if (retarray->base_addr == NULL)
45098186Sgordon    {
45198186Sgordon      size_t alloc_size, str;
45298186Sgordon
45378344Sobrien      for (n = 0; n < rank; n++)
45478344Sobrien	{
455116097Smtm	  if (n == 0)
45698186Sgordon	    str = 1;
45778344Sobrien	  else
45898186Sgordon	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
45978344Sobrien
46078344Sobrien	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
46198186Sgordon
46278344Sobrien	}
46398186Sgordon
46498186Sgordon      retarray->offset = 0;
46578344Sobrien      retarray->dtype.rank = rank;
46678344Sobrien
46798186Sgordon      alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
46898186Sgordon
46978344Sobrien      if (alloc_size == 0)
47078344Sobrien	{
47178344Sobrien	  /* Make sure we have a zero-sized array.  */
47278344Sobrien	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
47378344Sobrien	  return;
47478344Sobrien	}
47598186Sgordon      else
47698186Sgordon	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_REAL_16));
47798186Sgordon    }
47898186Sgordon  else
47998186Sgordon    {
48078344Sobrien      if (rank != GFC_DESCRIPTOR_RANK (retarray))
48198186Sgordon	runtime_error ("rank of return array incorrect in"
48278344Sobrien		       " SUM intrinsic: is %ld, should be %ld",
48398186Sgordon		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
48498186Sgordon		       (long int) rank);
48578344Sobrien
48698186Sgordon      if (unlikely (compile_options.bounds_check))
48778344Sobrien	{
48898186Sgordon	  for (n=0; n < rank; n++)
48998186Sgordon	    {
49098186Sgordon	      index_type ret_extent;
49178344Sobrien
49278344Sobrien	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
49398186Sgordon	      if (extent[n] != ret_extent)
49478344Sobrien		runtime_error ("Incorrect extent in return value of"
49578344Sobrien			       " SUM intrinsic in dimension %ld:"
49678344Sobrien			       " is %ld, should be %ld", (long int) n + 1,
49798186Sgordon			       (long int) ret_extent, (long int) extent[n]);
49878344Sobrien	    }
49978344Sobrien	}
50078344Sobrien    }
50178344Sobrien
50298186Sgordon  for (n = 0; n < rank; n++)
50378344Sobrien    {
50498186Sgordon      count[n] = 0;
50578344Sobrien      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
50698186Sgordon    }
50798186Sgordon
50898186Sgordon  dest = retarray->base_addr;
50978344Sobrien
51098186Sgordon  while(1)
511124832Smtm    {
51298186Sgordon      *dest = 0;
51398186Sgordon      count[0]++;
51498186Sgordon      dest += dstride[0];
51598186Sgordon      n = 0;
51678344Sobrien      while (count[n] == extent[n])
51798186Sgordon	{
51878344Sobrien	  /* When we get to the end of a dimension, reset it and increment
51978344Sobrien	     the next dimension.  */
52078344Sobrien	  count[n] = 0;
52198186Sgordon	  /* We could precalculate these products, but this is a less
52278344Sobrien	     frequently used path so probably not worth it.  */
52378344Sobrien	  dest -= dstride[n] * extent[n];
52478344Sobrien	  n++;
52578344Sobrien	  if (n >= rank)
52678344Sobrien	    return;
52778344Sobrien	  else
52878344Sobrien	    {
52978344Sobrien	      count[n]++;
53098186Sgordon	      dest += dstride[n];
53178344Sobrien	    }
53278344Sobrien      	}
53378344Sobrien    }
53478344Sobrien}
53578344Sobrien
53678344Sobrien#endif
53798186Sgordon