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