xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/generated/findloc1_s4.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_UINTEGER_4)
30627f7eb2Smrg extern void findloc1_s4 (gfc_array_index_type * const restrict retarray,
31627f7eb2Smrg 		         gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
32627f7eb2Smrg 			 const index_type * restrict pdim, GFC_LOGICAL_4 back,
33627f7eb2Smrg 			 gfc_charlen_type len_array, gfc_charlen_type len_value);
34627f7eb2Smrg export_proto(findloc1_s4);
35627f7eb2Smrg 
36627f7eb2Smrg extern void
findloc1_s4(gfc_array_index_type * const restrict retarray,gfc_array_s4 * const restrict array,GFC_UINTEGER_4 * const restrict value,const index_type * restrict pdim,GFC_LOGICAL_4 back,gfc_charlen_type len_array,gfc_charlen_type len_value)37627f7eb2Smrg findloc1_s4 (gfc_array_index_type * const restrict retarray,
38627f7eb2Smrg 	    gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
39627f7eb2Smrg 	    const index_type * restrict pdim, GFC_LOGICAL_4 back,
40627f7eb2Smrg 	    gfc_charlen_type len_array, gfc_charlen_type len_value)
41627f7eb2Smrg {
42627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
43627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
44627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
45627f7eb2Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
46627f7eb2Smrg   const GFC_UINTEGER_4 * restrict base;
47627f7eb2Smrg   index_type * restrict dest;
48627f7eb2Smrg   index_type rank;
49627f7eb2Smrg   index_type n;
50627f7eb2Smrg   index_type len;
51627f7eb2Smrg   index_type delta;
52627f7eb2Smrg   index_type dim;
53627f7eb2Smrg   int continue_loop;
54627f7eb2Smrg 
55627f7eb2Smrg   /* Make dim zero based to avoid confusion.  */
56627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
57627f7eb2Smrg   dim = (*pdim) - 1;
58627f7eb2Smrg 
59627f7eb2Smrg   if (unlikely (dim < 0 || dim > rank))
60627f7eb2Smrg     {
61627f7eb2Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
62627f7eb2Smrg  		     "is %ld, should be between 1 and %ld",
63627f7eb2Smrg 		     (long int) dim + 1, (long int) rank + 1);
64627f7eb2Smrg     }
65627f7eb2Smrg 
66627f7eb2Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
67627f7eb2Smrg   if (len < 0)
68627f7eb2Smrg     len = 0;
69627f7eb2Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
70627f7eb2Smrg 
71627f7eb2Smrg   for (n = 0; n < dim; n++)
72627f7eb2Smrg     {
73627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
74627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
75627f7eb2Smrg 
76627f7eb2Smrg       if (extent[n] < 0)
77627f7eb2Smrg 	extent[n] = 0;
78627f7eb2Smrg     }
79627f7eb2Smrg   for (n = dim; n < rank; n++)
80627f7eb2Smrg     {
81627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
82627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
83627f7eb2Smrg 
84627f7eb2Smrg       if (extent[n] < 0)
85627f7eb2Smrg 	extent[n] = 0;
86627f7eb2Smrg     }
87627f7eb2Smrg 
88627f7eb2Smrg   if (retarray->base_addr == NULL)
89627f7eb2Smrg     {
90627f7eb2Smrg       size_t alloc_size, str;
91627f7eb2Smrg 
92627f7eb2Smrg       for (n = 0; n < rank; n++)
93627f7eb2Smrg 	{
94627f7eb2Smrg 	  if (n == 0)
95627f7eb2Smrg 	    str = 1;
96627f7eb2Smrg 	  else
97627f7eb2Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
98627f7eb2Smrg 
99627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
100627f7eb2Smrg 
101627f7eb2Smrg 	}
102627f7eb2Smrg 
103627f7eb2Smrg       retarray->offset = 0;
104627f7eb2Smrg       retarray->dtype.rank = rank;
105627f7eb2Smrg 
106627f7eb2Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
107627f7eb2Smrg 
108627f7eb2Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
109627f7eb2Smrg       if (alloc_size == 0)
110627f7eb2Smrg 	{
111627f7eb2Smrg 	  /* Make sure we have a zero-sized array.  */
112627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
113627f7eb2Smrg 	  return;
114627f7eb2Smrg 	}
115627f7eb2Smrg     }
116627f7eb2Smrg   else
117627f7eb2Smrg     {
118627f7eb2Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
119627f7eb2Smrg 	runtime_error ("rank of return array incorrect in"
120627f7eb2Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
121627f7eb2Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
122627f7eb2Smrg 		       (long int) rank);
123627f7eb2Smrg 
124627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
125627f7eb2Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
126627f7eb2Smrg 				 "return value", "FINDLOC");
127627f7eb2Smrg     }
128627f7eb2Smrg 
129627f7eb2Smrg   for (n = 0; n < rank; n++)
130627f7eb2Smrg     {
131627f7eb2Smrg       count[n] = 0;
132627f7eb2Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
133627f7eb2Smrg       if (extent[n] <= 0)
134627f7eb2Smrg 	return;
135627f7eb2Smrg     }
136627f7eb2Smrg 
137627f7eb2Smrg   dest = retarray->base_addr;
138627f7eb2Smrg   continue_loop = 1;
139627f7eb2Smrg 
140627f7eb2Smrg   base = array->base_addr;
141627f7eb2Smrg   while (continue_loop)
142627f7eb2Smrg     {
143627f7eb2Smrg       const GFC_UINTEGER_4 * restrict src;
144627f7eb2Smrg       index_type result;
145627f7eb2Smrg 
146627f7eb2Smrg       result = 0;
147627f7eb2Smrg       if (back)
148627f7eb2Smrg 	{
149627f7eb2Smrg 	  src = base + (len - 1) * delta * len_array;
150627f7eb2Smrg 	  for (n = len; n > 0; n--, src -= delta * len_array)
151627f7eb2Smrg 	    {
152627f7eb2Smrg 	      if (compare_string_char4 (len_array, src, len_value, value) == 0)
153627f7eb2Smrg 		{
154627f7eb2Smrg 		  result = n;
155627f7eb2Smrg 		  break;
156627f7eb2Smrg 		}
157627f7eb2Smrg 	    }
158627f7eb2Smrg 	}
159627f7eb2Smrg       else
160627f7eb2Smrg 	{
161627f7eb2Smrg 	  src = base;
162627f7eb2Smrg 	  for (n = 1; n <= len; n++, src += delta * len_array)
163627f7eb2Smrg 	    {
164627f7eb2Smrg 	      if (compare_string_char4 (len_array, src, len_value, value) == 0)
165627f7eb2Smrg 		{
166627f7eb2Smrg 		  result = n;
167627f7eb2Smrg 		  break;
168627f7eb2Smrg 		}
169627f7eb2Smrg 	    }
170627f7eb2Smrg 	}
171627f7eb2Smrg       *dest = result;
172627f7eb2Smrg 
173627f7eb2Smrg       count[0]++;
174627f7eb2Smrg       base += sstride[0] * len_array;
175627f7eb2Smrg       dest += dstride[0];
176627f7eb2Smrg       n = 0;
177627f7eb2Smrg       while (count[n] == extent[n])
178627f7eb2Smrg 	{
179627f7eb2Smrg 	  count[n] = 0;
180627f7eb2Smrg 	  base -= sstride[n] * extent[n] * len_array;
181627f7eb2Smrg 	  dest -= dstride[n] * extent[n];
182627f7eb2Smrg 	  n++;
183627f7eb2Smrg 	  if (n >= rank)
184627f7eb2Smrg 	    {
185627f7eb2Smrg 	      continue_loop = 0;
186627f7eb2Smrg 	      break;
187627f7eb2Smrg 	    }
188627f7eb2Smrg 	  else
189627f7eb2Smrg 	    {
190627f7eb2Smrg 	      count[n]++;
191627f7eb2Smrg 	      base += sstride[n] * len_array;
192627f7eb2Smrg 	      dest += dstride[n];
193627f7eb2Smrg 	    }
194627f7eb2Smrg 	}
195627f7eb2Smrg     }
196627f7eb2Smrg }
197627f7eb2Smrg extern void mfindloc1_s4 (gfc_array_index_type * const restrict retarray,
198627f7eb2Smrg 		         gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
199627f7eb2Smrg 			 const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
200627f7eb2Smrg 			 GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value);
201627f7eb2Smrg export_proto(mfindloc1_s4);
202627f7eb2Smrg 
203627f7eb2Smrg extern void
mfindloc1_s4(gfc_array_index_type * const restrict retarray,gfc_array_s4 * const restrict array,GFC_UINTEGER_4 * 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)204627f7eb2Smrg mfindloc1_s4 (gfc_array_index_type * const restrict retarray,
205627f7eb2Smrg 	    gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
206627f7eb2Smrg 	    const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
207627f7eb2Smrg 	    GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value)
208627f7eb2Smrg {
209627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
210627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
211627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
212627f7eb2Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
213627f7eb2Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
214627f7eb2Smrg   const GFC_UINTEGER_4 * restrict base;
215627f7eb2Smrg   const GFC_LOGICAL_1 * restrict mbase;
216627f7eb2Smrg   index_type * restrict dest;
217627f7eb2Smrg   index_type rank;
218627f7eb2Smrg   index_type n;
219627f7eb2Smrg   index_type len;
220627f7eb2Smrg   index_type delta;
221627f7eb2Smrg   index_type mdelta;
222627f7eb2Smrg   index_type dim;
223627f7eb2Smrg   int mask_kind;
224627f7eb2Smrg   int continue_loop;
225627f7eb2Smrg 
226627f7eb2Smrg   /* Make dim zero based to avoid confusion.  */
227627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
228627f7eb2Smrg   dim = (*pdim) - 1;
229627f7eb2Smrg 
230627f7eb2Smrg   if (unlikely (dim < 0 || dim > rank))
231627f7eb2Smrg     {
232627f7eb2Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
233627f7eb2Smrg  		     "is %ld, should be between 1 and %ld",
234627f7eb2Smrg 		     (long int) dim + 1, (long int) rank + 1);
235627f7eb2Smrg     }
236627f7eb2Smrg 
237627f7eb2Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
238627f7eb2Smrg   if (len < 0)
239627f7eb2Smrg     len = 0;
240627f7eb2Smrg 
241627f7eb2Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
242627f7eb2Smrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
243627f7eb2Smrg 
244627f7eb2Smrg   mbase = mask->base_addr;
245627f7eb2Smrg 
246627f7eb2Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
247627f7eb2Smrg 
248627f7eb2Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
249627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
250627f7eb2Smrg       || mask_kind == 16
251627f7eb2Smrg #endif
252627f7eb2Smrg       )
253627f7eb2Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
254627f7eb2Smrg   else
255627f7eb2Smrg     internal_error (NULL, "Funny sized logical array");
256627f7eb2Smrg 
257627f7eb2Smrg   for (n = 0; n < dim; n++)
258627f7eb2Smrg     {
259627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
260627f7eb2Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
261627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
262627f7eb2Smrg 
263627f7eb2Smrg       if (extent[n] < 0)
264627f7eb2Smrg 	extent[n] = 0;
265627f7eb2Smrg     }
266627f7eb2Smrg   for (n = dim; n < rank; n++)
267627f7eb2Smrg     {
268627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
269627f7eb2Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
270627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
271627f7eb2Smrg 
272627f7eb2Smrg       if (extent[n] < 0)
273627f7eb2Smrg 	extent[n] = 0;
274627f7eb2Smrg     }
275627f7eb2Smrg 
276627f7eb2Smrg   if (retarray->base_addr == NULL)
277627f7eb2Smrg     {
278627f7eb2Smrg       size_t alloc_size, str;
279627f7eb2Smrg 
280627f7eb2Smrg       for (n = 0; n < rank; n++)
281627f7eb2Smrg 	{
282627f7eb2Smrg 	  if (n == 0)
283627f7eb2Smrg 	    str = 1;
284627f7eb2Smrg 	  else
285627f7eb2Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
286627f7eb2Smrg 
287627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
288627f7eb2Smrg 
289627f7eb2Smrg 	}
290627f7eb2Smrg 
291627f7eb2Smrg       retarray->offset = 0;
292627f7eb2Smrg       retarray->dtype.rank = rank;
293627f7eb2Smrg 
294627f7eb2Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
295627f7eb2Smrg 
296627f7eb2Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
297627f7eb2Smrg       if (alloc_size == 0)
298627f7eb2Smrg 	{
299627f7eb2Smrg 	  /* Make sure we have a zero-sized array.  */
300627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
301627f7eb2Smrg 	  return;
302627f7eb2Smrg 	}
303627f7eb2Smrg     }
304627f7eb2Smrg   else
305627f7eb2Smrg     {
306627f7eb2Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
307627f7eb2Smrg 	runtime_error ("rank of return array incorrect in"
308627f7eb2Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
309627f7eb2Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
310627f7eb2Smrg 		       (long int) rank);
311627f7eb2Smrg 
312627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
313627f7eb2Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
314627f7eb2Smrg 				 "return value", "FINDLOC");
315627f7eb2Smrg     }
316627f7eb2Smrg 
317627f7eb2Smrg   for (n = 0; n < rank; n++)
318627f7eb2Smrg     {
319627f7eb2Smrg       count[n] = 0;
320627f7eb2Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
321627f7eb2Smrg       if (extent[n] <= 0)
322627f7eb2Smrg 	return;
323627f7eb2Smrg     }
324627f7eb2Smrg 
325627f7eb2Smrg   dest = retarray->base_addr;
326627f7eb2Smrg   continue_loop = 1;
327627f7eb2Smrg 
328627f7eb2Smrg   base = array->base_addr;
329627f7eb2Smrg   while (continue_loop)
330627f7eb2Smrg     {
331627f7eb2Smrg       const GFC_UINTEGER_4 * restrict src;
332627f7eb2Smrg       const GFC_LOGICAL_1 * restrict msrc;
333627f7eb2Smrg       index_type result;
334627f7eb2Smrg 
335627f7eb2Smrg       result = 0;
336627f7eb2Smrg       if (back)
337627f7eb2Smrg 	{
338627f7eb2Smrg 	  src = base + (len - 1) * delta * len_array;
339627f7eb2Smrg 	  msrc = mbase + (len - 1) * mdelta;
340627f7eb2Smrg 	  for (n = len; n > 0; n--, src -= delta * len_array, msrc -= mdelta)
341627f7eb2Smrg 	    {
342627f7eb2Smrg 	      if (*msrc && compare_string_char4 (len_array, src, len_value, value) == 0)
343627f7eb2Smrg 		{
344627f7eb2Smrg 		  result = n;
345627f7eb2Smrg 		  break;
346627f7eb2Smrg 		}
347627f7eb2Smrg 	    }
348627f7eb2Smrg 	}
349627f7eb2Smrg       else
350627f7eb2Smrg 	{
351627f7eb2Smrg 	  src = base;
352627f7eb2Smrg 	  msrc = mbase;
353627f7eb2Smrg 	  for (n = 1; n <= len; n++, src += delta * len_array, msrc += mdelta)
354627f7eb2Smrg 	    {
355627f7eb2Smrg 	      if (*msrc && compare_string_char4 (len_array, src, len_value, value) == 0)
356627f7eb2Smrg 		{
357627f7eb2Smrg 		  result = n;
358627f7eb2Smrg 		  break;
359627f7eb2Smrg 		}
360627f7eb2Smrg 	    }
361627f7eb2Smrg 	}
362627f7eb2Smrg       *dest = result;
363627f7eb2Smrg 
364627f7eb2Smrg       count[0]++;
365627f7eb2Smrg       base += sstride[0] * len_array;
366627f7eb2Smrg       mbase += mstride[0];
367627f7eb2Smrg       dest += dstride[0];
368627f7eb2Smrg       n = 0;
369627f7eb2Smrg       while (count[n] == extent[n])
370627f7eb2Smrg 	{
371627f7eb2Smrg 	  count[n] = 0;
372627f7eb2Smrg 	  base -= sstride[n] * extent[n] * len_array;
373627f7eb2Smrg 	  mbase -= mstride[n] * extent[n];
374627f7eb2Smrg 	  dest -= dstride[n] * extent[n];
375627f7eb2Smrg 	  n++;
376627f7eb2Smrg 	  if (n >= rank)
377627f7eb2Smrg 	    {
378627f7eb2Smrg 	      continue_loop = 0;
379627f7eb2Smrg 	      break;
380627f7eb2Smrg 	    }
381627f7eb2Smrg 	  else
382627f7eb2Smrg 	    {
383627f7eb2Smrg 	      count[n]++;
384627f7eb2Smrg 	      base += sstride[n] * len_array;
385627f7eb2Smrg 	      dest += dstride[n];
386627f7eb2Smrg 	    }
387627f7eb2Smrg 	}
388627f7eb2Smrg     }
389627f7eb2Smrg }
390627f7eb2Smrg extern void sfindloc1_s4 (gfc_array_index_type * const restrict retarray,
391627f7eb2Smrg 		         gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
392627f7eb2Smrg 			 const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
393627f7eb2Smrg 			 GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value);
394627f7eb2Smrg export_proto(sfindloc1_s4);
395627f7eb2Smrg 
396627f7eb2Smrg extern void
sfindloc1_s4(gfc_array_index_type * const restrict retarray,gfc_array_s4 * const restrict array,GFC_UINTEGER_4 * 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)397627f7eb2Smrg sfindloc1_s4 (gfc_array_index_type * const restrict retarray,
398627f7eb2Smrg 	    gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
399627f7eb2Smrg 	    const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict  mask,
400627f7eb2Smrg 	    GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value)
401627f7eb2Smrg {
402627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
403627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
404627f7eb2Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
405627f7eb2Smrg   index_type * restrict dest;
406627f7eb2Smrg   index_type rank;
407627f7eb2Smrg   index_type n;
408627f7eb2Smrg   index_type len;
409627f7eb2Smrg   index_type dim;
410627f7eb2Smrg   bool continue_loop;
411627f7eb2Smrg 
412627f7eb2Smrg   if (mask == NULL || *mask)
413627f7eb2Smrg     {
414627f7eb2Smrg       findloc1_s4 (retarray, array, value, pdim, back, len_array, len_value);
415627f7eb2Smrg       return;
416627f7eb2Smrg     }
417627f7eb2Smrg     /* Make dim zero based to avoid confusion.  */
418627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
419627f7eb2Smrg   dim = (*pdim) - 1;
420627f7eb2Smrg 
421627f7eb2Smrg   if (unlikely (dim < 0 || dim > rank))
422627f7eb2Smrg     {
423627f7eb2Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
424627f7eb2Smrg  		     "is %ld, should be between 1 and %ld",
425627f7eb2Smrg 		     (long int) dim + 1, (long int) rank + 1);
426627f7eb2Smrg     }
427627f7eb2Smrg 
428627f7eb2Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
429627f7eb2Smrg   if (len < 0)
430627f7eb2Smrg     len = 0;
431627f7eb2Smrg 
432627f7eb2Smrg   for (n = 0; n < dim; n++)
433627f7eb2Smrg     {
434627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
435627f7eb2Smrg 
436627f7eb2Smrg       if (extent[n] <= 0)
437627f7eb2Smrg 	extent[n] = 0;
438627f7eb2Smrg     }
439627f7eb2Smrg 
440627f7eb2Smrg   for (n = dim; n < rank; n++)
441627f7eb2Smrg     {
442627f7eb2Smrg       extent[n] =
443627f7eb2Smrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
444627f7eb2Smrg 
445627f7eb2Smrg       if (extent[n] <= 0)
446627f7eb2Smrg 	extent[n] = 0;
447627f7eb2Smrg     }
448627f7eb2Smrg 
449627f7eb2Smrg 
450627f7eb2Smrg   if (retarray->base_addr == NULL)
451627f7eb2Smrg     {
452627f7eb2Smrg       size_t alloc_size, str;
453627f7eb2Smrg 
454627f7eb2Smrg       for (n = 0; n < rank; n++)
455627f7eb2Smrg 	{
456627f7eb2Smrg 	  if (n == 0)
457627f7eb2Smrg 	    str = 1;
458627f7eb2Smrg 	  else
459627f7eb2Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
460627f7eb2Smrg 
461627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
462627f7eb2Smrg 	}
463627f7eb2Smrg 
464627f7eb2Smrg       retarray->offset = 0;
465627f7eb2Smrg       retarray->dtype.rank = rank;
466627f7eb2Smrg 
467627f7eb2Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
468627f7eb2Smrg 
469627f7eb2Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
470627f7eb2Smrg       if (alloc_size == 0)
471627f7eb2Smrg 	{
472627f7eb2Smrg 	  /* Make sure we have a zero-sized array.  */
473627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
474627f7eb2Smrg 	  return;
475627f7eb2Smrg 	}
476627f7eb2Smrg     }
477627f7eb2Smrg   else
478627f7eb2Smrg     {
479627f7eb2Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
480627f7eb2Smrg 	runtime_error ("rank of return array incorrect in"
481627f7eb2Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
482627f7eb2Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
483627f7eb2Smrg 		       (long int) rank);
484627f7eb2Smrg 
485627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
486627f7eb2Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
487627f7eb2Smrg 				 "return value", "FINDLOC");
488627f7eb2Smrg     }
489627f7eb2Smrg 
490627f7eb2Smrg   for (n = 0; n < rank; n++)
491627f7eb2Smrg     {
492627f7eb2Smrg       count[n] = 0;
493627f7eb2Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
494627f7eb2Smrg       if (extent[n] <= 0)
495627f7eb2Smrg 	return;
496627f7eb2Smrg     }
497627f7eb2Smrg   dest = retarray->base_addr;
498627f7eb2Smrg   continue_loop = 1;
499627f7eb2Smrg 
500627f7eb2Smrg   while (continue_loop)
501627f7eb2Smrg     {
502627f7eb2Smrg       *dest = 0;
503627f7eb2Smrg 
504627f7eb2Smrg       count[0]++;
505627f7eb2Smrg       dest += dstride[0];
506627f7eb2Smrg       n = 0;
507627f7eb2Smrg       while (count[n] == extent[n])
508627f7eb2Smrg 	{
509627f7eb2Smrg 	  count[n] = 0;
510627f7eb2Smrg 	  dest -= dstride[n] * extent[n];
511627f7eb2Smrg 	  n++;
512627f7eb2Smrg 	  if (n >= rank)
513627f7eb2Smrg 	    {
514627f7eb2Smrg 	      continue_loop = 0;
515627f7eb2Smrg 	      break;
516627f7eb2Smrg 	    }
517627f7eb2Smrg 	  else
518627f7eb2Smrg 	    {
519627f7eb2Smrg 	      count[n]++;
520627f7eb2Smrg 	      dest += dstride[n];
521627f7eb2Smrg 	    }
522627f7eb2Smrg 	}
523627f7eb2Smrg     }
524627f7eb2Smrg }
525627f7eb2Smrg #endif
526