xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/sum_i2.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1181254a7Smrg /* Implementation of the SUM intrinsic
2*b1e83836Smrg    Copyright (C) 2002-2022 Free Software Foundation, Inc.
3181254a7Smrg    Contributed by Paul Brook <paul@nowt.org>
4181254a7Smrg 
5181254a7Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
6181254a7Smrg 
7181254a7Smrg Libgfortran is free software; you can redistribute it and/or
8181254a7Smrg modify it under the terms of the GNU General Public
9181254a7Smrg License as published by the Free Software Foundation; either
10181254a7Smrg version 3 of the License, or (at your option) any later version.
11181254a7Smrg 
12181254a7Smrg Libgfortran is distributed in the hope that it will be useful,
13181254a7Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14181254a7Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15181254a7Smrg GNU General Public License for more details.
16181254a7Smrg 
17181254a7Smrg Under Section 7 of GPL version 3, you are granted additional
18181254a7Smrg permissions described in the GCC Runtime Library Exception, version
19181254a7Smrg 3.1, as published by the Free Software Foundation.
20181254a7Smrg 
21181254a7Smrg You should have received a copy of the GNU General Public License and
22181254a7Smrg a copy of the GCC Runtime Library Exception along with this program;
23181254a7Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24181254a7Smrg <http://www.gnu.org/licenses/>.  */
25181254a7Smrg 
26181254a7Smrg #include "libgfortran.h"
27181254a7Smrg 
28181254a7Smrg 
29181254a7Smrg #if defined (HAVE_GFC_INTEGER_2) && defined (HAVE_GFC_INTEGER_2)
30181254a7Smrg 
31181254a7Smrg 
32181254a7Smrg extern void sum_i2 (gfc_array_i2 * const restrict,
33181254a7Smrg 	gfc_array_i2 * const restrict, const index_type * const restrict);
34181254a7Smrg export_proto(sum_i2);
35181254a7Smrg 
36181254a7Smrg void
sum_i2(gfc_array_i2 * const restrict retarray,gfc_array_i2 * const restrict array,const index_type * const restrict pdim)37181254a7Smrg sum_i2 (gfc_array_i2 * const restrict retarray,
38181254a7Smrg 	gfc_array_i2 * const restrict array,
39181254a7Smrg 	const index_type * const restrict pdim)
40181254a7Smrg {
41181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
42181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
43181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
44181254a7Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
45181254a7Smrg   const GFC_INTEGER_2 * restrict base;
46181254a7Smrg   GFC_INTEGER_2 * restrict dest;
47181254a7Smrg   index_type rank;
48181254a7Smrg   index_type n;
49181254a7Smrg   index_type len;
50181254a7Smrg   index_type delta;
51181254a7Smrg   index_type dim;
52181254a7Smrg   int continue_loop;
53181254a7Smrg 
54181254a7Smrg   /* Make dim zero based to avoid confusion.  */
55181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
56181254a7Smrg   dim = (*pdim) - 1;
57181254a7Smrg 
58181254a7Smrg   if (unlikely (dim < 0 || dim > rank))
59181254a7Smrg     {
60181254a7Smrg       runtime_error ("Dim argument incorrect in SUM intrinsic: "
61181254a7Smrg  		     "is %ld, should be between 1 and %ld",
62181254a7Smrg 		     (long int) dim + 1, (long int) rank + 1);
63181254a7Smrg     }
64181254a7Smrg 
65181254a7Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
66181254a7Smrg   if (len < 0)
67181254a7Smrg     len = 0;
68181254a7Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
69181254a7Smrg 
70181254a7Smrg   for (n = 0; n < dim; n++)
71181254a7Smrg     {
72181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
73181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
74181254a7Smrg 
75181254a7Smrg       if (extent[n] < 0)
76181254a7Smrg 	extent[n] = 0;
77181254a7Smrg     }
78181254a7Smrg   for (n = dim; n < rank; n++)
79181254a7Smrg     {
80181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
81181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
82181254a7Smrg 
83181254a7Smrg       if (extent[n] < 0)
84181254a7Smrg 	extent[n] = 0;
85181254a7Smrg     }
86181254a7Smrg 
87181254a7Smrg   if (retarray->base_addr == NULL)
88181254a7Smrg     {
89181254a7Smrg       size_t alloc_size, str;
90181254a7Smrg 
91181254a7Smrg       for (n = 0; n < rank; n++)
92181254a7Smrg 	{
93181254a7Smrg 	  if (n == 0)
94181254a7Smrg 	    str = 1;
95181254a7Smrg 	  else
96181254a7Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
97181254a7Smrg 
98181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
99181254a7Smrg 
100181254a7Smrg 	}
101181254a7Smrg 
102181254a7Smrg       retarray->offset = 0;
103181254a7Smrg       retarray->dtype.rank = rank;
104181254a7Smrg 
105181254a7Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
106181254a7Smrg 
107181254a7Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_2));
108181254a7Smrg       if (alloc_size == 0)
109181254a7Smrg 	{
110181254a7Smrg 	  /* Make sure we have a zero-sized array.  */
111181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
112181254a7Smrg 	  return;
113181254a7Smrg 
114181254a7Smrg 	}
115181254a7Smrg     }
116181254a7Smrg   else
117181254a7Smrg     {
118181254a7Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
119181254a7Smrg 	runtime_error ("rank of return array incorrect in"
120181254a7Smrg 		       " SUM intrinsic: is %ld, should be %ld",
121181254a7Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
122181254a7Smrg 		       (long int) rank);
123181254a7Smrg 
124181254a7Smrg       if (unlikely (compile_options.bounds_check))
125181254a7Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
126181254a7Smrg 				 "return value", "SUM");
127181254a7Smrg     }
128181254a7Smrg 
129181254a7Smrg   for (n = 0; n < rank; n++)
130181254a7Smrg     {
131181254a7Smrg       count[n] = 0;
132181254a7Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
133181254a7Smrg       if (extent[n] <= 0)
134181254a7Smrg 	return;
135181254a7Smrg     }
136181254a7Smrg 
137181254a7Smrg   base = array->base_addr;
138181254a7Smrg   dest = retarray->base_addr;
139181254a7Smrg 
140181254a7Smrg   continue_loop = 1;
141181254a7Smrg   while (continue_loop)
142181254a7Smrg     {
143181254a7Smrg       const GFC_INTEGER_2 * restrict src;
144181254a7Smrg       GFC_INTEGER_2 result;
145181254a7Smrg       src = base;
146181254a7Smrg       {
147181254a7Smrg 
148181254a7Smrg   result = 0;
149181254a7Smrg 	if (len <= 0)
150181254a7Smrg 	  *dest = 0;
151181254a7Smrg 	else
152181254a7Smrg 	  {
153181254a7Smrg #if ! defined HAVE_BACK_ARG
154181254a7Smrg 	    for (n = 0; n < len; n++, src += delta)
155181254a7Smrg 	      {
156181254a7Smrg #endif
157181254a7Smrg 
158181254a7Smrg   result += *src;
159181254a7Smrg 	      }
160181254a7Smrg 
161181254a7Smrg 	    *dest = result;
162181254a7Smrg 	  }
163181254a7Smrg       }
164181254a7Smrg       /* Advance to the next element.  */
165181254a7Smrg       count[0]++;
166181254a7Smrg       base += sstride[0];
167181254a7Smrg       dest += dstride[0];
168181254a7Smrg       n = 0;
169181254a7Smrg       while (count[n] == extent[n])
170181254a7Smrg 	{
171181254a7Smrg 	  /* When we get to the end of a dimension, reset it and increment
172181254a7Smrg 	     the next dimension.  */
173181254a7Smrg 	  count[n] = 0;
174181254a7Smrg 	  /* We could precalculate these products, but this is a less
175181254a7Smrg 	     frequently used path so probably not worth it.  */
176181254a7Smrg 	  base -= sstride[n] * extent[n];
177181254a7Smrg 	  dest -= dstride[n] * extent[n];
178181254a7Smrg 	  n++;
179181254a7Smrg 	  if (n >= rank)
180181254a7Smrg 	    {
181181254a7Smrg 	      /* Break out of the loop.  */
182181254a7Smrg 	      continue_loop = 0;
183181254a7Smrg 	      break;
184181254a7Smrg 	    }
185181254a7Smrg 	  else
186181254a7Smrg 	    {
187181254a7Smrg 	      count[n]++;
188181254a7Smrg 	      base += sstride[n];
189181254a7Smrg 	      dest += dstride[n];
190181254a7Smrg 	    }
191181254a7Smrg 	}
192181254a7Smrg     }
193181254a7Smrg }
194181254a7Smrg 
195181254a7Smrg 
196181254a7Smrg extern void msum_i2 (gfc_array_i2 * const restrict,
197181254a7Smrg 	gfc_array_i2 * const restrict, const index_type * const restrict,
198181254a7Smrg 	gfc_array_l1 * const restrict);
199181254a7Smrg export_proto(msum_i2);
200181254a7Smrg 
201181254a7Smrg void
msum_i2(gfc_array_i2 * const restrict retarray,gfc_array_i2 * const restrict array,const index_type * const restrict pdim,gfc_array_l1 * const restrict mask)202181254a7Smrg msum_i2 (gfc_array_i2 * const restrict retarray,
203181254a7Smrg 	gfc_array_i2 * const restrict array,
204181254a7Smrg 	const index_type * const restrict pdim,
205181254a7Smrg 	gfc_array_l1 * const restrict mask)
206181254a7Smrg {
207181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
208181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
209181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
210181254a7Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
211181254a7Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
212181254a7Smrg   GFC_INTEGER_2 * restrict dest;
213181254a7Smrg   const GFC_INTEGER_2 * restrict base;
214181254a7Smrg   const GFC_LOGICAL_1 * restrict mbase;
215181254a7Smrg   index_type rank;
216181254a7Smrg   index_type dim;
217181254a7Smrg   index_type n;
218181254a7Smrg   index_type len;
219181254a7Smrg   index_type delta;
220181254a7Smrg   index_type mdelta;
221181254a7Smrg   int mask_kind;
222181254a7Smrg 
223181254a7Smrg   if (mask == NULL)
224181254a7Smrg     {
225181254a7Smrg #ifdef HAVE_BACK_ARG
226181254a7Smrg       sum_i2 (retarray, array, pdim, back);
227181254a7Smrg #else
228181254a7Smrg       sum_i2 (retarray, array, pdim);
229181254a7Smrg #endif
230181254a7Smrg       return;
231181254a7Smrg     }
232181254a7Smrg 
233181254a7Smrg   dim = (*pdim) - 1;
234181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
235181254a7Smrg 
236181254a7Smrg 
237181254a7Smrg   if (unlikely (dim < 0 || dim > rank))
238181254a7Smrg     {
239181254a7Smrg       runtime_error ("Dim argument incorrect in SUM intrinsic: "
240181254a7Smrg  		     "is %ld, should be between 1 and %ld",
241181254a7Smrg 		     (long int) dim + 1, (long int) rank + 1);
242181254a7Smrg     }
243181254a7Smrg 
244181254a7Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
245181254a7Smrg   if (len <= 0)
246181254a7Smrg     return;
247181254a7Smrg 
248181254a7Smrg   mbase = mask->base_addr;
249181254a7Smrg 
250181254a7Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
251181254a7Smrg 
252181254a7Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
253181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
254181254a7Smrg       || mask_kind == 16
255181254a7Smrg #endif
256181254a7Smrg       )
257181254a7Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
258181254a7Smrg   else
259181254a7Smrg     runtime_error ("Funny sized logical array");
260181254a7Smrg 
261181254a7Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
262181254a7Smrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
263181254a7Smrg 
264181254a7Smrg   for (n = 0; n < dim; n++)
265181254a7Smrg     {
266181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
267181254a7Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
268181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
269181254a7Smrg 
270181254a7Smrg       if (extent[n] < 0)
271181254a7Smrg 	extent[n] = 0;
272181254a7Smrg 
273181254a7Smrg     }
274181254a7Smrg   for (n = dim; n < rank; n++)
275181254a7Smrg     {
276181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
277181254a7Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
278181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
279181254a7Smrg 
280181254a7Smrg       if (extent[n] < 0)
281181254a7Smrg 	extent[n] = 0;
282181254a7Smrg     }
283181254a7Smrg 
284181254a7Smrg   if (retarray->base_addr == NULL)
285181254a7Smrg     {
286181254a7Smrg       size_t alloc_size, str;
287181254a7Smrg 
288181254a7Smrg       for (n = 0; n < rank; n++)
289181254a7Smrg 	{
290181254a7Smrg 	  if (n == 0)
291181254a7Smrg 	    str = 1;
292181254a7Smrg 	  else
293181254a7Smrg 	    str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
294181254a7Smrg 
295181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
296181254a7Smrg 
297181254a7Smrg 	}
298181254a7Smrg 
299181254a7Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
300181254a7Smrg 
301181254a7Smrg       retarray->offset = 0;
302181254a7Smrg       retarray->dtype.rank = rank;
303181254a7Smrg 
304181254a7Smrg       if (alloc_size == 0)
305181254a7Smrg 	{
306181254a7Smrg 	  /* Make sure we have a zero-sized array.  */
307181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
308181254a7Smrg 	  return;
309181254a7Smrg 	}
310181254a7Smrg       else
311181254a7Smrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_2));
312181254a7Smrg 
313181254a7Smrg     }
314181254a7Smrg   else
315181254a7Smrg     {
316181254a7Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
317181254a7Smrg 	runtime_error ("rank of return array incorrect in SUM intrinsic");
318181254a7Smrg 
319181254a7Smrg       if (unlikely (compile_options.bounds_check))
320181254a7Smrg 	{
321181254a7Smrg 	  bounds_ifunction_return ((array_t *) retarray, extent,
322181254a7Smrg 				   "return value", "SUM");
323181254a7Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
324181254a7Smrg 	  			"MASK argument", "SUM");
325181254a7Smrg 	}
326181254a7Smrg     }
327181254a7Smrg 
328181254a7Smrg   for (n = 0; n < rank; n++)
329181254a7Smrg     {
330181254a7Smrg       count[n] = 0;
331181254a7Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
332181254a7Smrg       if (extent[n] <= 0)
333181254a7Smrg 	return;
334181254a7Smrg     }
335181254a7Smrg 
336181254a7Smrg   dest = retarray->base_addr;
337181254a7Smrg   base = array->base_addr;
338181254a7Smrg 
339181254a7Smrg   while (base)
340181254a7Smrg     {
341181254a7Smrg       const GFC_INTEGER_2 * restrict src;
342181254a7Smrg       const GFC_LOGICAL_1 * restrict msrc;
343181254a7Smrg       GFC_INTEGER_2 result;
344181254a7Smrg       src = base;
345181254a7Smrg       msrc = mbase;
346181254a7Smrg       {
347181254a7Smrg 
348181254a7Smrg   result = 0;
349181254a7Smrg 	for (n = 0; n < len; n++, src += delta, msrc += mdelta)
350181254a7Smrg 	  {
351181254a7Smrg 
352181254a7Smrg   if (*msrc)
353181254a7Smrg     result += *src;
354181254a7Smrg 	  }
355181254a7Smrg 	*dest = result;
356181254a7Smrg       }
357181254a7Smrg       /* Advance to the next element.  */
358181254a7Smrg       count[0]++;
359181254a7Smrg       base += sstride[0];
360181254a7Smrg       mbase += mstride[0];
361181254a7Smrg       dest += dstride[0];
362181254a7Smrg       n = 0;
363181254a7Smrg       while (count[n] == extent[n])
364181254a7Smrg 	{
365181254a7Smrg 	  /* When we get to the end of a dimension, reset it and increment
366181254a7Smrg 	     the next dimension.  */
367181254a7Smrg 	  count[n] = 0;
368181254a7Smrg 	  /* We could precalculate these products, but this is a less
369181254a7Smrg 	     frequently used path so probably not worth it.  */
370181254a7Smrg 	  base -= sstride[n] * extent[n];
371181254a7Smrg 	  mbase -= mstride[n] * extent[n];
372181254a7Smrg 	  dest -= dstride[n] * extent[n];
373181254a7Smrg 	  n++;
374181254a7Smrg 	  if (n >= rank)
375181254a7Smrg 	    {
376181254a7Smrg 	      /* Break out of the loop.  */
377181254a7Smrg 	      base = NULL;
378181254a7Smrg 	      break;
379181254a7Smrg 	    }
380181254a7Smrg 	  else
381181254a7Smrg 	    {
382181254a7Smrg 	      count[n]++;
383181254a7Smrg 	      base += sstride[n];
384181254a7Smrg 	      mbase += mstride[n];
385181254a7Smrg 	      dest += dstride[n];
386181254a7Smrg 	    }
387181254a7Smrg 	}
388181254a7Smrg     }
389181254a7Smrg }
390181254a7Smrg 
391181254a7Smrg 
392181254a7Smrg extern void ssum_i2 (gfc_array_i2 * const restrict,
393181254a7Smrg 	gfc_array_i2 * const restrict, const index_type * const restrict,
394181254a7Smrg 	GFC_LOGICAL_4 *);
395181254a7Smrg export_proto(ssum_i2);
396181254a7Smrg 
397181254a7Smrg void
ssum_i2(gfc_array_i2 * const restrict retarray,gfc_array_i2 * const restrict array,const index_type * const restrict pdim,GFC_LOGICAL_4 * mask)398181254a7Smrg ssum_i2 (gfc_array_i2 * const restrict retarray,
399181254a7Smrg 	gfc_array_i2 * const restrict array,
400181254a7Smrg 	const index_type * const restrict pdim,
401181254a7Smrg 	GFC_LOGICAL_4 * mask)
402181254a7Smrg {
403181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
404181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
405181254a7Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
406181254a7Smrg   GFC_INTEGER_2 * restrict dest;
407181254a7Smrg   index_type rank;
408181254a7Smrg   index_type n;
409181254a7Smrg   index_type dim;
410181254a7Smrg 
411181254a7Smrg 
412181254a7Smrg   if (mask == NULL || *mask)
413181254a7Smrg     {
414181254a7Smrg #ifdef HAVE_BACK_ARG
415181254a7Smrg       sum_i2 (retarray, array, pdim, back);
416181254a7Smrg #else
417181254a7Smrg       sum_i2 (retarray, array, pdim);
418181254a7Smrg #endif
419181254a7Smrg       return;
420181254a7Smrg     }
421181254a7Smrg   /* Make dim zero based to avoid confusion.  */
422181254a7Smrg   dim = (*pdim) - 1;
423181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
424181254a7Smrg 
425181254a7Smrg   if (unlikely (dim < 0 || dim > rank))
426181254a7Smrg     {
427181254a7Smrg       runtime_error ("Dim argument incorrect in SUM intrinsic: "
428181254a7Smrg  		     "is %ld, should be between 1 and %ld",
429181254a7Smrg 		     (long int) dim + 1, (long int) rank + 1);
430181254a7Smrg     }
431181254a7Smrg 
432181254a7Smrg   for (n = 0; n < dim; n++)
433181254a7Smrg     {
434181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
435181254a7Smrg 
436181254a7Smrg       if (extent[n] <= 0)
437181254a7Smrg 	extent[n] = 0;
438181254a7Smrg     }
439181254a7Smrg 
440181254a7Smrg   for (n = dim; n < rank; n++)
441181254a7Smrg     {
442181254a7Smrg       extent[n] =
443181254a7Smrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
444181254a7Smrg 
445181254a7Smrg       if (extent[n] <= 0)
446181254a7Smrg 	extent[n] = 0;
447181254a7Smrg     }
448181254a7Smrg 
449181254a7Smrg   if (retarray->base_addr == NULL)
450181254a7Smrg     {
451181254a7Smrg       size_t alloc_size, str;
452181254a7Smrg 
453181254a7Smrg       for (n = 0; n < rank; n++)
454181254a7Smrg 	{
455181254a7Smrg 	  if (n == 0)
456181254a7Smrg 	    str = 1;
457181254a7Smrg 	  else
458181254a7Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
459181254a7Smrg 
460181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
461181254a7Smrg 
462181254a7Smrg 	}
463181254a7Smrg 
464181254a7Smrg       retarray->offset = 0;
465181254a7Smrg       retarray->dtype.rank = rank;
466181254a7Smrg 
467181254a7Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
468181254a7Smrg 
469181254a7Smrg       if (alloc_size == 0)
470181254a7Smrg 	{
471181254a7Smrg 	  /* Make sure we have a zero-sized array.  */
472181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
473181254a7Smrg 	  return;
474181254a7Smrg 	}
475181254a7Smrg       else
476181254a7Smrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_2));
477181254a7Smrg     }
478181254a7Smrg   else
479181254a7Smrg     {
480181254a7Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
481181254a7Smrg 	runtime_error ("rank of return array incorrect in"
482181254a7Smrg 		       " SUM intrinsic: is %ld, should be %ld",
483181254a7Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
484181254a7Smrg 		       (long int) rank);
485181254a7Smrg 
486181254a7Smrg       if (unlikely (compile_options.bounds_check))
487181254a7Smrg 	{
488181254a7Smrg 	  for (n=0; n < rank; n++)
489181254a7Smrg 	    {
490181254a7Smrg 	      index_type ret_extent;
491181254a7Smrg 
492181254a7Smrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
493181254a7Smrg 	      if (extent[n] != ret_extent)
494181254a7Smrg 		runtime_error ("Incorrect extent in return value of"
495181254a7Smrg 			       " SUM intrinsic in dimension %ld:"
496181254a7Smrg 			       " is %ld, should be %ld", (long int) n + 1,
497181254a7Smrg 			       (long int) ret_extent, (long int) extent[n]);
498181254a7Smrg 	    }
499181254a7Smrg 	}
500181254a7Smrg     }
501181254a7Smrg 
502181254a7Smrg   for (n = 0; n < rank; n++)
503181254a7Smrg     {
504181254a7Smrg       count[n] = 0;
505181254a7Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
506181254a7Smrg     }
507181254a7Smrg 
508181254a7Smrg   dest = retarray->base_addr;
509181254a7Smrg 
510181254a7Smrg   while(1)
511181254a7Smrg     {
512181254a7Smrg       *dest = 0;
513181254a7Smrg       count[0]++;
514181254a7Smrg       dest += dstride[0];
515181254a7Smrg       n = 0;
516181254a7Smrg       while (count[n] == extent[n])
517181254a7Smrg 	{
518181254a7Smrg 	  /* When we get to the end of a dimension, reset it and increment
519181254a7Smrg 	     the next dimension.  */
520181254a7Smrg 	  count[n] = 0;
521181254a7Smrg 	  /* We could precalculate these products, but this is a less
522181254a7Smrg 	     frequently used path so probably not worth it.  */
523181254a7Smrg 	  dest -= dstride[n] * extent[n];
524181254a7Smrg 	  n++;
525181254a7Smrg 	  if (n >= rank)
526181254a7Smrg 	    return;
527181254a7Smrg 	  else
528181254a7Smrg 	    {
529181254a7Smrg 	      count[n]++;
530181254a7Smrg 	      dest += dstride[n];
531181254a7Smrg 	    }
532181254a7Smrg       	}
533181254a7Smrg     }
534181254a7Smrg }
535181254a7Smrg 
536181254a7Smrg #endif
537