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