xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/findloc1_c4.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1181254a7Smrg /* Implementation of the FINDLOC intrinsic
2*b1e83836Smrg    Copyright (C) 2018-2022 Free Software Foundation, Inc.
3181254a7Smrg    Contributed by Thomas König <tk@tkoenig.net>
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 #include <assert.h>
28181254a7Smrg 
29181254a7Smrg #if defined (HAVE_GFC_COMPLEX_4)
30181254a7Smrg extern void findloc1_c4 (gfc_array_index_type * const restrict retarray,
31181254a7Smrg 		         gfc_array_c4 * const restrict array, GFC_COMPLEX_4 value,
32181254a7Smrg 			 const index_type * restrict pdim, GFC_LOGICAL_4 back);
33181254a7Smrg export_proto(findloc1_c4);
34181254a7Smrg 
35181254a7Smrg extern void
findloc1_c4(gfc_array_index_type * const restrict retarray,gfc_array_c4 * const restrict array,GFC_COMPLEX_4 value,const index_type * restrict pdim,GFC_LOGICAL_4 back)36181254a7Smrg findloc1_c4 (gfc_array_index_type * const restrict retarray,
37181254a7Smrg 	    gfc_array_c4 * const restrict array, GFC_COMPLEX_4 value,
38181254a7Smrg 	    const index_type * restrict pdim, GFC_LOGICAL_4 back)
39181254a7Smrg {
40181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
41181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
42181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
43181254a7Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
44181254a7Smrg   const GFC_COMPLEX_4 * restrict base;
45181254a7Smrg   index_type * restrict dest;
46181254a7Smrg   index_type rank;
47181254a7Smrg   index_type n;
48181254a7Smrg   index_type len;
49181254a7Smrg   index_type delta;
50181254a7Smrg   index_type dim;
51181254a7Smrg   int continue_loop;
52181254a7Smrg 
53181254a7Smrg   /* Make dim zero based to avoid confusion.  */
54181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
55181254a7Smrg   dim = (*pdim) - 1;
56181254a7Smrg 
57181254a7Smrg   if (unlikely (dim < 0 || dim > rank))
58181254a7Smrg     {
59181254a7Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
60181254a7Smrg  		     "is %ld, should be between 1 and %ld",
61181254a7Smrg 		     (long int) dim + 1, (long int) rank + 1);
62181254a7Smrg     }
63181254a7Smrg 
64181254a7Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
65181254a7Smrg   if (len < 0)
66181254a7Smrg     len = 0;
67181254a7Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
68181254a7Smrg 
69181254a7Smrg   for (n = 0; n < dim; n++)
70181254a7Smrg     {
71181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
72181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
73181254a7Smrg 
74181254a7Smrg       if (extent[n] < 0)
75181254a7Smrg 	extent[n] = 0;
76181254a7Smrg     }
77181254a7Smrg   for (n = dim; n < rank; n++)
78181254a7Smrg     {
79181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
80181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
81181254a7Smrg 
82181254a7Smrg       if (extent[n] < 0)
83181254a7Smrg 	extent[n] = 0;
84181254a7Smrg     }
85181254a7Smrg 
86181254a7Smrg   if (retarray->base_addr == NULL)
87181254a7Smrg     {
88181254a7Smrg       size_t alloc_size, str;
89181254a7Smrg 
90181254a7Smrg       for (n = 0; n < rank; n++)
91181254a7Smrg 	{
92181254a7Smrg 	  if (n == 0)
93181254a7Smrg 	    str = 1;
94181254a7Smrg 	  else
95181254a7Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
96181254a7Smrg 
97181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
98181254a7Smrg 
99181254a7Smrg 	}
100181254a7Smrg 
101181254a7Smrg       retarray->offset = 0;
102181254a7Smrg       retarray->dtype.rank = rank;
103181254a7Smrg 
104181254a7Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
105181254a7Smrg 
106181254a7Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
107181254a7Smrg       if (alloc_size == 0)
108181254a7Smrg 	{
109181254a7Smrg 	  /* Make sure we have a zero-sized array.  */
110181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
111181254a7Smrg 	  return;
112181254a7Smrg 	}
113181254a7Smrg     }
114181254a7Smrg   else
115181254a7Smrg     {
116181254a7Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
117181254a7Smrg 	runtime_error ("rank of return array incorrect in"
118181254a7Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
119181254a7Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
120181254a7Smrg 		       (long int) rank);
121181254a7Smrg 
122181254a7Smrg       if (unlikely (compile_options.bounds_check))
123181254a7Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
124181254a7Smrg 				 "return value", "FINDLOC");
125181254a7Smrg     }
126181254a7Smrg 
127181254a7Smrg   for (n = 0; n < rank; n++)
128181254a7Smrg     {
129181254a7Smrg       count[n] = 0;
130181254a7Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
131181254a7Smrg       if (extent[n] <= 0)
132181254a7Smrg 	return;
133181254a7Smrg     }
134181254a7Smrg 
135181254a7Smrg   dest = retarray->base_addr;
136181254a7Smrg   continue_loop = 1;
137181254a7Smrg 
138181254a7Smrg   base = array->base_addr;
139181254a7Smrg   while (continue_loop)
140181254a7Smrg     {
141181254a7Smrg       const GFC_COMPLEX_4 * restrict src;
142181254a7Smrg       index_type result;
143181254a7Smrg 
144181254a7Smrg       result = 0;
145181254a7Smrg       if (back)
146181254a7Smrg 	{
147181254a7Smrg 	  src = base + (len - 1) * delta * 1;
148181254a7Smrg 	  for (n = len; n > 0; n--, src -= delta * 1)
149181254a7Smrg 	    {
150181254a7Smrg 	      if (*src == value)
151181254a7Smrg 		{
152181254a7Smrg 		  result = n;
153181254a7Smrg 		  break;
154181254a7Smrg 		}
155181254a7Smrg 	    }
156181254a7Smrg 	}
157181254a7Smrg       else
158181254a7Smrg 	{
159181254a7Smrg 	  src = base;
160181254a7Smrg 	  for (n = 1; n <= len; n++, src += delta * 1)
161181254a7Smrg 	    {
162181254a7Smrg 	      if (*src == value)
163181254a7Smrg 		{
164181254a7Smrg 		  result = n;
165181254a7Smrg 		  break;
166181254a7Smrg 		}
167181254a7Smrg 	    }
168181254a7Smrg 	}
169181254a7Smrg       *dest = result;
170181254a7Smrg 
171181254a7Smrg       count[0]++;
172181254a7Smrg       base += sstride[0] * 1;
173181254a7Smrg       dest += dstride[0];
174181254a7Smrg       n = 0;
175181254a7Smrg       while (count[n] == extent[n])
176181254a7Smrg 	{
177181254a7Smrg 	  count[n] = 0;
178181254a7Smrg 	  base -= sstride[n] * extent[n] * 1;
179181254a7Smrg 	  dest -= dstride[n] * extent[n];
180181254a7Smrg 	  n++;
181181254a7Smrg 	  if (n >= rank)
182181254a7Smrg 	    {
183181254a7Smrg 	      continue_loop = 0;
184181254a7Smrg 	      break;
185181254a7Smrg 	    }
186181254a7Smrg 	  else
187181254a7Smrg 	    {
188181254a7Smrg 	      count[n]++;
189181254a7Smrg 	      base += sstride[n] * 1;
190181254a7Smrg 	      dest += dstride[n];
191181254a7Smrg 	    }
192181254a7Smrg 	}
193181254a7Smrg     }
194181254a7Smrg }
195181254a7Smrg extern void mfindloc1_c4 (gfc_array_index_type * const restrict retarray,
196181254a7Smrg 		         gfc_array_c4 * const restrict array, GFC_COMPLEX_4 value,
197181254a7Smrg 			 const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
198181254a7Smrg 			 GFC_LOGICAL_4 back);
199181254a7Smrg export_proto(mfindloc1_c4);
200181254a7Smrg 
201181254a7Smrg extern void
mfindloc1_c4(gfc_array_index_type * const restrict retarray,gfc_array_c4 * const restrict array,GFC_COMPLEX_4 value,const index_type * restrict pdim,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back)202181254a7Smrg mfindloc1_c4 (gfc_array_index_type * const restrict retarray,
203181254a7Smrg 	    gfc_array_c4 * const restrict array, GFC_COMPLEX_4 value,
204181254a7Smrg 	    const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
205181254a7Smrg 	    GFC_LOGICAL_4 back)
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 mstride[GFC_MAX_DIMENSIONS];
211181254a7Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
212181254a7Smrg   const GFC_COMPLEX_4 * restrict base;
213181254a7Smrg   const GFC_LOGICAL_1 * restrict mbase;
214181254a7Smrg   index_type * restrict dest;
215181254a7Smrg   index_type rank;
216181254a7Smrg   index_type n;
217181254a7Smrg   index_type len;
218181254a7Smrg   index_type delta;
219181254a7Smrg   index_type mdelta;
220181254a7Smrg   index_type dim;
221181254a7Smrg   int mask_kind;
222181254a7Smrg   int continue_loop;
223181254a7Smrg 
224181254a7Smrg   /* Make dim zero based to avoid confusion.  */
225181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
226181254a7Smrg   dim = (*pdim) - 1;
227181254a7Smrg 
228181254a7Smrg   if (unlikely (dim < 0 || dim > rank))
229181254a7Smrg     {
230181254a7Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
231181254a7Smrg  		     "is %ld, should be between 1 and %ld",
232181254a7Smrg 		     (long int) dim + 1, (long int) rank + 1);
233181254a7Smrg     }
234181254a7Smrg 
235181254a7Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
236181254a7Smrg   if (len < 0)
237181254a7Smrg     len = 0;
238181254a7Smrg 
239181254a7Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
240181254a7Smrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
241181254a7Smrg 
242181254a7Smrg   mbase = mask->base_addr;
243181254a7Smrg 
244181254a7Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
245181254a7Smrg 
246181254a7Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
247181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
248181254a7Smrg       || mask_kind == 16
249181254a7Smrg #endif
250181254a7Smrg       )
251181254a7Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
252181254a7Smrg   else
253181254a7Smrg     internal_error (NULL, "Funny sized logical array");
254181254a7Smrg 
255181254a7Smrg   for (n = 0; n < dim; n++)
256181254a7Smrg     {
257181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
258181254a7Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
259181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
260181254a7Smrg 
261181254a7Smrg       if (extent[n] < 0)
262181254a7Smrg 	extent[n] = 0;
263181254a7Smrg     }
264181254a7Smrg   for (n = dim; n < rank; n++)
265181254a7Smrg     {
266181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
267181254a7Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
268181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
269181254a7Smrg 
270181254a7Smrg       if (extent[n] < 0)
271181254a7Smrg 	extent[n] = 0;
272181254a7Smrg     }
273181254a7Smrg 
274181254a7Smrg   if (retarray->base_addr == NULL)
275181254a7Smrg     {
276181254a7Smrg       size_t alloc_size, str;
277181254a7Smrg 
278181254a7Smrg       for (n = 0; n < rank; n++)
279181254a7Smrg 	{
280181254a7Smrg 	  if (n == 0)
281181254a7Smrg 	    str = 1;
282181254a7Smrg 	  else
283181254a7Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
284181254a7Smrg 
285181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
286181254a7Smrg 
287181254a7Smrg 	}
288181254a7Smrg 
289181254a7Smrg       retarray->offset = 0;
290181254a7Smrg       retarray->dtype.rank = rank;
291181254a7Smrg 
292181254a7Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
293181254a7Smrg 
294181254a7Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
295181254a7Smrg       if (alloc_size == 0)
296181254a7Smrg 	{
297181254a7Smrg 	  /* Make sure we have a zero-sized array.  */
298181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
299181254a7Smrg 	  return;
300181254a7Smrg 	}
301181254a7Smrg     }
302181254a7Smrg   else
303181254a7Smrg     {
304181254a7Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
305181254a7Smrg 	runtime_error ("rank of return array incorrect in"
306181254a7Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
307181254a7Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
308181254a7Smrg 		       (long int) rank);
309181254a7Smrg 
310181254a7Smrg       if (unlikely (compile_options.bounds_check))
311181254a7Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
312181254a7Smrg 				 "return value", "FINDLOC");
313181254a7Smrg     }
314181254a7Smrg 
315181254a7Smrg   for (n = 0; n < rank; n++)
316181254a7Smrg     {
317181254a7Smrg       count[n] = 0;
318181254a7Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
319181254a7Smrg       if (extent[n] <= 0)
320181254a7Smrg 	return;
321181254a7Smrg     }
322181254a7Smrg 
323181254a7Smrg   dest = retarray->base_addr;
324181254a7Smrg   continue_loop = 1;
325181254a7Smrg 
326181254a7Smrg   base = array->base_addr;
327181254a7Smrg   while (continue_loop)
328181254a7Smrg     {
329181254a7Smrg       const GFC_COMPLEX_4 * restrict src;
330181254a7Smrg       const GFC_LOGICAL_1 * restrict msrc;
331181254a7Smrg       index_type result;
332181254a7Smrg 
333181254a7Smrg       result = 0;
334181254a7Smrg       if (back)
335181254a7Smrg 	{
336181254a7Smrg 	  src = base + (len - 1) * delta * 1;
337181254a7Smrg 	  msrc = mbase + (len - 1) * mdelta;
338181254a7Smrg 	  for (n = len; n > 0; n--, src -= delta * 1, msrc -= mdelta)
339181254a7Smrg 	    {
340181254a7Smrg 	      if (*msrc && *src == value)
341181254a7Smrg 		{
342181254a7Smrg 		  result = n;
343181254a7Smrg 		  break;
344181254a7Smrg 		}
345181254a7Smrg 	    }
346181254a7Smrg 	}
347181254a7Smrg       else
348181254a7Smrg 	{
349181254a7Smrg 	  src = base;
350181254a7Smrg 	  msrc = mbase;
351181254a7Smrg 	  for (n = 1; n <= len; n++, src += delta * 1, msrc += mdelta)
352181254a7Smrg 	    {
353181254a7Smrg 	      if (*msrc && *src == value)
354181254a7Smrg 		{
355181254a7Smrg 		  result = n;
356181254a7Smrg 		  break;
357181254a7Smrg 		}
358181254a7Smrg 	    }
359181254a7Smrg 	}
360181254a7Smrg       *dest = result;
361181254a7Smrg 
362181254a7Smrg       count[0]++;
363181254a7Smrg       base += sstride[0] * 1;
364181254a7Smrg       mbase += mstride[0];
365181254a7Smrg       dest += dstride[0];
366181254a7Smrg       n = 0;
367181254a7Smrg       while (count[n] == extent[n])
368181254a7Smrg 	{
369181254a7Smrg 	  count[n] = 0;
370181254a7Smrg 	  base -= sstride[n] * extent[n] * 1;
371181254a7Smrg 	  mbase -= mstride[n] * extent[n];
372181254a7Smrg 	  dest -= dstride[n] * extent[n];
373181254a7Smrg 	  n++;
374181254a7Smrg 	  if (n >= rank)
375181254a7Smrg 	    {
376181254a7Smrg 	      continue_loop = 0;
377181254a7Smrg 	      break;
378181254a7Smrg 	    }
379181254a7Smrg 	  else
380181254a7Smrg 	    {
381181254a7Smrg 	      count[n]++;
382181254a7Smrg 	      base += sstride[n] * 1;
383181254a7Smrg 	      dest += dstride[n];
384181254a7Smrg 	    }
385181254a7Smrg 	}
386181254a7Smrg     }
387181254a7Smrg }
388181254a7Smrg extern void sfindloc1_c4 (gfc_array_index_type * const restrict retarray,
389181254a7Smrg 		         gfc_array_c4 * const restrict array, GFC_COMPLEX_4 value,
390181254a7Smrg 			 const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
391181254a7Smrg 			 GFC_LOGICAL_4 back);
392181254a7Smrg export_proto(sfindloc1_c4);
393181254a7Smrg 
394181254a7Smrg extern void
sfindloc1_c4(gfc_array_index_type * const restrict retarray,gfc_array_c4 * const restrict array,GFC_COMPLEX_4 value,const index_type * restrict pdim,GFC_LOGICAL_4 * const restrict mask,GFC_LOGICAL_4 back)395181254a7Smrg sfindloc1_c4 (gfc_array_index_type * const restrict retarray,
396181254a7Smrg 	    gfc_array_c4 * const restrict array, GFC_COMPLEX_4 value,
397181254a7Smrg 	    const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict  mask,
398181254a7Smrg 	    GFC_LOGICAL_4 back)
399181254a7Smrg {
400181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
401181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
402181254a7Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
403181254a7Smrg   index_type * restrict dest;
404181254a7Smrg   index_type rank;
405181254a7Smrg   index_type n;
406181254a7Smrg   index_type len;
407181254a7Smrg   index_type dim;
408181254a7Smrg   bool continue_loop;
409181254a7Smrg 
410181254a7Smrg   if (mask == NULL || *mask)
411181254a7Smrg     {
412181254a7Smrg       findloc1_c4 (retarray, array, value, pdim, back);
413181254a7Smrg       return;
414181254a7Smrg     }
415181254a7Smrg     /* Make dim zero based to avoid confusion.  */
416181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
417181254a7Smrg   dim = (*pdim) - 1;
418181254a7Smrg 
419181254a7Smrg   if (unlikely (dim < 0 || dim > rank))
420181254a7Smrg     {
421181254a7Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
422181254a7Smrg  		     "is %ld, should be between 1 and %ld",
423181254a7Smrg 		     (long int) dim + 1, (long int) rank + 1);
424181254a7Smrg     }
425181254a7Smrg 
426181254a7Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
427181254a7Smrg   if (len < 0)
428181254a7Smrg     len = 0;
429181254a7Smrg 
430181254a7Smrg   for (n = 0; n < dim; n++)
431181254a7Smrg     {
432181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
433181254a7Smrg 
434181254a7Smrg       if (extent[n] <= 0)
435181254a7Smrg 	extent[n] = 0;
436181254a7Smrg     }
437181254a7Smrg 
438181254a7Smrg   for (n = dim; n < rank; n++)
439181254a7Smrg     {
440181254a7Smrg       extent[n] =
441181254a7Smrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
442181254a7Smrg 
443181254a7Smrg       if (extent[n] <= 0)
444181254a7Smrg 	extent[n] = 0;
445181254a7Smrg     }
446181254a7Smrg 
447181254a7Smrg 
448181254a7Smrg   if (retarray->base_addr == NULL)
449181254a7Smrg     {
450181254a7Smrg       size_t alloc_size, str;
451181254a7Smrg 
452181254a7Smrg       for (n = 0; n < rank; n++)
453181254a7Smrg 	{
454181254a7Smrg 	  if (n == 0)
455181254a7Smrg 	    str = 1;
456181254a7Smrg 	  else
457181254a7Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
458181254a7Smrg 
459181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
460181254a7Smrg 	}
461181254a7Smrg 
462181254a7Smrg       retarray->offset = 0;
463181254a7Smrg       retarray->dtype.rank = rank;
464181254a7Smrg 
465181254a7Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
466181254a7Smrg 
467181254a7Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
468181254a7Smrg       if (alloc_size == 0)
469181254a7Smrg 	{
470181254a7Smrg 	  /* Make sure we have a zero-sized array.  */
471181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
472181254a7Smrg 	  return;
473181254a7Smrg 	}
474181254a7Smrg     }
475181254a7Smrg   else
476181254a7Smrg     {
477181254a7Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
478181254a7Smrg 	runtime_error ("rank of return array incorrect in"
479181254a7Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
480181254a7Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
481181254a7Smrg 		       (long int) rank);
482181254a7Smrg 
483181254a7Smrg       if (unlikely (compile_options.bounds_check))
484181254a7Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
485181254a7Smrg 				 "return value", "FINDLOC");
486181254a7Smrg     }
487181254a7Smrg 
488181254a7Smrg   for (n = 0; n < rank; n++)
489181254a7Smrg     {
490181254a7Smrg       count[n] = 0;
491181254a7Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
492181254a7Smrg       if (extent[n] <= 0)
493181254a7Smrg 	return;
494181254a7Smrg     }
495181254a7Smrg   dest = retarray->base_addr;
496181254a7Smrg   continue_loop = 1;
497181254a7Smrg 
498181254a7Smrg   while (continue_loop)
499181254a7Smrg     {
500181254a7Smrg       *dest = 0;
501181254a7Smrg 
502181254a7Smrg       count[0]++;
503181254a7Smrg       dest += dstride[0];
504181254a7Smrg       n = 0;
505181254a7Smrg       while (count[n] == extent[n])
506181254a7Smrg 	{
507181254a7Smrg 	  count[n] = 0;
508181254a7Smrg 	  dest -= dstride[n] * extent[n];
509181254a7Smrg 	  n++;
510181254a7Smrg 	  if (n >= rank)
511181254a7Smrg 	    {
512181254a7Smrg 	      continue_loop = 0;
513181254a7Smrg 	      break;
514181254a7Smrg 	    }
515181254a7Smrg 	  else
516181254a7Smrg 	    {
517181254a7Smrg 	      count[n]++;
518181254a7Smrg 	      dest += dstride[n];
519181254a7Smrg 	    }
520181254a7Smrg 	}
521181254a7Smrg     }
522181254a7Smrg }
523181254a7Smrg #endif
524