xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/findloc1_c17.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1*b1e83836Smrg /* Implementation of the FINDLOC intrinsic
2*b1e83836Smrg    Copyright (C) 2018-2022 Free Software Foundation, Inc.
3*b1e83836Smrg    Contributed by Thomas König <tk@tkoenig.net>
4*b1e83836Smrg 
5*b1e83836Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
6*b1e83836Smrg 
7*b1e83836Smrg Libgfortran is free software; you can redistribute it and/or
8*b1e83836Smrg modify it under the terms of the GNU General Public
9*b1e83836Smrg License as published by the Free Software Foundation; either
10*b1e83836Smrg version 3 of the License, or (at your option) any later version.
11*b1e83836Smrg 
12*b1e83836Smrg Libgfortran is distributed in the hope that it will be useful,
13*b1e83836Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14*b1e83836Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*b1e83836Smrg GNU General Public License for more details.
16*b1e83836Smrg 
17*b1e83836Smrg Under Section 7 of GPL version 3, you are granted additional
18*b1e83836Smrg permissions described in the GCC Runtime Library Exception, version
19*b1e83836Smrg 3.1, as published by the Free Software Foundation.
20*b1e83836Smrg 
21*b1e83836Smrg You should have received a copy of the GNU General Public License and
22*b1e83836Smrg a copy of the GCC Runtime Library Exception along with this program;
23*b1e83836Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24*b1e83836Smrg <http://www.gnu.org/licenses/>.  */
25*b1e83836Smrg 
26*b1e83836Smrg #include "libgfortran.h"
27*b1e83836Smrg #include <assert.h>
28*b1e83836Smrg 
29*b1e83836Smrg #if defined (HAVE_GFC_COMPLEX_17)
30*b1e83836Smrg extern void findloc1_c17 (gfc_array_index_type * const restrict retarray,
31*b1e83836Smrg 		         gfc_array_c17 * const restrict array, GFC_COMPLEX_17 value,
32*b1e83836Smrg 			 const index_type * restrict pdim, GFC_LOGICAL_4 back);
33*b1e83836Smrg export_proto(findloc1_c17);
34*b1e83836Smrg 
35*b1e83836Smrg extern void
findloc1_c17(gfc_array_index_type * const restrict retarray,gfc_array_c17 * const restrict array,GFC_COMPLEX_17 value,const index_type * restrict pdim,GFC_LOGICAL_4 back)36*b1e83836Smrg findloc1_c17 (gfc_array_index_type * const restrict retarray,
37*b1e83836Smrg 	    gfc_array_c17 * const restrict array, GFC_COMPLEX_17 value,
38*b1e83836Smrg 	    const index_type * restrict pdim, GFC_LOGICAL_4 back)
39*b1e83836Smrg {
40*b1e83836Smrg   index_type count[GFC_MAX_DIMENSIONS];
41*b1e83836Smrg   index_type extent[GFC_MAX_DIMENSIONS];
42*b1e83836Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
43*b1e83836Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
44*b1e83836Smrg   const GFC_COMPLEX_17 * restrict base;
45*b1e83836Smrg   index_type * restrict dest;
46*b1e83836Smrg   index_type rank;
47*b1e83836Smrg   index_type n;
48*b1e83836Smrg   index_type len;
49*b1e83836Smrg   index_type delta;
50*b1e83836Smrg   index_type dim;
51*b1e83836Smrg   int continue_loop;
52*b1e83836Smrg 
53*b1e83836Smrg   /* Make dim zero based to avoid confusion.  */
54*b1e83836Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
55*b1e83836Smrg   dim = (*pdim) - 1;
56*b1e83836Smrg 
57*b1e83836Smrg   if (unlikely (dim < 0 || dim > rank))
58*b1e83836Smrg     {
59*b1e83836Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
60*b1e83836Smrg  		     "is %ld, should be between 1 and %ld",
61*b1e83836Smrg 		     (long int) dim + 1, (long int) rank + 1);
62*b1e83836Smrg     }
63*b1e83836Smrg 
64*b1e83836Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
65*b1e83836Smrg   if (len < 0)
66*b1e83836Smrg     len = 0;
67*b1e83836Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
68*b1e83836Smrg 
69*b1e83836Smrg   for (n = 0; n < dim; n++)
70*b1e83836Smrg     {
71*b1e83836Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
72*b1e83836Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
73*b1e83836Smrg 
74*b1e83836Smrg       if (extent[n] < 0)
75*b1e83836Smrg 	extent[n] = 0;
76*b1e83836Smrg     }
77*b1e83836Smrg   for (n = dim; n < rank; n++)
78*b1e83836Smrg     {
79*b1e83836Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
80*b1e83836Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
81*b1e83836Smrg 
82*b1e83836Smrg       if (extent[n] < 0)
83*b1e83836Smrg 	extent[n] = 0;
84*b1e83836Smrg     }
85*b1e83836Smrg 
86*b1e83836Smrg   if (retarray->base_addr == NULL)
87*b1e83836Smrg     {
88*b1e83836Smrg       size_t alloc_size, str;
89*b1e83836Smrg 
90*b1e83836Smrg       for (n = 0; n < rank; n++)
91*b1e83836Smrg 	{
92*b1e83836Smrg 	  if (n == 0)
93*b1e83836Smrg 	    str = 1;
94*b1e83836Smrg 	  else
95*b1e83836Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
96*b1e83836Smrg 
97*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
98*b1e83836Smrg 
99*b1e83836Smrg 	}
100*b1e83836Smrg 
101*b1e83836Smrg       retarray->offset = 0;
102*b1e83836Smrg       retarray->dtype.rank = rank;
103*b1e83836Smrg 
104*b1e83836Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
105*b1e83836Smrg 
106*b1e83836Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
107*b1e83836Smrg       if (alloc_size == 0)
108*b1e83836Smrg 	{
109*b1e83836Smrg 	  /* Make sure we have a zero-sized array.  */
110*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
111*b1e83836Smrg 	  return;
112*b1e83836Smrg 	}
113*b1e83836Smrg     }
114*b1e83836Smrg   else
115*b1e83836Smrg     {
116*b1e83836Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
117*b1e83836Smrg 	runtime_error ("rank of return array incorrect in"
118*b1e83836Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
119*b1e83836Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
120*b1e83836Smrg 		       (long int) rank);
121*b1e83836Smrg 
122*b1e83836Smrg       if (unlikely (compile_options.bounds_check))
123*b1e83836Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
124*b1e83836Smrg 				 "return value", "FINDLOC");
125*b1e83836Smrg     }
126*b1e83836Smrg 
127*b1e83836Smrg   for (n = 0; n < rank; n++)
128*b1e83836Smrg     {
129*b1e83836Smrg       count[n] = 0;
130*b1e83836Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
131*b1e83836Smrg       if (extent[n] <= 0)
132*b1e83836Smrg 	return;
133*b1e83836Smrg     }
134*b1e83836Smrg 
135*b1e83836Smrg   dest = retarray->base_addr;
136*b1e83836Smrg   continue_loop = 1;
137*b1e83836Smrg 
138*b1e83836Smrg   base = array->base_addr;
139*b1e83836Smrg   while (continue_loop)
140*b1e83836Smrg     {
141*b1e83836Smrg       const GFC_COMPLEX_17 * restrict src;
142*b1e83836Smrg       index_type result;
143*b1e83836Smrg 
144*b1e83836Smrg       result = 0;
145*b1e83836Smrg       if (back)
146*b1e83836Smrg 	{
147*b1e83836Smrg 	  src = base + (len - 1) * delta * 1;
148*b1e83836Smrg 	  for (n = len; n > 0; n--, src -= delta * 1)
149*b1e83836Smrg 	    {
150*b1e83836Smrg 	      if (*src == value)
151*b1e83836Smrg 		{
152*b1e83836Smrg 		  result = n;
153*b1e83836Smrg 		  break;
154*b1e83836Smrg 		}
155*b1e83836Smrg 	    }
156*b1e83836Smrg 	}
157*b1e83836Smrg       else
158*b1e83836Smrg 	{
159*b1e83836Smrg 	  src = base;
160*b1e83836Smrg 	  for (n = 1; n <= len; n++, src += delta * 1)
161*b1e83836Smrg 	    {
162*b1e83836Smrg 	      if (*src == value)
163*b1e83836Smrg 		{
164*b1e83836Smrg 		  result = n;
165*b1e83836Smrg 		  break;
166*b1e83836Smrg 		}
167*b1e83836Smrg 	    }
168*b1e83836Smrg 	}
169*b1e83836Smrg       *dest = result;
170*b1e83836Smrg 
171*b1e83836Smrg       count[0]++;
172*b1e83836Smrg       base += sstride[0] * 1;
173*b1e83836Smrg       dest += dstride[0];
174*b1e83836Smrg       n = 0;
175*b1e83836Smrg       while (count[n] == extent[n])
176*b1e83836Smrg 	{
177*b1e83836Smrg 	  count[n] = 0;
178*b1e83836Smrg 	  base -= sstride[n] * extent[n] * 1;
179*b1e83836Smrg 	  dest -= dstride[n] * extent[n];
180*b1e83836Smrg 	  n++;
181*b1e83836Smrg 	  if (n >= rank)
182*b1e83836Smrg 	    {
183*b1e83836Smrg 	      continue_loop = 0;
184*b1e83836Smrg 	      break;
185*b1e83836Smrg 	    }
186*b1e83836Smrg 	  else
187*b1e83836Smrg 	    {
188*b1e83836Smrg 	      count[n]++;
189*b1e83836Smrg 	      base += sstride[n] * 1;
190*b1e83836Smrg 	      dest += dstride[n];
191*b1e83836Smrg 	    }
192*b1e83836Smrg 	}
193*b1e83836Smrg     }
194*b1e83836Smrg }
195*b1e83836Smrg extern void mfindloc1_c17 (gfc_array_index_type * const restrict retarray,
196*b1e83836Smrg 		         gfc_array_c17 * const restrict array, GFC_COMPLEX_17 value,
197*b1e83836Smrg 			 const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
198*b1e83836Smrg 			 GFC_LOGICAL_4 back);
199*b1e83836Smrg export_proto(mfindloc1_c17);
200*b1e83836Smrg 
201*b1e83836Smrg extern void
mfindloc1_c17(gfc_array_index_type * const restrict retarray,gfc_array_c17 * const restrict array,GFC_COMPLEX_17 value,const index_type * restrict pdim,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back)202*b1e83836Smrg mfindloc1_c17 (gfc_array_index_type * const restrict retarray,
203*b1e83836Smrg 	    gfc_array_c17 * const restrict array, GFC_COMPLEX_17 value,
204*b1e83836Smrg 	    const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
205*b1e83836Smrg 	    GFC_LOGICAL_4 back)
206*b1e83836Smrg {
207*b1e83836Smrg   index_type count[GFC_MAX_DIMENSIONS];
208*b1e83836Smrg   index_type extent[GFC_MAX_DIMENSIONS];
209*b1e83836Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
210*b1e83836Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
211*b1e83836Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
212*b1e83836Smrg   const GFC_COMPLEX_17 * restrict base;
213*b1e83836Smrg   const GFC_LOGICAL_1 * restrict mbase;
214*b1e83836Smrg   index_type * restrict dest;
215*b1e83836Smrg   index_type rank;
216*b1e83836Smrg   index_type n;
217*b1e83836Smrg   index_type len;
218*b1e83836Smrg   index_type delta;
219*b1e83836Smrg   index_type mdelta;
220*b1e83836Smrg   index_type dim;
221*b1e83836Smrg   int mask_kind;
222*b1e83836Smrg   int continue_loop;
223*b1e83836Smrg 
224*b1e83836Smrg   /* Make dim zero based to avoid confusion.  */
225*b1e83836Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
226*b1e83836Smrg   dim = (*pdim) - 1;
227*b1e83836Smrg 
228*b1e83836Smrg   if (unlikely (dim < 0 || dim > rank))
229*b1e83836Smrg     {
230*b1e83836Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
231*b1e83836Smrg  		     "is %ld, should be between 1 and %ld",
232*b1e83836Smrg 		     (long int) dim + 1, (long int) rank + 1);
233*b1e83836Smrg     }
234*b1e83836Smrg 
235*b1e83836Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
236*b1e83836Smrg   if (len < 0)
237*b1e83836Smrg     len = 0;
238*b1e83836Smrg 
239*b1e83836Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
240*b1e83836Smrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
241*b1e83836Smrg 
242*b1e83836Smrg   mbase = mask->base_addr;
243*b1e83836Smrg 
244*b1e83836Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
245*b1e83836Smrg 
246*b1e83836Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
247*b1e83836Smrg #ifdef HAVE_GFC_LOGICAL_16
248*b1e83836Smrg       || mask_kind == 16
249*b1e83836Smrg #endif
250*b1e83836Smrg       )
251*b1e83836Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
252*b1e83836Smrg   else
253*b1e83836Smrg     internal_error (NULL, "Funny sized logical array");
254*b1e83836Smrg 
255*b1e83836Smrg   for (n = 0; n < dim; n++)
256*b1e83836Smrg     {
257*b1e83836Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
258*b1e83836Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
259*b1e83836Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
260*b1e83836Smrg 
261*b1e83836Smrg       if (extent[n] < 0)
262*b1e83836Smrg 	extent[n] = 0;
263*b1e83836Smrg     }
264*b1e83836Smrg   for (n = dim; n < rank; n++)
265*b1e83836Smrg     {
266*b1e83836Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
267*b1e83836Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
268*b1e83836Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
269*b1e83836Smrg 
270*b1e83836Smrg       if (extent[n] < 0)
271*b1e83836Smrg 	extent[n] = 0;
272*b1e83836Smrg     }
273*b1e83836Smrg 
274*b1e83836Smrg   if (retarray->base_addr == NULL)
275*b1e83836Smrg     {
276*b1e83836Smrg       size_t alloc_size, str;
277*b1e83836Smrg 
278*b1e83836Smrg       for (n = 0; n < rank; n++)
279*b1e83836Smrg 	{
280*b1e83836Smrg 	  if (n == 0)
281*b1e83836Smrg 	    str = 1;
282*b1e83836Smrg 	  else
283*b1e83836Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
284*b1e83836Smrg 
285*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
286*b1e83836Smrg 
287*b1e83836Smrg 	}
288*b1e83836Smrg 
289*b1e83836Smrg       retarray->offset = 0;
290*b1e83836Smrg       retarray->dtype.rank = rank;
291*b1e83836Smrg 
292*b1e83836Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
293*b1e83836Smrg 
294*b1e83836Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
295*b1e83836Smrg       if (alloc_size == 0)
296*b1e83836Smrg 	{
297*b1e83836Smrg 	  /* Make sure we have a zero-sized array.  */
298*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
299*b1e83836Smrg 	  return;
300*b1e83836Smrg 	}
301*b1e83836Smrg     }
302*b1e83836Smrg   else
303*b1e83836Smrg     {
304*b1e83836Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
305*b1e83836Smrg 	runtime_error ("rank of return array incorrect in"
306*b1e83836Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
307*b1e83836Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
308*b1e83836Smrg 		       (long int) rank);
309*b1e83836Smrg 
310*b1e83836Smrg       if (unlikely (compile_options.bounds_check))
311*b1e83836Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
312*b1e83836Smrg 				 "return value", "FINDLOC");
313*b1e83836Smrg     }
314*b1e83836Smrg 
315*b1e83836Smrg   for (n = 0; n < rank; n++)
316*b1e83836Smrg     {
317*b1e83836Smrg       count[n] = 0;
318*b1e83836Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
319*b1e83836Smrg       if (extent[n] <= 0)
320*b1e83836Smrg 	return;
321*b1e83836Smrg     }
322*b1e83836Smrg 
323*b1e83836Smrg   dest = retarray->base_addr;
324*b1e83836Smrg   continue_loop = 1;
325*b1e83836Smrg 
326*b1e83836Smrg   base = array->base_addr;
327*b1e83836Smrg   while (continue_loop)
328*b1e83836Smrg     {
329*b1e83836Smrg       const GFC_COMPLEX_17 * restrict src;
330*b1e83836Smrg       const GFC_LOGICAL_1 * restrict msrc;
331*b1e83836Smrg       index_type result;
332*b1e83836Smrg 
333*b1e83836Smrg       result = 0;
334*b1e83836Smrg       if (back)
335*b1e83836Smrg 	{
336*b1e83836Smrg 	  src = base + (len - 1) * delta * 1;
337*b1e83836Smrg 	  msrc = mbase + (len - 1) * mdelta;
338*b1e83836Smrg 	  for (n = len; n > 0; n--, src -= delta * 1, msrc -= mdelta)
339*b1e83836Smrg 	    {
340*b1e83836Smrg 	      if (*msrc && *src == value)
341*b1e83836Smrg 		{
342*b1e83836Smrg 		  result = n;
343*b1e83836Smrg 		  break;
344*b1e83836Smrg 		}
345*b1e83836Smrg 	    }
346*b1e83836Smrg 	}
347*b1e83836Smrg       else
348*b1e83836Smrg 	{
349*b1e83836Smrg 	  src = base;
350*b1e83836Smrg 	  msrc = mbase;
351*b1e83836Smrg 	  for (n = 1; n <= len; n++, src += delta * 1, msrc += mdelta)
352*b1e83836Smrg 	    {
353*b1e83836Smrg 	      if (*msrc && *src == value)
354*b1e83836Smrg 		{
355*b1e83836Smrg 		  result = n;
356*b1e83836Smrg 		  break;
357*b1e83836Smrg 		}
358*b1e83836Smrg 	    }
359*b1e83836Smrg 	}
360*b1e83836Smrg       *dest = result;
361*b1e83836Smrg 
362*b1e83836Smrg       count[0]++;
363*b1e83836Smrg       base += sstride[0] * 1;
364*b1e83836Smrg       mbase += mstride[0];
365*b1e83836Smrg       dest += dstride[0];
366*b1e83836Smrg       n = 0;
367*b1e83836Smrg       while (count[n] == extent[n])
368*b1e83836Smrg 	{
369*b1e83836Smrg 	  count[n] = 0;
370*b1e83836Smrg 	  base -= sstride[n] * extent[n] * 1;
371*b1e83836Smrg 	  mbase -= mstride[n] * extent[n];
372*b1e83836Smrg 	  dest -= dstride[n] * extent[n];
373*b1e83836Smrg 	  n++;
374*b1e83836Smrg 	  if (n >= rank)
375*b1e83836Smrg 	    {
376*b1e83836Smrg 	      continue_loop = 0;
377*b1e83836Smrg 	      break;
378*b1e83836Smrg 	    }
379*b1e83836Smrg 	  else
380*b1e83836Smrg 	    {
381*b1e83836Smrg 	      count[n]++;
382*b1e83836Smrg 	      base += sstride[n] * 1;
383*b1e83836Smrg 	      dest += dstride[n];
384*b1e83836Smrg 	    }
385*b1e83836Smrg 	}
386*b1e83836Smrg     }
387*b1e83836Smrg }
388*b1e83836Smrg extern void sfindloc1_c17 (gfc_array_index_type * const restrict retarray,
389*b1e83836Smrg 		         gfc_array_c17 * const restrict array, GFC_COMPLEX_17 value,
390*b1e83836Smrg 			 const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
391*b1e83836Smrg 			 GFC_LOGICAL_4 back);
392*b1e83836Smrg export_proto(sfindloc1_c17);
393*b1e83836Smrg 
394*b1e83836Smrg extern void
sfindloc1_c17(gfc_array_index_type * const restrict retarray,gfc_array_c17 * const restrict array,GFC_COMPLEX_17 value,const index_type * restrict pdim,GFC_LOGICAL_4 * const restrict mask,GFC_LOGICAL_4 back)395*b1e83836Smrg sfindloc1_c17 (gfc_array_index_type * const restrict retarray,
396*b1e83836Smrg 	    gfc_array_c17 * const restrict array, GFC_COMPLEX_17 value,
397*b1e83836Smrg 	    const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict  mask,
398*b1e83836Smrg 	    GFC_LOGICAL_4 back)
399*b1e83836Smrg {
400*b1e83836Smrg   index_type count[GFC_MAX_DIMENSIONS];
401*b1e83836Smrg   index_type extent[GFC_MAX_DIMENSIONS];
402*b1e83836Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
403*b1e83836Smrg   index_type * restrict dest;
404*b1e83836Smrg   index_type rank;
405*b1e83836Smrg   index_type n;
406*b1e83836Smrg   index_type len;
407*b1e83836Smrg   index_type dim;
408*b1e83836Smrg   bool continue_loop;
409*b1e83836Smrg 
410*b1e83836Smrg   if (mask == NULL || *mask)
411*b1e83836Smrg     {
412*b1e83836Smrg       findloc1_c17 (retarray, array, value, pdim, back);
413*b1e83836Smrg       return;
414*b1e83836Smrg     }
415*b1e83836Smrg     /* Make dim zero based to avoid confusion.  */
416*b1e83836Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
417*b1e83836Smrg   dim = (*pdim) - 1;
418*b1e83836Smrg 
419*b1e83836Smrg   if (unlikely (dim < 0 || dim > rank))
420*b1e83836Smrg     {
421*b1e83836Smrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
422*b1e83836Smrg  		     "is %ld, should be between 1 and %ld",
423*b1e83836Smrg 		     (long int) dim + 1, (long int) rank + 1);
424*b1e83836Smrg     }
425*b1e83836Smrg 
426*b1e83836Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
427*b1e83836Smrg   if (len < 0)
428*b1e83836Smrg     len = 0;
429*b1e83836Smrg 
430*b1e83836Smrg   for (n = 0; n < dim; n++)
431*b1e83836Smrg     {
432*b1e83836Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
433*b1e83836Smrg 
434*b1e83836Smrg       if (extent[n] <= 0)
435*b1e83836Smrg 	extent[n] = 0;
436*b1e83836Smrg     }
437*b1e83836Smrg 
438*b1e83836Smrg   for (n = dim; n < rank; n++)
439*b1e83836Smrg     {
440*b1e83836Smrg       extent[n] =
441*b1e83836Smrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
442*b1e83836Smrg 
443*b1e83836Smrg       if (extent[n] <= 0)
444*b1e83836Smrg 	extent[n] = 0;
445*b1e83836Smrg     }
446*b1e83836Smrg 
447*b1e83836Smrg 
448*b1e83836Smrg   if (retarray->base_addr == NULL)
449*b1e83836Smrg     {
450*b1e83836Smrg       size_t alloc_size, str;
451*b1e83836Smrg 
452*b1e83836Smrg       for (n = 0; n < rank; n++)
453*b1e83836Smrg 	{
454*b1e83836Smrg 	  if (n == 0)
455*b1e83836Smrg 	    str = 1;
456*b1e83836Smrg 	  else
457*b1e83836Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
458*b1e83836Smrg 
459*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
460*b1e83836Smrg 	}
461*b1e83836Smrg 
462*b1e83836Smrg       retarray->offset = 0;
463*b1e83836Smrg       retarray->dtype.rank = rank;
464*b1e83836Smrg 
465*b1e83836Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
466*b1e83836Smrg 
467*b1e83836Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
468*b1e83836Smrg       if (alloc_size == 0)
469*b1e83836Smrg 	{
470*b1e83836Smrg 	  /* Make sure we have a zero-sized array.  */
471*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
472*b1e83836Smrg 	  return;
473*b1e83836Smrg 	}
474*b1e83836Smrg     }
475*b1e83836Smrg   else
476*b1e83836Smrg     {
477*b1e83836Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
478*b1e83836Smrg 	runtime_error ("rank of return array incorrect in"
479*b1e83836Smrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
480*b1e83836Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
481*b1e83836Smrg 		       (long int) rank);
482*b1e83836Smrg 
483*b1e83836Smrg       if (unlikely (compile_options.bounds_check))
484*b1e83836Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
485*b1e83836Smrg 				 "return value", "FINDLOC");
486*b1e83836Smrg     }
487*b1e83836Smrg 
488*b1e83836Smrg   for (n = 0; n < rank; n++)
489*b1e83836Smrg     {
490*b1e83836Smrg       count[n] = 0;
491*b1e83836Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
492*b1e83836Smrg       if (extent[n] <= 0)
493*b1e83836Smrg 	return;
494*b1e83836Smrg     }
495*b1e83836Smrg   dest = retarray->base_addr;
496*b1e83836Smrg   continue_loop = 1;
497*b1e83836Smrg 
498*b1e83836Smrg   while (continue_loop)
499*b1e83836Smrg     {
500*b1e83836Smrg       *dest = 0;
501*b1e83836Smrg 
502*b1e83836Smrg       count[0]++;
503*b1e83836Smrg       dest += dstride[0];
504*b1e83836Smrg       n = 0;
505*b1e83836Smrg       while (count[n] == extent[n])
506*b1e83836Smrg 	{
507*b1e83836Smrg 	  count[n] = 0;
508*b1e83836Smrg 	  dest -= dstride[n] * extent[n];
509*b1e83836Smrg 	  n++;
510*b1e83836Smrg 	  if (n >= rank)
511*b1e83836Smrg 	    {
512*b1e83836Smrg 	      continue_loop = 0;
513*b1e83836Smrg 	      break;
514*b1e83836Smrg 	    }
515*b1e83836Smrg 	  else
516*b1e83836Smrg 	    {
517*b1e83836Smrg 	      count[n]++;
518*b1e83836Smrg 	      dest += dstride[n];
519*b1e83836Smrg 	    }
520*b1e83836Smrg 	}
521*b1e83836Smrg     }
522*b1e83836Smrg }
523*b1e83836Smrg #endif
524