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