1181254a7Smrg /* Implementation of the FINDLOC intrinsic
2*b1e83836Smrg Copyright (C) 2018-2022 Free Software Foundation, Inc.
3181254a7Smrg Contributed by Thomas König <tk@tkoenig.net>
4181254a7Smrg
5181254a7Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
6181254a7Smrg
7181254a7Smrg Libgfortran is free software; you can redistribute it and/or
8181254a7Smrg modify it under the terms of the GNU General Public
9181254a7Smrg License as published by the Free Software Foundation; either
10181254a7Smrg version 3 of the License, or (at your option) any later version.
11181254a7Smrg
12181254a7Smrg Libgfortran is distributed in the hope that it will be useful,
13181254a7Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14181254a7Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15181254a7Smrg GNU General Public License for more details.
16181254a7Smrg
17181254a7Smrg Under Section 7 of GPL version 3, you are granted additional
18181254a7Smrg permissions described in the GCC Runtime Library Exception, version
19181254a7Smrg 3.1, as published by the Free Software Foundation.
20181254a7Smrg
21181254a7Smrg You should have received a copy of the GNU General Public License and
22181254a7Smrg a copy of the GCC Runtime Library Exception along with this program;
23181254a7Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24181254a7Smrg <http://www.gnu.org/licenses/>. */
25181254a7Smrg
26181254a7Smrg #include "libgfortran.h"
27181254a7Smrg #include <assert.h>
28181254a7Smrg
29181254a7Smrg #if defined (HAVE_GFC_REAL_10)
30181254a7Smrg extern void findloc1_r10 (gfc_array_index_type * const restrict retarray,
31181254a7Smrg gfc_array_r10 * const restrict array, GFC_REAL_10 value,
32181254a7Smrg const index_type * restrict pdim, GFC_LOGICAL_4 back);
33181254a7Smrg export_proto(findloc1_r10);
34181254a7Smrg
35181254a7Smrg extern void
findloc1_r10(gfc_array_index_type * const restrict retarray,gfc_array_r10 * const restrict array,GFC_REAL_10 value,const index_type * restrict pdim,GFC_LOGICAL_4 back)36181254a7Smrg findloc1_r10 (gfc_array_index_type * const restrict retarray,
37181254a7Smrg gfc_array_r10 * const restrict array, GFC_REAL_10 value,
38181254a7Smrg const index_type * restrict pdim, GFC_LOGICAL_4 back)
39181254a7Smrg {
40181254a7Smrg index_type count[GFC_MAX_DIMENSIONS];
41181254a7Smrg index_type extent[GFC_MAX_DIMENSIONS];
42181254a7Smrg index_type sstride[GFC_MAX_DIMENSIONS];
43181254a7Smrg index_type dstride[GFC_MAX_DIMENSIONS];
44181254a7Smrg const GFC_REAL_10 * restrict base;
45181254a7Smrg index_type * restrict dest;
46181254a7Smrg index_type rank;
47181254a7Smrg index_type n;
48181254a7Smrg index_type len;
49181254a7Smrg index_type delta;
50181254a7Smrg index_type dim;
51181254a7Smrg int continue_loop;
52181254a7Smrg
53181254a7Smrg /* Make dim zero based to avoid confusion. */
54181254a7Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
55181254a7Smrg dim = (*pdim) - 1;
56181254a7Smrg
57181254a7Smrg if (unlikely (dim < 0 || dim > rank))
58181254a7Smrg {
59181254a7Smrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
60181254a7Smrg "is %ld, should be between 1 and %ld",
61181254a7Smrg (long int) dim + 1, (long int) rank + 1);
62181254a7Smrg }
63181254a7Smrg
64181254a7Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
65181254a7Smrg if (len < 0)
66181254a7Smrg len = 0;
67181254a7Smrg delta = GFC_DESCRIPTOR_STRIDE(array,dim);
68181254a7Smrg
69181254a7Smrg for (n = 0; n < dim; n++)
70181254a7Smrg {
71181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
72181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
73181254a7Smrg
74181254a7Smrg if (extent[n] < 0)
75181254a7Smrg extent[n] = 0;
76181254a7Smrg }
77181254a7Smrg for (n = dim; n < rank; n++)
78181254a7Smrg {
79181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
80181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
81181254a7Smrg
82181254a7Smrg if (extent[n] < 0)
83181254a7Smrg extent[n] = 0;
84181254a7Smrg }
85181254a7Smrg
86181254a7Smrg if (retarray->base_addr == NULL)
87181254a7Smrg {
88181254a7Smrg size_t alloc_size, str;
89181254a7Smrg
90181254a7Smrg for (n = 0; n < rank; n++)
91181254a7Smrg {
92181254a7Smrg if (n == 0)
93181254a7Smrg str = 1;
94181254a7Smrg else
95181254a7Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
96181254a7Smrg
97181254a7Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
98181254a7Smrg
99181254a7Smrg }
100181254a7Smrg
101181254a7Smrg retarray->offset = 0;
102181254a7Smrg retarray->dtype.rank = rank;
103181254a7Smrg
104181254a7Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
105181254a7Smrg
106181254a7Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
107181254a7Smrg if (alloc_size == 0)
108181254a7Smrg {
109181254a7Smrg /* Make sure we have a zero-sized array. */
110181254a7Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
111181254a7Smrg return;
112181254a7Smrg }
113181254a7Smrg }
114181254a7Smrg else
115181254a7Smrg {
116181254a7Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
117181254a7Smrg runtime_error ("rank of return array incorrect in"
118181254a7Smrg " FINDLOC intrinsic: is %ld, should be %ld",
119181254a7Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
120181254a7Smrg (long int) rank);
121181254a7Smrg
122181254a7Smrg if (unlikely (compile_options.bounds_check))
123181254a7Smrg bounds_ifunction_return ((array_t *) retarray, extent,
124181254a7Smrg "return value", "FINDLOC");
125181254a7Smrg }
126181254a7Smrg
127181254a7Smrg for (n = 0; n < rank; n++)
128181254a7Smrg {
129181254a7Smrg count[n] = 0;
130181254a7Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
131181254a7Smrg if (extent[n] <= 0)
132181254a7Smrg return;
133181254a7Smrg }
134181254a7Smrg
135181254a7Smrg dest = retarray->base_addr;
136181254a7Smrg continue_loop = 1;
137181254a7Smrg
138181254a7Smrg base = array->base_addr;
139181254a7Smrg while (continue_loop)
140181254a7Smrg {
141181254a7Smrg const GFC_REAL_10 * restrict src;
142181254a7Smrg index_type result;
143181254a7Smrg
144181254a7Smrg result = 0;
145181254a7Smrg if (back)
146181254a7Smrg {
147181254a7Smrg src = base + (len - 1) * delta * 1;
148181254a7Smrg for (n = len; n > 0; n--, src -= delta * 1)
149181254a7Smrg {
150181254a7Smrg if (*src == value)
151181254a7Smrg {
152181254a7Smrg result = n;
153181254a7Smrg break;
154181254a7Smrg }
155181254a7Smrg }
156181254a7Smrg }
157181254a7Smrg else
158181254a7Smrg {
159181254a7Smrg src = base;
160181254a7Smrg for (n = 1; n <= len; n++, src += delta * 1)
161181254a7Smrg {
162181254a7Smrg if (*src == value)
163181254a7Smrg {
164181254a7Smrg result = n;
165181254a7Smrg break;
166181254a7Smrg }
167181254a7Smrg }
168181254a7Smrg }
169181254a7Smrg *dest = result;
170181254a7Smrg
171181254a7Smrg count[0]++;
172181254a7Smrg base += sstride[0] * 1;
173181254a7Smrg dest += dstride[0];
174181254a7Smrg n = 0;
175181254a7Smrg while (count[n] == extent[n])
176181254a7Smrg {
177181254a7Smrg count[n] = 0;
178181254a7Smrg base -= sstride[n] * extent[n] * 1;
179181254a7Smrg dest -= dstride[n] * extent[n];
180181254a7Smrg n++;
181181254a7Smrg if (n >= rank)
182181254a7Smrg {
183181254a7Smrg continue_loop = 0;
184181254a7Smrg break;
185181254a7Smrg }
186181254a7Smrg else
187181254a7Smrg {
188181254a7Smrg count[n]++;
189181254a7Smrg base += sstride[n] * 1;
190181254a7Smrg dest += dstride[n];
191181254a7Smrg }
192181254a7Smrg }
193181254a7Smrg }
194181254a7Smrg }
195181254a7Smrg extern void mfindloc1_r10 (gfc_array_index_type * const restrict retarray,
196181254a7Smrg gfc_array_r10 * const restrict array, GFC_REAL_10 value,
197181254a7Smrg const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
198181254a7Smrg GFC_LOGICAL_4 back);
199181254a7Smrg export_proto(mfindloc1_r10);
200181254a7Smrg
201181254a7Smrg extern void
mfindloc1_r10(gfc_array_index_type * const restrict retarray,gfc_array_r10 * const restrict array,GFC_REAL_10 value,const index_type * restrict pdim,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back)202181254a7Smrg mfindloc1_r10 (gfc_array_index_type * const restrict retarray,
203181254a7Smrg gfc_array_r10 * const restrict array, GFC_REAL_10 value,
204181254a7Smrg const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
205181254a7Smrg GFC_LOGICAL_4 back)
206181254a7Smrg {
207181254a7Smrg index_type count[GFC_MAX_DIMENSIONS];
208181254a7Smrg index_type extent[GFC_MAX_DIMENSIONS];
209181254a7Smrg index_type sstride[GFC_MAX_DIMENSIONS];
210181254a7Smrg index_type mstride[GFC_MAX_DIMENSIONS];
211181254a7Smrg index_type dstride[GFC_MAX_DIMENSIONS];
212181254a7Smrg const GFC_REAL_10 * restrict base;
213181254a7Smrg const GFC_LOGICAL_1 * restrict mbase;
214181254a7Smrg index_type * restrict dest;
215181254a7Smrg index_type rank;
216181254a7Smrg index_type n;
217181254a7Smrg index_type len;
218181254a7Smrg index_type delta;
219181254a7Smrg index_type mdelta;
220181254a7Smrg index_type dim;
221181254a7Smrg int mask_kind;
222181254a7Smrg int continue_loop;
223181254a7Smrg
224181254a7Smrg /* Make dim zero based to avoid confusion. */
225181254a7Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
226181254a7Smrg dim = (*pdim) - 1;
227181254a7Smrg
228181254a7Smrg if (unlikely (dim < 0 || dim > rank))
229181254a7Smrg {
230181254a7Smrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
231181254a7Smrg "is %ld, should be between 1 and %ld",
232181254a7Smrg (long int) dim + 1, (long int) rank + 1);
233181254a7Smrg }
234181254a7Smrg
235181254a7Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
236181254a7Smrg if (len < 0)
237181254a7Smrg len = 0;
238181254a7Smrg
239181254a7Smrg delta = GFC_DESCRIPTOR_STRIDE(array,dim);
240181254a7Smrg mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
241181254a7Smrg
242181254a7Smrg mbase = mask->base_addr;
243181254a7Smrg
244181254a7Smrg mask_kind = GFC_DESCRIPTOR_SIZE (mask);
245181254a7Smrg
246181254a7Smrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
247181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
248181254a7Smrg || mask_kind == 16
249181254a7Smrg #endif
250181254a7Smrg )
251181254a7Smrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
252181254a7Smrg else
253181254a7Smrg internal_error (NULL, "Funny sized logical array");
254181254a7Smrg
255181254a7Smrg for (n = 0; n < dim; n++)
256181254a7Smrg {
257181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
258181254a7Smrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
259181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
260181254a7Smrg
261181254a7Smrg if (extent[n] < 0)
262181254a7Smrg extent[n] = 0;
263181254a7Smrg }
264181254a7Smrg for (n = dim; n < rank; n++)
265181254a7Smrg {
266181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
267181254a7Smrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
268181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
269181254a7Smrg
270181254a7Smrg if (extent[n] < 0)
271181254a7Smrg extent[n] = 0;
272181254a7Smrg }
273181254a7Smrg
274181254a7Smrg if (retarray->base_addr == NULL)
275181254a7Smrg {
276181254a7Smrg size_t alloc_size, str;
277181254a7Smrg
278181254a7Smrg for (n = 0; n < rank; n++)
279181254a7Smrg {
280181254a7Smrg if (n == 0)
281181254a7Smrg str = 1;
282181254a7Smrg else
283181254a7Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
284181254a7Smrg
285181254a7Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
286181254a7Smrg
287181254a7Smrg }
288181254a7Smrg
289181254a7Smrg retarray->offset = 0;
290181254a7Smrg retarray->dtype.rank = rank;
291181254a7Smrg
292181254a7Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
293181254a7Smrg
294181254a7Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
295181254a7Smrg if (alloc_size == 0)
296181254a7Smrg {
297181254a7Smrg /* Make sure we have a zero-sized array. */
298181254a7Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
299181254a7Smrg return;
300181254a7Smrg }
301181254a7Smrg }
302181254a7Smrg else
303181254a7Smrg {
304181254a7Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
305181254a7Smrg runtime_error ("rank of return array incorrect in"
306181254a7Smrg " FINDLOC intrinsic: is %ld, should be %ld",
307181254a7Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
308181254a7Smrg (long int) rank);
309181254a7Smrg
310181254a7Smrg if (unlikely (compile_options.bounds_check))
311181254a7Smrg bounds_ifunction_return ((array_t *) retarray, extent,
312181254a7Smrg "return value", "FINDLOC");
313181254a7Smrg }
314181254a7Smrg
315181254a7Smrg for (n = 0; n < rank; n++)
316181254a7Smrg {
317181254a7Smrg count[n] = 0;
318181254a7Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
319181254a7Smrg if (extent[n] <= 0)
320181254a7Smrg return;
321181254a7Smrg }
322181254a7Smrg
323181254a7Smrg dest = retarray->base_addr;
324181254a7Smrg continue_loop = 1;
325181254a7Smrg
326181254a7Smrg base = array->base_addr;
327181254a7Smrg while (continue_loop)
328181254a7Smrg {
329181254a7Smrg const GFC_REAL_10 * restrict src;
330181254a7Smrg const GFC_LOGICAL_1 * restrict msrc;
331181254a7Smrg index_type result;
332181254a7Smrg
333181254a7Smrg result = 0;
334181254a7Smrg if (back)
335181254a7Smrg {
336181254a7Smrg src = base + (len - 1) * delta * 1;
337181254a7Smrg msrc = mbase + (len - 1) * mdelta;
338181254a7Smrg for (n = len; n > 0; n--, src -= delta * 1, msrc -= mdelta)
339181254a7Smrg {
340181254a7Smrg if (*msrc && *src == value)
341181254a7Smrg {
342181254a7Smrg result = n;
343181254a7Smrg break;
344181254a7Smrg }
345181254a7Smrg }
346181254a7Smrg }
347181254a7Smrg else
348181254a7Smrg {
349181254a7Smrg src = base;
350181254a7Smrg msrc = mbase;
351181254a7Smrg for (n = 1; n <= len; n++, src += delta * 1, msrc += mdelta)
352181254a7Smrg {
353181254a7Smrg if (*msrc && *src == value)
354181254a7Smrg {
355181254a7Smrg result = n;
356181254a7Smrg break;
357181254a7Smrg }
358181254a7Smrg }
359181254a7Smrg }
360181254a7Smrg *dest = result;
361181254a7Smrg
362181254a7Smrg count[0]++;
363181254a7Smrg base += sstride[0] * 1;
364181254a7Smrg mbase += mstride[0];
365181254a7Smrg dest += dstride[0];
366181254a7Smrg n = 0;
367181254a7Smrg while (count[n] == extent[n])
368181254a7Smrg {
369181254a7Smrg count[n] = 0;
370181254a7Smrg base -= sstride[n] * extent[n] * 1;
371181254a7Smrg mbase -= mstride[n] * extent[n];
372181254a7Smrg dest -= dstride[n] * extent[n];
373181254a7Smrg n++;
374181254a7Smrg if (n >= rank)
375181254a7Smrg {
376181254a7Smrg continue_loop = 0;
377181254a7Smrg break;
378181254a7Smrg }
379181254a7Smrg else
380181254a7Smrg {
381181254a7Smrg count[n]++;
382181254a7Smrg base += sstride[n] * 1;
383181254a7Smrg dest += dstride[n];
384181254a7Smrg }
385181254a7Smrg }
386181254a7Smrg }
387181254a7Smrg }
388181254a7Smrg extern void sfindloc1_r10 (gfc_array_index_type * const restrict retarray,
389181254a7Smrg gfc_array_r10 * const restrict array, GFC_REAL_10 value,
390181254a7Smrg const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
391181254a7Smrg GFC_LOGICAL_4 back);
392181254a7Smrg export_proto(sfindloc1_r10);
393181254a7Smrg
394181254a7Smrg extern void
sfindloc1_r10(gfc_array_index_type * const restrict retarray,gfc_array_r10 * const restrict array,GFC_REAL_10 value,const index_type * restrict pdim,GFC_LOGICAL_4 * const restrict mask,GFC_LOGICAL_4 back)395181254a7Smrg sfindloc1_r10 (gfc_array_index_type * const restrict retarray,
396181254a7Smrg gfc_array_r10 * const restrict array, GFC_REAL_10 value,
397181254a7Smrg const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
398181254a7Smrg GFC_LOGICAL_4 back)
399181254a7Smrg {
400181254a7Smrg index_type count[GFC_MAX_DIMENSIONS];
401181254a7Smrg index_type extent[GFC_MAX_DIMENSIONS];
402181254a7Smrg index_type dstride[GFC_MAX_DIMENSIONS];
403181254a7Smrg index_type * restrict dest;
404181254a7Smrg index_type rank;
405181254a7Smrg index_type n;
406181254a7Smrg index_type len;
407181254a7Smrg index_type dim;
408181254a7Smrg bool continue_loop;
409181254a7Smrg
410181254a7Smrg if (mask == NULL || *mask)
411181254a7Smrg {
412181254a7Smrg findloc1_r10 (retarray, array, value, pdim, back);
413181254a7Smrg return;
414181254a7Smrg }
415181254a7Smrg /* Make dim zero based to avoid confusion. */
416181254a7Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
417181254a7Smrg dim = (*pdim) - 1;
418181254a7Smrg
419181254a7Smrg if (unlikely (dim < 0 || dim > rank))
420181254a7Smrg {
421181254a7Smrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
422181254a7Smrg "is %ld, should be between 1 and %ld",
423181254a7Smrg (long int) dim + 1, (long int) rank + 1);
424181254a7Smrg }
425181254a7Smrg
426181254a7Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
427181254a7Smrg if (len < 0)
428181254a7Smrg len = 0;
429181254a7Smrg
430181254a7Smrg for (n = 0; n < dim; n++)
431181254a7Smrg {
432181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
433181254a7Smrg
434181254a7Smrg if (extent[n] <= 0)
435181254a7Smrg extent[n] = 0;
436181254a7Smrg }
437181254a7Smrg
438181254a7Smrg for (n = dim; n < rank; n++)
439181254a7Smrg {
440181254a7Smrg extent[n] =
441181254a7Smrg GFC_DESCRIPTOR_EXTENT(array,n + 1);
442181254a7Smrg
443181254a7Smrg if (extent[n] <= 0)
444181254a7Smrg extent[n] = 0;
445181254a7Smrg }
446181254a7Smrg
447181254a7Smrg
448181254a7Smrg if (retarray->base_addr == NULL)
449181254a7Smrg {
450181254a7Smrg size_t alloc_size, str;
451181254a7Smrg
452181254a7Smrg for (n = 0; n < rank; n++)
453181254a7Smrg {
454181254a7Smrg if (n == 0)
455181254a7Smrg str = 1;
456181254a7Smrg else
457181254a7Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
458181254a7Smrg
459181254a7Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
460181254a7Smrg }
461181254a7Smrg
462181254a7Smrg retarray->offset = 0;
463181254a7Smrg retarray->dtype.rank = rank;
464181254a7Smrg
465181254a7Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
466181254a7Smrg
467181254a7Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
468181254a7Smrg if (alloc_size == 0)
469181254a7Smrg {
470181254a7Smrg /* Make sure we have a zero-sized array. */
471181254a7Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
472181254a7Smrg return;
473181254a7Smrg }
474181254a7Smrg }
475181254a7Smrg else
476181254a7Smrg {
477181254a7Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
478181254a7Smrg runtime_error ("rank of return array incorrect in"
479181254a7Smrg " FINDLOC intrinsic: is %ld, should be %ld",
480181254a7Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
481181254a7Smrg (long int) rank);
482181254a7Smrg
483181254a7Smrg if (unlikely (compile_options.bounds_check))
484181254a7Smrg bounds_ifunction_return ((array_t *) retarray, extent,
485181254a7Smrg "return value", "FINDLOC");
486181254a7Smrg }
487181254a7Smrg
488181254a7Smrg for (n = 0; n < rank; n++)
489181254a7Smrg {
490181254a7Smrg count[n] = 0;
491181254a7Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
492181254a7Smrg if (extent[n] <= 0)
493181254a7Smrg return;
494181254a7Smrg }
495181254a7Smrg dest = retarray->base_addr;
496181254a7Smrg continue_loop = 1;
497181254a7Smrg
498181254a7Smrg while (continue_loop)
499181254a7Smrg {
500181254a7Smrg *dest = 0;
501181254a7Smrg
502181254a7Smrg count[0]++;
503181254a7Smrg dest += dstride[0];
504181254a7Smrg n = 0;
505181254a7Smrg while (count[n] == extent[n])
506181254a7Smrg {
507181254a7Smrg count[n] = 0;
508181254a7Smrg dest -= dstride[n] * extent[n];
509181254a7Smrg n++;
510181254a7Smrg if (n >= rank)
511181254a7Smrg {
512181254a7Smrg continue_loop = 0;
513181254a7Smrg break;
514181254a7Smrg }
515181254a7Smrg else
516181254a7Smrg {
517181254a7Smrg count[n]++;
518181254a7Smrg dest += dstride[n];
519181254a7Smrg }
520181254a7Smrg }
521181254a7Smrg }
522181254a7Smrg }
523181254a7Smrg #endif
524