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_UINTEGER_1)
30181254a7Smrg extern void findloc1_s1 (gfc_array_index_type * const restrict retarray,
31181254a7Smrg gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *const restrict value,
32181254a7Smrg const index_type * restrict pdim, GFC_LOGICAL_4 back,
33181254a7Smrg gfc_charlen_type len_array, gfc_charlen_type len_value);
34181254a7Smrg export_proto(findloc1_s1);
35181254a7Smrg
36181254a7Smrg extern void
findloc1_s1(gfc_array_index_type * const restrict retarray,gfc_array_s1 * const restrict array,GFC_UINTEGER_1 * const restrict value,const index_type * restrict pdim,GFC_LOGICAL_4 back,gfc_charlen_type len_array,gfc_charlen_type len_value)37181254a7Smrg findloc1_s1 (gfc_array_index_type * const restrict retarray,
38181254a7Smrg gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *const restrict value,
39181254a7Smrg const index_type * restrict pdim, GFC_LOGICAL_4 back,
40181254a7Smrg gfc_charlen_type len_array, gfc_charlen_type len_value)
41181254a7Smrg {
42181254a7Smrg index_type count[GFC_MAX_DIMENSIONS];
43181254a7Smrg index_type extent[GFC_MAX_DIMENSIONS];
44181254a7Smrg index_type sstride[GFC_MAX_DIMENSIONS];
45181254a7Smrg index_type dstride[GFC_MAX_DIMENSIONS];
46181254a7Smrg const GFC_UINTEGER_1 * restrict base;
47181254a7Smrg index_type * restrict dest;
48181254a7Smrg index_type rank;
49181254a7Smrg index_type n;
50181254a7Smrg index_type len;
51181254a7Smrg index_type delta;
52181254a7Smrg index_type dim;
53181254a7Smrg int continue_loop;
54181254a7Smrg
55181254a7Smrg /* Make dim zero based to avoid confusion. */
56181254a7Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
57181254a7Smrg dim = (*pdim) - 1;
58181254a7Smrg
59181254a7Smrg if (unlikely (dim < 0 || dim > rank))
60181254a7Smrg {
61181254a7Smrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
62181254a7Smrg "is %ld, should be between 1 and %ld",
63181254a7Smrg (long int) dim + 1, (long int) rank + 1);
64181254a7Smrg }
65181254a7Smrg
66181254a7Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
67181254a7Smrg if (len < 0)
68181254a7Smrg len = 0;
69181254a7Smrg delta = GFC_DESCRIPTOR_STRIDE(array,dim);
70181254a7Smrg
71181254a7Smrg for (n = 0; n < dim; n++)
72181254a7Smrg {
73181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
74181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
75181254a7Smrg
76181254a7Smrg if (extent[n] < 0)
77181254a7Smrg extent[n] = 0;
78181254a7Smrg }
79181254a7Smrg for (n = dim; n < rank; n++)
80181254a7Smrg {
81181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
82181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
83181254a7Smrg
84181254a7Smrg if (extent[n] < 0)
85181254a7Smrg extent[n] = 0;
86181254a7Smrg }
87181254a7Smrg
88181254a7Smrg if (retarray->base_addr == NULL)
89181254a7Smrg {
90181254a7Smrg size_t alloc_size, str;
91181254a7Smrg
92181254a7Smrg for (n = 0; n < rank; n++)
93181254a7Smrg {
94181254a7Smrg if (n == 0)
95181254a7Smrg str = 1;
96181254a7Smrg else
97181254a7Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
98181254a7Smrg
99181254a7Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
100181254a7Smrg
101181254a7Smrg }
102181254a7Smrg
103181254a7Smrg retarray->offset = 0;
104181254a7Smrg retarray->dtype.rank = rank;
105181254a7Smrg
106181254a7Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
107181254a7Smrg
108181254a7Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
109181254a7Smrg if (alloc_size == 0)
110181254a7Smrg {
111181254a7Smrg /* Make sure we have a zero-sized array. */
112181254a7Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
113181254a7Smrg return;
114181254a7Smrg }
115181254a7Smrg }
116181254a7Smrg else
117181254a7Smrg {
118181254a7Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
119181254a7Smrg runtime_error ("rank of return array incorrect in"
120181254a7Smrg " FINDLOC intrinsic: is %ld, should be %ld",
121181254a7Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
122181254a7Smrg (long int) rank);
123181254a7Smrg
124181254a7Smrg if (unlikely (compile_options.bounds_check))
125181254a7Smrg bounds_ifunction_return ((array_t *) retarray, extent,
126181254a7Smrg "return value", "FINDLOC");
127181254a7Smrg }
128181254a7Smrg
129181254a7Smrg for (n = 0; n < rank; n++)
130181254a7Smrg {
131181254a7Smrg count[n] = 0;
132181254a7Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
133181254a7Smrg if (extent[n] <= 0)
134181254a7Smrg return;
135181254a7Smrg }
136181254a7Smrg
137181254a7Smrg dest = retarray->base_addr;
138181254a7Smrg continue_loop = 1;
139181254a7Smrg
140181254a7Smrg base = array->base_addr;
141181254a7Smrg while (continue_loop)
142181254a7Smrg {
143181254a7Smrg const GFC_UINTEGER_1 * restrict src;
144181254a7Smrg index_type result;
145181254a7Smrg
146181254a7Smrg result = 0;
147181254a7Smrg if (back)
148181254a7Smrg {
149181254a7Smrg src = base + (len - 1) * delta * len_array;
150181254a7Smrg for (n = len; n > 0; n--, src -= delta * len_array)
151181254a7Smrg {
152181254a7Smrg if (compare_string (len_array, (char *) src, len_value, (char *) value) == 0)
153181254a7Smrg {
154181254a7Smrg result = n;
155181254a7Smrg break;
156181254a7Smrg }
157181254a7Smrg }
158181254a7Smrg }
159181254a7Smrg else
160181254a7Smrg {
161181254a7Smrg src = base;
162181254a7Smrg for (n = 1; n <= len; n++, src += delta * len_array)
163181254a7Smrg {
164181254a7Smrg if (compare_string (len_array, (char *) src, len_value, (char *) value) == 0)
165181254a7Smrg {
166181254a7Smrg result = n;
167181254a7Smrg break;
168181254a7Smrg }
169181254a7Smrg }
170181254a7Smrg }
171181254a7Smrg *dest = result;
172181254a7Smrg
173181254a7Smrg count[0]++;
174181254a7Smrg base += sstride[0] * len_array;
175181254a7Smrg dest += dstride[0];
176181254a7Smrg n = 0;
177181254a7Smrg while (count[n] == extent[n])
178181254a7Smrg {
179181254a7Smrg count[n] = 0;
180181254a7Smrg base -= sstride[n] * extent[n] * len_array;
181181254a7Smrg dest -= dstride[n] * extent[n];
182181254a7Smrg n++;
183181254a7Smrg if (n >= rank)
184181254a7Smrg {
185181254a7Smrg continue_loop = 0;
186181254a7Smrg break;
187181254a7Smrg }
188181254a7Smrg else
189181254a7Smrg {
190181254a7Smrg count[n]++;
191181254a7Smrg base += sstride[n] * len_array;
192181254a7Smrg dest += dstride[n];
193181254a7Smrg }
194181254a7Smrg }
195181254a7Smrg }
196181254a7Smrg }
197181254a7Smrg extern void mfindloc1_s1 (gfc_array_index_type * const restrict retarray,
198181254a7Smrg gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *const restrict value,
199181254a7Smrg const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
200181254a7Smrg GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value);
201181254a7Smrg export_proto(mfindloc1_s1);
202181254a7Smrg
203181254a7Smrg extern void
mfindloc1_s1(gfc_array_index_type * const restrict retarray,gfc_array_s1 * const restrict array,GFC_UINTEGER_1 * 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)204181254a7Smrg mfindloc1_s1 (gfc_array_index_type * const restrict retarray,
205181254a7Smrg gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *const restrict value,
206181254a7Smrg const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
207181254a7Smrg GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value)
208181254a7Smrg {
209181254a7Smrg index_type count[GFC_MAX_DIMENSIONS];
210181254a7Smrg index_type extent[GFC_MAX_DIMENSIONS];
211181254a7Smrg index_type sstride[GFC_MAX_DIMENSIONS];
212181254a7Smrg index_type mstride[GFC_MAX_DIMENSIONS];
213181254a7Smrg index_type dstride[GFC_MAX_DIMENSIONS];
214181254a7Smrg const GFC_UINTEGER_1 * restrict base;
215181254a7Smrg const GFC_LOGICAL_1 * restrict mbase;
216181254a7Smrg index_type * restrict dest;
217181254a7Smrg index_type rank;
218181254a7Smrg index_type n;
219181254a7Smrg index_type len;
220181254a7Smrg index_type delta;
221181254a7Smrg index_type mdelta;
222181254a7Smrg index_type dim;
223181254a7Smrg int mask_kind;
224181254a7Smrg int continue_loop;
225181254a7Smrg
226181254a7Smrg /* Make dim zero based to avoid confusion. */
227181254a7Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
228181254a7Smrg dim = (*pdim) - 1;
229181254a7Smrg
230181254a7Smrg if (unlikely (dim < 0 || dim > rank))
231181254a7Smrg {
232181254a7Smrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
233181254a7Smrg "is %ld, should be between 1 and %ld",
234181254a7Smrg (long int) dim + 1, (long int) rank + 1);
235181254a7Smrg }
236181254a7Smrg
237181254a7Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
238181254a7Smrg if (len < 0)
239181254a7Smrg len = 0;
240181254a7Smrg
241181254a7Smrg delta = GFC_DESCRIPTOR_STRIDE(array,dim);
242181254a7Smrg mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
243181254a7Smrg
244181254a7Smrg mbase = mask->base_addr;
245181254a7Smrg
246181254a7Smrg mask_kind = GFC_DESCRIPTOR_SIZE (mask);
247181254a7Smrg
248181254a7Smrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
249181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
250181254a7Smrg || mask_kind == 16
251181254a7Smrg #endif
252181254a7Smrg )
253181254a7Smrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
254181254a7Smrg else
255181254a7Smrg internal_error (NULL, "Funny sized logical array");
256181254a7Smrg
257181254a7Smrg for (n = 0; n < dim; n++)
258181254a7Smrg {
259181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
260181254a7Smrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
261181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
262181254a7Smrg
263181254a7Smrg if (extent[n] < 0)
264181254a7Smrg extent[n] = 0;
265181254a7Smrg }
266181254a7Smrg for (n = dim; n < rank; n++)
267181254a7Smrg {
268181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
269181254a7Smrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
270181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
271181254a7Smrg
272181254a7Smrg if (extent[n] < 0)
273181254a7Smrg extent[n] = 0;
274181254a7Smrg }
275181254a7Smrg
276181254a7Smrg if (retarray->base_addr == NULL)
277181254a7Smrg {
278181254a7Smrg size_t alloc_size, str;
279181254a7Smrg
280181254a7Smrg for (n = 0; n < rank; n++)
281181254a7Smrg {
282181254a7Smrg if (n == 0)
283181254a7Smrg str = 1;
284181254a7Smrg else
285181254a7Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
286181254a7Smrg
287181254a7Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
288181254a7Smrg
289181254a7Smrg }
290181254a7Smrg
291181254a7Smrg retarray->offset = 0;
292181254a7Smrg retarray->dtype.rank = rank;
293181254a7Smrg
294181254a7Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
295181254a7Smrg
296181254a7Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
297181254a7Smrg if (alloc_size == 0)
298181254a7Smrg {
299181254a7Smrg /* Make sure we have a zero-sized array. */
300181254a7Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
301181254a7Smrg return;
302181254a7Smrg }
303181254a7Smrg }
304181254a7Smrg else
305181254a7Smrg {
306181254a7Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
307181254a7Smrg runtime_error ("rank of return array incorrect in"
308181254a7Smrg " FINDLOC intrinsic: is %ld, should be %ld",
309181254a7Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
310181254a7Smrg (long int) rank);
311181254a7Smrg
312181254a7Smrg if (unlikely (compile_options.bounds_check))
313181254a7Smrg bounds_ifunction_return ((array_t *) retarray, extent,
314181254a7Smrg "return value", "FINDLOC");
315181254a7Smrg }
316181254a7Smrg
317181254a7Smrg for (n = 0; n < rank; n++)
318181254a7Smrg {
319181254a7Smrg count[n] = 0;
320181254a7Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
321181254a7Smrg if (extent[n] <= 0)
322181254a7Smrg return;
323181254a7Smrg }
324181254a7Smrg
325181254a7Smrg dest = retarray->base_addr;
326181254a7Smrg continue_loop = 1;
327181254a7Smrg
328181254a7Smrg base = array->base_addr;
329181254a7Smrg while (continue_loop)
330181254a7Smrg {
331181254a7Smrg const GFC_UINTEGER_1 * restrict src;
332181254a7Smrg const GFC_LOGICAL_1 * restrict msrc;
333181254a7Smrg index_type result;
334181254a7Smrg
335181254a7Smrg result = 0;
336181254a7Smrg if (back)
337181254a7Smrg {
338181254a7Smrg src = base + (len - 1) * delta * len_array;
339181254a7Smrg msrc = mbase + (len - 1) * mdelta;
340181254a7Smrg for (n = len; n > 0; n--, src -= delta * len_array, msrc -= mdelta)
341181254a7Smrg {
342181254a7Smrg if (*msrc && compare_string (len_array, (char *) src, len_value, (char *) value) == 0)
343181254a7Smrg {
344181254a7Smrg result = n;
345181254a7Smrg break;
346181254a7Smrg }
347181254a7Smrg }
348181254a7Smrg }
349181254a7Smrg else
350181254a7Smrg {
351181254a7Smrg src = base;
352181254a7Smrg msrc = mbase;
353181254a7Smrg for (n = 1; n <= len; n++, src += delta * len_array, msrc += mdelta)
354181254a7Smrg {
355181254a7Smrg if (*msrc && compare_string (len_array, (char *) src, len_value, (char *) value) == 0)
356181254a7Smrg {
357181254a7Smrg result = n;
358181254a7Smrg break;
359181254a7Smrg }
360181254a7Smrg }
361181254a7Smrg }
362181254a7Smrg *dest = result;
363181254a7Smrg
364181254a7Smrg count[0]++;
365181254a7Smrg base += sstride[0] * len_array;
366181254a7Smrg mbase += mstride[0];
367181254a7Smrg dest += dstride[0];
368181254a7Smrg n = 0;
369181254a7Smrg while (count[n] == extent[n])
370181254a7Smrg {
371181254a7Smrg count[n] = 0;
372181254a7Smrg base -= sstride[n] * extent[n] * len_array;
373181254a7Smrg mbase -= mstride[n] * extent[n];
374181254a7Smrg dest -= dstride[n] * extent[n];
375181254a7Smrg n++;
376181254a7Smrg if (n >= rank)
377181254a7Smrg {
378181254a7Smrg continue_loop = 0;
379181254a7Smrg break;
380181254a7Smrg }
381181254a7Smrg else
382181254a7Smrg {
383181254a7Smrg count[n]++;
384181254a7Smrg base += sstride[n] * len_array;
385181254a7Smrg dest += dstride[n];
386181254a7Smrg }
387181254a7Smrg }
388181254a7Smrg }
389181254a7Smrg }
390181254a7Smrg extern void sfindloc1_s1 (gfc_array_index_type * const restrict retarray,
391181254a7Smrg gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *const restrict value,
392181254a7Smrg const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
393181254a7Smrg GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value);
394181254a7Smrg export_proto(sfindloc1_s1);
395181254a7Smrg
396181254a7Smrg extern void
sfindloc1_s1(gfc_array_index_type * const restrict retarray,gfc_array_s1 * const restrict array,GFC_UINTEGER_1 * 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)397181254a7Smrg sfindloc1_s1 (gfc_array_index_type * const restrict retarray,
398181254a7Smrg gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *const restrict value,
399181254a7Smrg const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
400181254a7Smrg GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value)
401181254a7Smrg {
402181254a7Smrg index_type count[GFC_MAX_DIMENSIONS];
403181254a7Smrg index_type extent[GFC_MAX_DIMENSIONS];
404181254a7Smrg index_type dstride[GFC_MAX_DIMENSIONS];
405181254a7Smrg index_type * restrict dest;
406181254a7Smrg index_type rank;
407181254a7Smrg index_type n;
408181254a7Smrg index_type len;
409181254a7Smrg index_type dim;
410181254a7Smrg bool continue_loop;
411181254a7Smrg
412181254a7Smrg if (mask == NULL || *mask)
413181254a7Smrg {
414181254a7Smrg findloc1_s1 (retarray, array, value, pdim, back, len_array, len_value);
415181254a7Smrg return;
416181254a7Smrg }
417181254a7Smrg /* Make dim zero based to avoid confusion. */
418181254a7Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
419181254a7Smrg dim = (*pdim) - 1;
420181254a7Smrg
421181254a7Smrg if (unlikely (dim < 0 || dim > rank))
422181254a7Smrg {
423181254a7Smrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
424181254a7Smrg "is %ld, should be between 1 and %ld",
425181254a7Smrg (long int) dim + 1, (long int) rank + 1);
426181254a7Smrg }
427181254a7Smrg
428181254a7Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
429181254a7Smrg if (len < 0)
430181254a7Smrg len = 0;
431181254a7Smrg
432181254a7Smrg for (n = 0; n < dim; n++)
433181254a7Smrg {
434181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
435181254a7Smrg
436181254a7Smrg if (extent[n] <= 0)
437181254a7Smrg extent[n] = 0;
438181254a7Smrg }
439181254a7Smrg
440181254a7Smrg for (n = dim; n < rank; n++)
441181254a7Smrg {
442181254a7Smrg extent[n] =
443181254a7Smrg GFC_DESCRIPTOR_EXTENT(array,n + 1);
444181254a7Smrg
445181254a7Smrg if (extent[n] <= 0)
446181254a7Smrg extent[n] = 0;
447181254a7Smrg }
448181254a7Smrg
449181254a7Smrg
450181254a7Smrg if (retarray->base_addr == NULL)
451181254a7Smrg {
452181254a7Smrg size_t alloc_size, str;
453181254a7Smrg
454181254a7Smrg for (n = 0; n < rank; n++)
455181254a7Smrg {
456181254a7Smrg if (n == 0)
457181254a7Smrg str = 1;
458181254a7Smrg else
459181254a7Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
460181254a7Smrg
461181254a7Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
462181254a7Smrg }
463181254a7Smrg
464181254a7Smrg retarray->offset = 0;
465181254a7Smrg retarray->dtype.rank = rank;
466181254a7Smrg
467181254a7Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
468181254a7Smrg
469181254a7Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
470181254a7Smrg if (alloc_size == 0)
471181254a7Smrg {
472181254a7Smrg /* Make sure we have a zero-sized array. */
473181254a7Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
474181254a7Smrg return;
475181254a7Smrg }
476181254a7Smrg }
477181254a7Smrg else
478181254a7Smrg {
479181254a7Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
480181254a7Smrg runtime_error ("rank of return array incorrect in"
481181254a7Smrg " FINDLOC intrinsic: is %ld, should be %ld",
482181254a7Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
483181254a7Smrg (long int) rank);
484181254a7Smrg
485181254a7Smrg if (unlikely (compile_options.bounds_check))
486181254a7Smrg bounds_ifunction_return ((array_t *) retarray, extent,
487181254a7Smrg "return value", "FINDLOC");
488181254a7Smrg }
489181254a7Smrg
490181254a7Smrg for (n = 0; n < rank; n++)
491181254a7Smrg {
492181254a7Smrg count[n] = 0;
493181254a7Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
494181254a7Smrg if (extent[n] <= 0)
495181254a7Smrg return;
496181254a7Smrg }
497181254a7Smrg dest = retarray->base_addr;
498181254a7Smrg continue_loop = 1;
499181254a7Smrg
500181254a7Smrg while (continue_loop)
501181254a7Smrg {
502181254a7Smrg *dest = 0;
503181254a7Smrg
504181254a7Smrg count[0]++;
505181254a7Smrg dest += dstride[0];
506181254a7Smrg n = 0;
507181254a7Smrg while (count[n] == extent[n])
508181254a7Smrg {
509181254a7Smrg count[n] = 0;
510181254a7Smrg dest -= dstride[n] * extent[n];
511181254a7Smrg n++;
512181254a7Smrg if (n >= rank)
513181254a7Smrg {
514181254a7Smrg continue_loop = 0;
515181254a7Smrg break;
516181254a7Smrg }
517181254a7Smrg else
518181254a7Smrg {
519181254a7Smrg count[n]++;
520181254a7Smrg dest += dstride[n];
521181254a7Smrg }
522181254a7Smrg }
523181254a7Smrg }
524181254a7Smrg }
525181254a7Smrg #endif
526