xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/generated/findloc1_i2.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg /* Implementation of the FINDLOC intrinsic
2*4c3eb207Smrg    Copyright (C) 2018-2020 Free Software Foundation, Inc.
3627f7eb2Smrg    Contributed by Thomas König <tk@tkoenig.net>
4627f7eb2Smrg 
5627f7eb2Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
6627f7eb2Smrg 
7627f7eb2Smrg Libgfortran is free software; you can redistribute it and/or
8627f7eb2Smrg modify it under the terms of the GNU General Public
9627f7eb2Smrg License as published by the Free Software Foundation; either
10627f7eb2Smrg version 3 of the License, or (at your option) any later version.
11627f7eb2Smrg 
12627f7eb2Smrg Libgfortran is distributed in the hope that it will be useful,
13627f7eb2Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14627f7eb2Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15627f7eb2Smrg GNU General Public License for more details.
16627f7eb2Smrg 
17627f7eb2Smrg Under Section 7 of GPL version 3, you are granted additional
18627f7eb2Smrg permissions described in the GCC Runtime Library Exception, version
19627f7eb2Smrg 3.1, as published by the Free Software Foundation.
20627f7eb2Smrg 
21627f7eb2Smrg You should have received a copy of the GNU General Public License and
22627f7eb2Smrg a copy of the GCC Runtime Library Exception along with this program;
23627f7eb2Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24627f7eb2Smrg <http://www.gnu.org/licenses/>.  */
25627f7eb2Smrg 
26627f7eb2Smrg #include "libgfortran.h"
27627f7eb2Smrg #include <assert.h>
28627f7eb2Smrg 
29627f7eb2Smrg #if defined (HAVE_GFC_INTEGER_2)
30627f7eb2Smrg extern void findloc1_i2 (gfc_array_index_type * const restrict retarray,
31627f7eb2Smrg 		         gfc_array_i2 * const restrict array, GFC_INTEGER_2 value,
32627f7eb2Smrg 			 const index_type * restrict pdim, GFC_LOGICAL_4 back);
33627f7eb2Smrg export_proto(findloc1_i2);
34627f7eb2Smrg 
35627f7eb2Smrg extern void
findloc1_i2(gfc_array_index_type * const restrict retarray,gfc_array_i2 * const restrict array,GFC_INTEGER_2 value,const index_type * restrict pdim,GFC_LOGICAL_4 back)36627f7eb2Smrg findloc1_i2 (gfc_array_index_type * const restrict retarray,
37627f7eb2Smrg 	    gfc_array_i2 * const restrict array, GFC_INTEGER_2 value,
38627f7eb2Smrg 	    const index_type * restrict pdim, GFC_LOGICAL_4 back)
39627f7eb2Smrg {
40627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
41627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
42627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
43627f7eb2Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
44627f7eb2Smrg   const GFC_INTEGER_2 * restrict base;
45627f7eb2Smrg   index_type * restrict dest;
46627f7eb2Smrg   index_type rank;
47627f7eb2Smrg   index_type n;
48627f7eb2Smrg   index_type len;
49627f7eb2Smrg   index_type delta;
50627f7eb2Smrg   index_type dim;
51627f7eb2Smrg   int continue_loop;
52627f7eb2Smrg 
53627f7eb2Smrg   /* Make dim zero based to avoid confusion.  */
54627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
55627f7eb2Smrg   dim = (*pdim) - 1;
56627f7eb2Smrg 
57627f7eb2Smrg   if (unlikely (dim < 0 || dim > rank))
58627f7eb2Smrg     {
59627f7eb2Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
60627f7eb2Smrg  		     "is %ld, should be between 1 and %ld",
61627f7eb2Smrg 		     (long int) dim + 1, (long int) rank + 1);
62627f7eb2Smrg     }
63627f7eb2Smrg 
64627f7eb2Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
65627f7eb2Smrg   if (len < 0)
66627f7eb2Smrg     len = 0;
67627f7eb2Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
68627f7eb2Smrg 
69627f7eb2Smrg   for (n = 0; n < dim; n++)
70627f7eb2Smrg     {
71627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
72627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
73627f7eb2Smrg 
74627f7eb2Smrg       if (extent[n] < 0)
75627f7eb2Smrg 	extent[n] = 0;
76627f7eb2Smrg     }
77627f7eb2Smrg   for (n = dim; n < rank; n++)
78627f7eb2Smrg     {
79627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
80627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
81627f7eb2Smrg 
82627f7eb2Smrg       if (extent[n] < 0)
83627f7eb2Smrg 	extent[n] = 0;
84627f7eb2Smrg     }
85627f7eb2Smrg 
86627f7eb2Smrg   if (retarray->base_addr == NULL)
87627f7eb2Smrg     {
88627f7eb2Smrg       size_t alloc_size, str;
89627f7eb2Smrg 
90627f7eb2Smrg       for (n = 0; n < rank; n++)
91627f7eb2Smrg 	{
92627f7eb2Smrg 	  if (n == 0)
93627f7eb2Smrg 	    str = 1;
94627f7eb2Smrg 	  else
95627f7eb2Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
96627f7eb2Smrg 
97627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
98627f7eb2Smrg 
99627f7eb2Smrg 	}
100627f7eb2Smrg 
101627f7eb2Smrg       retarray->offset = 0;
102627f7eb2Smrg       retarray->dtype.rank = rank;
103627f7eb2Smrg 
104627f7eb2Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
105627f7eb2Smrg 
106627f7eb2Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
107627f7eb2Smrg       if (alloc_size == 0)
108627f7eb2Smrg 	{
109627f7eb2Smrg 	  /* Make sure we have a zero-sized array.  */
110627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
111627f7eb2Smrg 	  return;
112627f7eb2Smrg 	}
113627f7eb2Smrg     }
114627f7eb2Smrg   else
115627f7eb2Smrg     {
116627f7eb2Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
117627f7eb2Smrg 	runtime_error ("rank of return array incorrect in"
118627f7eb2Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
119627f7eb2Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
120627f7eb2Smrg 		       (long int) rank);
121627f7eb2Smrg 
122627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
123627f7eb2Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
124627f7eb2Smrg 				 "return value", "FINDLOC");
125627f7eb2Smrg     }
126627f7eb2Smrg 
127627f7eb2Smrg   for (n = 0; n < rank; n++)
128627f7eb2Smrg     {
129627f7eb2Smrg       count[n] = 0;
130627f7eb2Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
131627f7eb2Smrg       if (extent[n] <= 0)
132627f7eb2Smrg 	return;
133627f7eb2Smrg     }
134627f7eb2Smrg 
135627f7eb2Smrg   dest = retarray->base_addr;
136627f7eb2Smrg   continue_loop = 1;
137627f7eb2Smrg 
138627f7eb2Smrg   base = array->base_addr;
139627f7eb2Smrg   while (continue_loop)
140627f7eb2Smrg     {
141627f7eb2Smrg       const GFC_INTEGER_2 * restrict src;
142627f7eb2Smrg       index_type result;
143627f7eb2Smrg 
144627f7eb2Smrg       result = 0;
145627f7eb2Smrg       if (back)
146627f7eb2Smrg 	{
147627f7eb2Smrg 	  src = base + (len - 1) * delta * 1;
148627f7eb2Smrg 	  for (n = len; n > 0; n--, src -= delta * 1)
149627f7eb2Smrg 	    {
150627f7eb2Smrg 	      if (*src == value)
151627f7eb2Smrg 		{
152627f7eb2Smrg 		  result = n;
153627f7eb2Smrg 		  break;
154627f7eb2Smrg 		}
155627f7eb2Smrg 	    }
156627f7eb2Smrg 	}
157627f7eb2Smrg       else
158627f7eb2Smrg 	{
159627f7eb2Smrg 	  src = base;
160627f7eb2Smrg 	  for (n = 1; n <= len; n++, src += delta * 1)
161627f7eb2Smrg 	    {
162627f7eb2Smrg 	      if (*src == value)
163627f7eb2Smrg 		{
164627f7eb2Smrg 		  result = n;
165627f7eb2Smrg 		  break;
166627f7eb2Smrg 		}
167627f7eb2Smrg 	    }
168627f7eb2Smrg 	}
169627f7eb2Smrg       *dest = result;
170627f7eb2Smrg 
171627f7eb2Smrg       count[0]++;
172627f7eb2Smrg       base += sstride[0] * 1;
173627f7eb2Smrg       dest += dstride[0];
174627f7eb2Smrg       n = 0;
175627f7eb2Smrg       while (count[n] == extent[n])
176627f7eb2Smrg 	{
177627f7eb2Smrg 	  count[n] = 0;
178627f7eb2Smrg 	  base -= sstride[n] * extent[n] * 1;
179627f7eb2Smrg 	  dest -= dstride[n] * extent[n];
180627f7eb2Smrg 	  n++;
181627f7eb2Smrg 	  if (n >= rank)
182627f7eb2Smrg 	    {
183627f7eb2Smrg 	      continue_loop = 0;
184627f7eb2Smrg 	      break;
185627f7eb2Smrg 	    }
186627f7eb2Smrg 	  else
187627f7eb2Smrg 	    {
188627f7eb2Smrg 	      count[n]++;
189627f7eb2Smrg 	      base += sstride[n] * 1;
190627f7eb2Smrg 	      dest += dstride[n];
191627f7eb2Smrg 	    }
192627f7eb2Smrg 	}
193627f7eb2Smrg     }
194627f7eb2Smrg }
195627f7eb2Smrg extern void mfindloc1_i2 (gfc_array_index_type * const restrict retarray,
196627f7eb2Smrg 		         gfc_array_i2 * const restrict array, GFC_INTEGER_2 value,
197627f7eb2Smrg 			 const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
198627f7eb2Smrg 			 GFC_LOGICAL_4 back);
199627f7eb2Smrg export_proto(mfindloc1_i2);
200627f7eb2Smrg 
201627f7eb2Smrg extern void
mfindloc1_i2(gfc_array_index_type * const restrict retarray,gfc_array_i2 * const restrict array,GFC_INTEGER_2 value,const index_type * restrict pdim,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back)202627f7eb2Smrg mfindloc1_i2 (gfc_array_index_type * const restrict retarray,
203627f7eb2Smrg 	    gfc_array_i2 * const restrict array, GFC_INTEGER_2 value,
204627f7eb2Smrg 	    const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
205627f7eb2Smrg 	    GFC_LOGICAL_4 back)
206627f7eb2Smrg {
207627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
208627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
209627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
210627f7eb2Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
211627f7eb2Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
212627f7eb2Smrg   const GFC_INTEGER_2 * restrict base;
213627f7eb2Smrg   const GFC_LOGICAL_1 * restrict mbase;
214627f7eb2Smrg   index_type * restrict dest;
215627f7eb2Smrg   index_type rank;
216627f7eb2Smrg   index_type n;
217627f7eb2Smrg   index_type len;
218627f7eb2Smrg   index_type delta;
219627f7eb2Smrg   index_type mdelta;
220627f7eb2Smrg   index_type dim;
221627f7eb2Smrg   int mask_kind;
222627f7eb2Smrg   int continue_loop;
223627f7eb2Smrg 
224627f7eb2Smrg   /* Make dim zero based to avoid confusion.  */
225627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
226627f7eb2Smrg   dim = (*pdim) - 1;
227627f7eb2Smrg 
228627f7eb2Smrg   if (unlikely (dim < 0 || dim > rank))
229627f7eb2Smrg     {
230627f7eb2Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
231627f7eb2Smrg  		     "is %ld, should be between 1 and %ld",
232627f7eb2Smrg 		     (long int) dim + 1, (long int) rank + 1);
233627f7eb2Smrg     }
234627f7eb2Smrg 
235627f7eb2Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
236627f7eb2Smrg   if (len < 0)
237627f7eb2Smrg     len = 0;
238627f7eb2Smrg 
239627f7eb2Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
240627f7eb2Smrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
241627f7eb2Smrg 
242627f7eb2Smrg   mbase = mask->base_addr;
243627f7eb2Smrg 
244627f7eb2Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
245627f7eb2Smrg 
246627f7eb2Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
247627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
248627f7eb2Smrg       || mask_kind == 16
249627f7eb2Smrg #endif
250627f7eb2Smrg       )
251627f7eb2Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
252627f7eb2Smrg   else
253627f7eb2Smrg     internal_error (NULL, "Funny sized logical array");
254627f7eb2Smrg 
255627f7eb2Smrg   for (n = 0; n < dim; n++)
256627f7eb2Smrg     {
257627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
258627f7eb2Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
259627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
260627f7eb2Smrg 
261627f7eb2Smrg       if (extent[n] < 0)
262627f7eb2Smrg 	extent[n] = 0;
263627f7eb2Smrg     }
264627f7eb2Smrg   for (n = dim; n < rank; n++)
265627f7eb2Smrg     {
266627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
267627f7eb2Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
268627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
269627f7eb2Smrg 
270627f7eb2Smrg       if (extent[n] < 0)
271627f7eb2Smrg 	extent[n] = 0;
272627f7eb2Smrg     }
273627f7eb2Smrg 
274627f7eb2Smrg   if (retarray->base_addr == NULL)
275627f7eb2Smrg     {
276627f7eb2Smrg       size_t alloc_size, str;
277627f7eb2Smrg 
278627f7eb2Smrg       for (n = 0; n < rank; n++)
279627f7eb2Smrg 	{
280627f7eb2Smrg 	  if (n == 0)
281627f7eb2Smrg 	    str = 1;
282627f7eb2Smrg 	  else
283627f7eb2Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
284627f7eb2Smrg 
285627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
286627f7eb2Smrg 
287627f7eb2Smrg 	}
288627f7eb2Smrg 
289627f7eb2Smrg       retarray->offset = 0;
290627f7eb2Smrg       retarray->dtype.rank = rank;
291627f7eb2Smrg 
292627f7eb2Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
293627f7eb2Smrg 
294627f7eb2Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
295627f7eb2Smrg       if (alloc_size == 0)
296627f7eb2Smrg 	{
297627f7eb2Smrg 	  /* Make sure we have a zero-sized array.  */
298627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
299627f7eb2Smrg 	  return;
300627f7eb2Smrg 	}
301627f7eb2Smrg     }
302627f7eb2Smrg   else
303627f7eb2Smrg     {
304627f7eb2Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
305627f7eb2Smrg 	runtime_error ("rank of return array incorrect in"
306627f7eb2Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
307627f7eb2Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
308627f7eb2Smrg 		       (long int) rank);
309627f7eb2Smrg 
310627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
311627f7eb2Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
312627f7eb2Smrg 				 "return value", "FINDLOC");
313627f7eb2Smrg     }
314627f7eb2Smrg 
315627f7eb2Smrg   for (n = 0; n < rank; n++)
316627f7eb2Smrg     {
317627f7eb2Smrg       count[n] = 0;
318627f7eb2Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
319627f7eb2Smrg       if (extent[n] <= 0)
320627f7eb2Smrg 	return;
321627f7eb2Smrg     }
322627f7eb2Smrg 
323627f7eb2Smrg   dest = retarray->base_addr;
324627f7eb2Smrg   continue_loop = 1;
325627f7eb2Smrg 
326627f7eb2Smrg   base = array->base_addr;
327627f7eb2Smrg   while (continue_loop)
328627f7eb2Smrg     {
329627f7eb2Smrg       const GFC_INTEGER_2 * restrict src;
330627f7eb2Smrg       const GFC_LOGICAL_1 * restrict msrc;
331627f7eb2Smrg       index_type result;
332627f7eb2Smrg 
333627f7eb2Smrg       result = 0;
334627f7eb2Smrg       if (back)
335627f7eb2Smrg 	{
336627f7eb2Smrg 	  src = base + (len - 1) * delta * 1;
337627f7eb2Smrg 	  msrc = mbase + (len - 1) * mdelta;
338627f7eb2Smrg 	  for (n = len; n > 0; n--, src -= delta * 1, msrc -= mdelta)
339627f7eb2Smrg 	    {
340627f7eb2Smrg 	      if (*msrc && *src == value)
341627f7eb2Smrg 		{
342627f7eb2Smrg 		  result = n;
343627f7eb2Smrg 		  break;
344627f7eb2Smrg 		}
345627f7eb2Smrg 	    }
346627f7eb2Smrg 	}
347627f7eb2Smrg       else
348627f7eb2Smrg 	{
349627f7eb2Smrg 	  src = base;
350627f7eb2Smrg 	  msrc = mbase;
351627f7eb2Smrg 	  for (n = 1; n <= len; n++, src += delta * 1, msrc += mdelta)
352627f7eb2Smrg 	    {
353627f7eb2Smrg 	      if (*msrc && *src == value)
354627f7eb2Smrg 		{
355627f7eb2Smrg 		  result = n;
356627f7eb2Smrg 		  break;
357627f7eb2Smrg 		}
358627f7eb2Smrg 	    }
359627f7eb2Smrg 	}
360627f7eb2Smrg       *dest = result;
361627f7eb2Smrg 
362627f7eb2Smrg       count[0]++;
363627f7eb2Smrg       base += sstride[0] * 1;
364627f7eb2Smrg       mbase += mstride[0];
365627f7eb2Smrg       dest += dstride[0];
366627f7eb2Smrg       n = 0;
367627f7eb2Smrg       while (count[n] == extent[n])
368627f7eb2Smrg 	{
369627f7eb2Smrg 	  count[n] = 0;
370627f7eb2Smrg 	  base -= sstride[n] * extent[n] * 1;
371627f7eb2Smrg 	  mbase -= mstride[n] * extent[n];
372627f7eb2Smrg 	  dest -= dstride[n] * extent[n];
373627f7eb2Smrg 	  n++;
374627f7eb2Smrg 	  if (n >= rank)
375627f7eb2Smrg 	    {
376627f7eb2Smrg 	      continue_loop = 0;
377627f7eb2Smrg 	      break;
378627f7eb2Smrg 	    }
379627f7eb2Smrg 	  else
380627f7eb2Smrg 	    {
381627f7eb2Smrg 	      count[n]++;
382627f7eb2Smrg 	      base += sstride[n] * 1;
383627f7eb2Smrg 	      dest += dstride[n];
384627f7eb2Smrg 	    }
385627f7eb2Smrg 	}
386627f7eb2Smrg     }
387627f7eb2Smrg }
388627f7eb2Smrg extern void sfindloc1_i2 (gfc_array_index_type * const restrict retarray,
389627f7eb2Smrg 		         gfc_array_i2 * const restrict array, GFC_INTEGER_2 value,
390627f7eb2Smrg 			 const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
391627f7eb2Smrg 			 GFC_LOGICAL_4 back);
392627f7eb2Smrg export_proto(sfindloc1_i2);
393627f7eb2Smrg 
394627f7eb2Smrg extern void
sfindloc1_i2(gfc_array_index_type * const restrict retarray,gfc_array_i2 * const restrict array,GFC_INTEGER_2 value,const index_type * restrict pdim,GFC_LOGICAL_4 * const restrict mask,GFC_LOGICAL_4 back)395627f7eb2Smrg sfindloc1_i2 (gfc_array_index_type * const restrict retarray,
396627f7eb2Smrg 	    gfc_array_i2 * const restrict array, GFC_INTEGER_2 value,
397627f7eb2Smrg 	    const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict  mask,
398627f7eb2Smrg 	    GFC_LOGICAL_4 back)
399627f7eb2Smrg {
400627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
401627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
402627f7eb2Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
403627f7eb2Smrg   index_type * restrict dest;
404627f7eb2Smrg   index_type rank;
405627f7eb2Smrg   index_type n;
406627f7eb2Smrg   index_type len;
407627f7eb2Smrg   index_type dim;
408627f7eb2Smrg   bool continue_loop;
409627f7eb2Smrg 
410627f7eb2Smrg   if (mask == NULL || *mask)
411627f7eb2Smrg     {
412627f7eb2Smrg       findloc1_i2 (retarray, array, value, pdim, back);
413627f7eb2Smrg       return;
414627f7eb2Smrg     }
415627f7eb2Smrg     /* Make dim zero based to avoid confusion.  */
416627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
417627f7eb2Smrg   dim = (*pdim) - 1;
418627f7eb2Smrg 
419627f7eb2Smrg   if (unlikely (dim < 0 || dim > rank))
420627f7eb2Smrg     {
421627f7eb2Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
422627f7eb2Smrg  		     "is %ld, should be between 1 and %ld",
423627f7eb2Smrg 		     (long int) dim + 1, (long int) rank + 1);
424627f7eb2Smrg     }
425627f7eb2Smrg 
426627f7eb2Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
427627f7eb2Smrg   if (len < 0)
428627f7eb2Smrg     len = 0;
429627f7eb2Smrg 
430627f7eb2Smrg   for (n = 0; n < dim; n++)
431627f7eb2Smrg     {
432627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
433627f7eb2Smrg 
434627f7eb2Smrg       if (extent[n] <= 0)
435627f7eb2Smrg 	extent[n] = 0;
436627f7eb2Smrg     }
437627f7eb2Smrg 
438627f7eb2Smrg   for (n = dim; n < rank; n++)
439627f7eb2Smrg     {
440627f7eb2Smrg       extent[n] =
441627f7eb2Smrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
442627f7eb2Smrg 
443627f7eb2Smrg       if (extent[n] <= 0)
444627f7eb2Smrg 	extent[n] = 0;
445627f7eb2Smrg     }
446627f7eb2Smrg 
447627f7eb2Smrg 
448627f7eb2Smrg   if (retarray->base_addr == NULL)
449627f7eb2Smrg     {
450627f7eb2Smrg       size_t alloc_size, str;
451627f7eb2Smrg 
452627f7eb2Smrg       for (n = 0; n < rank; n++)
453627f7eb2Smrg 	{
454627f7eb2Smrg 	  if (n == 0)
455627f7eb2Smrg 	    str = 1;
456627f7eb2Smrg 	  else
457627f7eb2Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
458627f7eb2Smrg 
459627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
460627f7eb2Smrg 	}
461627f7eb2Smrg 
462627f7eb2Smrg       retarray->offset = 0;
463627f7eb2Smrg       retarray->dtype.rank = rank;
464627f7eb2Smrg 
465627f7eb2Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
466627f7eb2Smrg 
467627f7eb2Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
468627f7eb2Smrg       if (alloc_size == 0)
469627f7eb2Smrg 	{
470627f7eb2Smrg 	  /* Make sure we have a zero-sized array.  */
471627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
472627f7eb2Smrg 	  return;
473627f7eb2Smrg 	}
474627f7eb2Smrg     }
475627f7eb2Smrg   else
476627f7eb2Smrg     {
477627f7eb2Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
478627f7eb2Smrg 	runtime_error ("rank of return array incorrect in"
479627f7eb2Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
480627f7eb2Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
481627f7eb2Smrg 		       (long int) rank);
482627f7eb2Smrg 
483627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
484627f7eb2Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
485627f7eb2Smrg 				 "return value", "FINDLOC");
486627f7eb2Smrg     }
487627f7eb2Smrg 
488627f7eb2Smrg   for (n = 0; n < rank; n++)
489627f7eb2Smrg     {
490627f7eb2Smrg       count[n] = 0;
491627f7eb2Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
492627f7eb2Smrg       if (extent[n] <= 0)
493627f7eb2Smrg 	return;
494627f7eb2Smrg     }
495627f7eb2Smrg   dest = retarray->base_addr;
496627f7eb2Smrg   continue_loop = 1;
497627f7eb2Smrg 
498627f7eb2Smrg   while (continue_loop)
499627f7eb2Smrg     {
500627f7eb2Smrg       *dest = 0;
501627f7eb2Smrg 
502627f7eb2Smrg       count[0]++;
503627f7eb2Smrg       dest += dstride[0];
504627f7eb2Smrg       n = 0;
505627f7eb2Smrg       while (count[n] == extent[n])
506627f7eb2Smrg 	{
507627f7eb2Smrg 	  count[n] = 0;
508627f7eb2Smrg 	  dest -= dstride[n] * extent[n];
509627f7eb2Smrg 	  n++;
510627f7eb2Smrg 	  if (n >= rank)
511627f7eb2Smrg 	    {
512627f7eb2Smrg 	      continue_loop = 0;
513627f7eb2Smrg 	      break;
514627f7eb2Smrg 	    }
515627f7eb2Smrg 	  else
516627f7eb2Smrg 	    {
517627f7eb2Smrg 	      count[n]++;
518627f7eb2Smrg 	      dest += dstride[n];
519627f7eb2Smrg 	    }
520627f7eb2Smrg 	}
521627f7eb2Smrg     }
522627f7eb2Smrg }
523627f7eb2Smrg #endif
524