1627f7eb2Smrg /* Implementation of the FINDLOC intrinsic
2*4c3eb207Smrg Copyright (C) 2018-2020 Free Software Foundation, Inc.
3627f7eb2Smrg Contributed by Thomas König <tk@tkoenig.net>
4627f7eb2Smrg
5627f7eb2Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
6627f7eb2Smrg
7627f7eb2Smrg Libgfortran is free software; you can redistribute it and/or
8627f7eb2Smrg modify it under the terms of the GNU General Public
9627f7eb2Smrg License as published by the Free Software Foundation; either
10627f7eb2Smrg version 3 of the License, or (at your option) any later version.
11627f7eb2Smrg
12627f7eb2Smrg Libgfortran is distributed in the hope that it will be useful,
13627f7eb2Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14627f7eb2Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15627f7eb2Smrg GNU General Public License for more details.
16627f7eb2Smrg
17627f7eb2Smrg Under Section 7 of GPL version 3, you are granted additional
18627f7eb2Smrg permissions described in the GCC Runtime Library Exception, version
19627f7eb2Smrg 3.1, as published by the Free Software Foundation.
20627f7eb2Smrg
21627f7eb2Smrg You should have received a copy of the GNU General Public License and
22627f7eb2Smrg a copy of the GCC Runtime Library Exception along with this program;
23627f7eb2Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24627f7eb2Smrg <http://www.gnu.org/licenses/>. */
25627f7eb2Smrg
26627f7eb2Smrg #include "libgfortran.h"
27627f7eb2Smrg #include <assert.h>
28627f7eb2Smrg
29627f7eb2Smrg #if defined (HAVE_GFC_REAL_8)
30627f7eb2Smrg extern void findloc1_r8 (gfc_array_index_type * const restrict retarray,
31627f7eb2Smrg gfc_array_r8 * const restrict array, GFC_REAL_8 value,
32627f7eb2Smrg const index_type * restrict pdim, GFC_LOGICAL_4 back);
33627f7eb2Smrg export_proto(findloc1_r8);
34627f7eb2Smrg
35627f7eb2Smrg extern void
findloc1_r8(gfc_array_index_type * const restrict retarray,gfc_array_r8 * const restrict array,GFC_REAL_8 value,const index_type * restrict pdim,GFC_LOGICAL_4 back)36627f7eb2Smrg findloc1_r8 (gfc_array_index_type * const restrict retarray,
37627f7eb2Smrg gfc_array_r8 * const restrict array, GFC_REAL_8 value,
38627f7eb2Smrg const index_type * restrict pdim, GFC_LOGICAL_4 back)
39627f7eb2Smrg {
40627f7eb2Smrg index_type count[GFC_MAX_DIMENSIONS];
41627f7eb2Smrg index_type extent[GFC_MAX_DIMENSIONS];
42627f7eb2Smrg index_type sstride[GFC_MAX_DIMENSIONS];
43627f7eb2Smrg index_type dstride[GFC_MAX_DIMENSIONS];
44627f7eb2Smrg const GFC_REAL_8 * restrict base;
45627f7eb2Smrg index_type * restrict dest;
46627f7eb2Smrg index_type rank;
47627f7eb2Smrg index_type n;
48627f7eb2Smrg index_type len;
49627f7eb2Smrg index_type delta;
50627f7eb2Smrg index_type dim;
51627f7eb2Smrg int continue_loop;
52627f7eb2Smrg
53627f7eb2Smrg /* Make dim zero based to avoid confusion. */
54627f7eb2Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
55627f7eb2Smrg dim = (*pdim) - 1;
56627f7eb2Smrg
57627f7eb2Smrg if (unlikely (dim < 0 || dim > rank))
58627f7eb2Smrg {
59627f7eb2Smrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
60627f7eb2Smrg "is %ld, should be between 1 and %ld",
61627f7eb2Smrg (long int) dim + 1, (long int) rank + 1);
62627f7eb2Smrg }
63627f7eb2Smrg
64627f7eb2Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
65627f7eb2Smrg if (len < 0)
66627f7eb2Smrg len = 0;
67627f7eb2Smrg delta = GFC_DESCRIPTOR_STRIDE(array,dim);
68627f7eb2Smrg
69627f7eb2Smrg for (n = 0; n < dim; n++)
70627f7eb2Smrg {
71627f7eb2Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
72627f7eb2Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
73627f7eb2Smrg
74627f7eb2Smrg if (extent[n] < 0)
75627f7eb2Smrg extent[n] = 0;
76627f7eb2Smrg }
77627f7eb2Smrg for (n = dim; n < rank; n++)
78627f7eb2Smrg {
79627f7eb2Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
80627f7eb2Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
81627f7eb2Smrg
82627f7eb2Smrg if (extent[n] < 0)
83627f7eb2Smrg extent[n] = 0;
84627f7eb2Smrg }
85627f7eb2Smrg
86627f7eb2Smrg if (retarray->base_addr == NULL)
87627f7eb2Smrg {
88627f7eb2Smrg size_t alloc_size, str;
89627f7eb2Smrg
90627f7eb2Smrg for (n = 0; n < rank; n++)
91627f7eb2Smrg {
92627f7eb2Smrg if (n == 0)
93627f7eb2Smrg str = 1;
94627f7eb2Smrg else
95627f7eb2Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
96627f7eb2Smrg
97627f7eb2Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
98627f7eb2Smrg
99627f7eb2Smrg }
100627f7eb2Smrg
101627f7eb2Smrg retarray->offset = 0;
102627f7eb2Smrg retarray->dtype.rank = rank;
103627f7eb2Smrg
104627f7eb2Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
105627f7eb2Smrg
106627f7eb2Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
107627f7eb2Smrg if (alloc_size == 0)
108627f7eb2Smrg {
109627f7eb2Smrg /* Make sure we have a zero-sized array. */
110627f7eb2Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
111627f7eb2Smrg return;
112627f7eb2Smrg }
113627f7eb2Smrg }
114627f7eb2Smrg else
115627f7eb2Smrg {
116627f7eb2Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
117627f7eb2Smrg runtime_error ("rank of return array incorrect in"
118627f7eb2Smrg " FINDLOC intrinsic: is %ld, should be %ld",
119627f7eb2Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
120627f7eb2Smrg (long int) rank);
121627f7eb2Smrg
122627f7eb2Smrg if (unlikely (compile_options.bounds_check))
123627f7eb2Smrg bounds_ifunction_return ((array_t *) retarray, extent,
124627f7eb2Smrg "return value", "FINDLOC");
125627f7eb2Smrg }
126627f7eb2Smrg
127627f7eb2Smrg for (n = 0; n < rank; n++)
128627f7eb2Smrg {
129627f7eb2Smrg count[n] = 0;
130627f7eb2Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
131627f7eb2Smrg if (extent[n] <= 0)
132627f7eb2Smrg return;
133627f7eb2Smrg }
134627f7eb2Smrg
135627f7eb2Smrg dest = retarray->base_addr;
136627f7eb2Smrg continue_loop = 1;
137627f7eb2Smrg
138627f7eb2Smrg base = array->base_addr;
139627f7eb2Smrg while (continue_loop)
140627f7eb2Smrg {
141627f7eb2Smrg const GFC_REAL_8 * restrict src;
142627f7eb2Smrg index_type result;
143627f7eb2Smrg
144627f7eb2Smrg result = 0;
145627f7eb2Smrg if (back)
146627f7eb2Smrg {
147627f7eb2Smrg src = base + (len - 1) * delta * 1;
148627f7eb2Smrg for (n = len; n > 0; n--, src -= delta * 1)
149627f7eb2Smrg {
150627f7eb2Smrg if (*src == value)
151627f7eb2Smrg {
152627f7eb2Smrg result = n;
153627f7eb2Smrg break;
154627f7eb2Smrg }
155627f7eb2Smrg }
156627f7eb2Smrg }
157627f7eb2Smrg else
158627f7eb2Smrg {
159627f7eb2Smrg src = base;
160627f7eb2Smrg for (n = 1; n <= len; n++, src += delta * 1)
161627f7eb2Smrg {
162627f7eb2Smrg if (*src == value)
163627f7eb2Smrg {
164627f7eb2Smrg result = n;
165627f7eb2Smrg break;
166627f7eb2Smrg }
167627f7eb2Smrg }
168627f7eb2Smrg }
169627f7eb2Smrg *dest = result;
170627f7eb2Smrg
171627f7eb2Smrg count[0]++;
172627f7eb2Smrg base += sstride[0] * 1;
173627f7eb2Smrg dest += dstride[0];
174627f7eb2Smrg n = 0;
175627f7eb2Smrg while (count[n] == extent[n])
176627f7eb2Smrg {
177627f7eb2Smrg count[n] = 0;
178627f7eb2Smrg base -= sstride[n] * extent[n] * 1;
179627f7eb2Smrg dest -= dstride[n] * extent[n];
180627f7eb2Smrg n++;
181627f7eb2Smrg if (n >= rank)
182627f7eb2Smrg {
183627f7eb2Smrg continue_loop = 0;
184627f7eb2Smrg break;
185627f7eb2Smrg }
186627f7eb2Smrg else
187627f7eb2Smrg {
188627f7eb2Smrg count[n]++;
189627f7eb2Smrg base += sstride[n] * 1;
190627f7eb2Smrg dest += dstride[n];
191627f7eb2Smrg }
192627f7eb2Smrg }
193627f7eb2Smrg }
194627f7eb2Smrg }
195627f7eb2Smrg extern void mfindloc1_r8 (gfc_array_index_type * const restrict retarray,
196627f7eb2Smrg gfc_array_r8 * const restrict array, GFC_REAL_8 value,
197627f7eb2Smrg const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
198627f7eb2Smrg GFC_LOGICAL_4 back);
199627f7eb2Smrg export_proto(mfindloc1_r8);
200627f7eb2Smrg
201627f7eb2Smrg extern void
mfindloc1_r8(gfc_array_index_type * const restrict retarray,gfc_array_r8 * const restrict array,GFC_REAL_8 value,const index_type * restrict pdim,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back)202627f7eb2Smrg mfindloc1_r8 (gfc_array_index_type * const restrict retarray,
203627f7eb2Smrg gfc_array_r8 * const restrict array, GFC_REAL_8 value,
204627f7eb2Smrg const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
205627f7eb2Smrg GFC_LOGICAL_4 back)
206627f7eb2Smrg {
207627f7eb2Smrg index_type count[GFC_MAX_DIMENSIONS];
208627f7eb2Smrg index_type extent[GFC_MAX_DIMENSIONS];
209627f7eb2Smrg index_type sstride[GFC_MAX_DIMENSIONS];
210627f7eb2Smrg index_type mstride[GFC_MAX_DIMENSIONS];
211627f7eb2Smrg index_type dstride[GFC_MAX_DIMENSIONS];
212627f7eb2Smrg const GFC_REAL_8 * restrict base;
213627f7eb2Smrg const GFC_LOGICAL_1 * restrict mbase;
214627f7eb2Smrg index_type * restrict dest;
215627f7eb2Smrg index_type rank;
216627f7eb2Smrg index_type n;
217627f7eb2Smrg index_type len;
218627f7eb2Smrg index_type delta;
219627f7eb2Smrg index_type mdelta;
220627f7eb2Smrg index_type dim;
221627f7eb2Smrg int mask_kind;
222627f7eb2Smrg int continue_loop;
223627f7eb2Smrg
224627f7eb2Smrg /* Make dim zero based to avoid confusion. */
225627f7eb2Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
226627f7eb2Smrg dim = (*pdim) - 1;
227627f7eb2Smrg
228627f7eb2Smrg if (unlikely (dim < 0 || dim > rank))
229627f7eb2Smrg {
230627f7eb2Smrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
231627f7eb2Smrg "is %ld, should be between 1 and %ld",
232627f7eb2Smrg (long int) dim + 1, (long int) rank + 1);
233627f7eb2Smrg }
234627f7eb2Smrg
235627f7eb2Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
236627f7eb2Smrg if (len < 0)
237627f7eb2Smrg len = 0;
238627f7eb2Smrg
239627f7eb2Smrg delta = GFC_DESCRIPTOR_STRIDE(array,dim);
240627f7eb2Smrg mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
241627f7eb2Smrg
242627f7eb2Smrg mbase = mask->base_addr;
243627f7eb2Smrg
244627f7eb2Smrg mask_kind = GFC_DESCRIPTOR_SIZE (mask);
245627f7eb2Smrg
246627f7eb2Smrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
247627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
248627f7eb2Smrg || mask_kind == 16
249627f7eb2Smrg #endif
250627f7eb2Smrg )
251627f7eb2Smrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
252627f7eb2Smrg else
253627f7eb2Smrg internal_error (NULL, "Funny sized logical array");
254627f7eb2Smrg
255627f7eb2Smrg for (n = 0; n < dim; n++)
256627f7eb2Smrg {
257627f7eb2Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
258627f7eb2Smrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
259627f7eb2Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
260627f7eb2Smrg
261627f7eb2Smrg if (extent[n] < 0)
262627f7eb2Smrg extent[n] = 0;
263627f7eb2Smrg }
264627f7eb2Smrg for (n = dim; n < rank; n++)
265627f7eb2Smrg {
266627f7eb2Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
267627f7eb2Smrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
268627f7eb2Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
269627f7eb2Smrg
270627f7eb2Smrg if (extent[n] < 0)
271627f7eb2Smrg extent[n] = 0;
272627f7eb2Smrg }
273627f7eb2Smrg
274627f7eb2Smrg if (retarray->base_addr == NULL)
275627f7eb2Smrg {
276627f7eb2Smrg size_t alloc_size, str;
277627f7eb2Smrg
278627f7eb2Smrg for (n = 0; n < rank; n++)
279627f7eb2Smrg {
280627f7eb2Smrg if (n == 0)
281627f7eb2Smrg str = 1;
282627f7eb2Smrg else
283627f7eb2Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
284627f7eb2Smrg
285627f7eb2Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
286627f7eb2Smrg
287627f7eb2Smrg }
288627f7eb2Smrg
289627f7eb2Smrg retarray->offset = 0;
290627f7eb2Smrg retarray->dtype.rank = rank;
291627f7eb2Smrg
292627f7eb2Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
293627f7eb2Smrg
294627f7eb2Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
295627f7eb2Smrg if (alloc_size == 0)
296627f7eb2Smrg {
297627f7eb2Smrg /* Make sure we have a zero-sized array. */
298627f7eb2Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
299627f7eb2Smrg return;
300627f7eb2Smrg }
301627f7eb2Smrg }
302627f7eb2Smrg else
303627f7eb2Smrg {
304627f7eb2Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
305627f7eb2Smrg runtime_error ("rank of return array incorrect in"
306627f7eb2Smrg " FINDLOC intrinsic: is %ld, should be %ld",
307627f7eb2Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
308627f7eb2Smrg (long int) rank);
309627f7eb2Smrg
310627f7eb2Smrg if (unlikely (compile_options.bounds_check))
311627f7eb2Smrg bounds_ifunction_return ((array_t *) retarray, extent,
312627f7eb2Smrg "return value", "FINDLOC");
313627f7eb2Smrg }
314627f7eb2Smrg
315627f7eb2Smrg for (n = 0; n < rank; n++)
316627f7eb2Smrg {
317627f7eb2Smrg count[n] = 0;
318627f7eb2Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
319627f7eb2Smrg if (extent[n] <= 0)
320627f7eb2Smrg return;
321627f7eb2Smrg }
322627f7eb2Smrg
323627f7eb2Smrg dest = retarray->base_addr;
324627f7eb2Smrg continue_loop = 1;
325627f7eb2Smrg
326627f7eb2Smrg base = array->base_addr;
327627f7eb2Smrg while (continue_loop)
328627f7eb2Smrg {
329627f7eb2Smrg const GFC_REAL_8 * restrict src;
330627f7eb2Smrg const GFC_LOGICAL_1 * restrict msrc;
331627f7eb2Smrg index_type result;
332627f7eb2Smrg
333627f7eb2Smrg result = 0;
334627f7eb2Smrg if (back)
335627f7eb2Smrg {
336627f7eb2Smrg src = base + (len - 1) * delta * 1;
337627f7eb2Smrg msrc = mbase + (len - 1) * mdelta;
338627f7eb2Smrg for (n = len; n > 0; n--, src -= delta * 1, msrc -= mdelta)
339627f7eb2Smrg {
340627f7eb2Smrg if (*msrc && *src == value)
341627f7eb2Smrg {
342627f7eb2Smrg result = n;
343627f7eb2Smrg break;
344627f7eb2Smrg }
345627f7eb2Smrg }
346627f7eb2Smrg }
347627f7eb2Smrg else
348627f7eb2Smrg {
349627f7eb2Smrg src = base;
350627f7eb2Smrg msrc = mbase;
351627f7eb2Smrg for (n = 1; n <= len; n++, src += delta * 1, msrc += mdelta)
352627f7eb2Smrg {
353627f7eb2Smrg if (*msrc && *src == value)
354627f7eb2Smrg {
355627f7eb2Smrg result = n;
356627f7eb2Smrg break;
357627f7eb2Smrg }
358627f7eb2Smrg }
359627f7eb2Smrg }
360627f7eb2Smrg *dest = result;
361627f7eb2Smrg
362627f7eb2Smrg count[0]++;
363627f7eb2Smrg base += sstride[0] * 1;
364627f7eb2Smrg mbase += mstride[0];
365627f7eb2Smrg dest += dstride[0];
366627f7eb2Smrg n = 0;
367627f7eb2Smrg while (count[n] == extent[n])
368627f7eb2Smrg {
369627f7eb2Smrg count[n] = 0;
370627f7eb2Smrg base -= sstride[n] * extent[n] * 1;
371627f7eb2Smrg mbase -= mstride[n] * extent[n];
372627f7eb2Smrg dest -= dstride[n] * extent[n];
373627f7eb2Smrg n++;
374627f7eb2Smrg if (n >= rank)
375627f7eb2Smrg {
376627f7eb2Smrg continue_loop = 0;
377627f7eb2Smrg break;
378627f7eb2Smrg }
379627f7eb2Smrg else
380627f7eb2Smrg {
381627f7eb2Smrg count[n]++;
382627f7eb2Smrg base += sstride[n] * 1;
383627f7eb2Smrg dest += dstride[n];
384627f7eb2Smrg }
385627f7eb2Smrg }
386627f7eb2Smrg }
387627f7eb2Smrg }
388627f7eb2Smrg extern void sfindloc1_r8 (gfc_array_index_type * const restrict retarray,
389627f7eb2Smrg gfc_array_r8 * const restrict array, GFC_REAL_8 value,
390627f7eb2Smrg const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
391627f7eb2Smrg GFC_LOGICAL_4 back);
392627f7eb2Smrg export_proto(sfindloc1_r8);
393627f7eb2Smrg
394627f7eb2Smrg extern void
sfindloc1_r8(gfc_array_index_type * const restrict retarray,gfc_array_r8 * const restrict array,GFC_REAL_8 value,const index_type * restrict pdim,GFC_LOGICAL_4 * const restrict mask,GFC_LOGICAL_4 back)395627f7eb2Smrg sfindloc1_r8 (gfc_array_index_type * const restrict retarray,
396627f7eb2Smrg gfc_array_r8 * const restrict array, GFC_REAL_8 value,
397627f7eb2Smrg const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
398627f7eb2Smrg GFC_LOGICAL_4 back)
399627f7eb2Smrg {
400627f7eb2Smrg index_type count[GFC_MAX_DIMENSIONS];
401627f7eb2Smrg index_type extent[GFC_MAX_DIMENSIONS];
402627f7eb2Smrg index_type dstride[GFC_MAX_DIMENSIONS];
403627f7eb2Smrg index_type * restrict dest;
404627f7eb2Smrg index_type rank;
405627f7eb2Smrg index_type n;
406627f7eb2Smrg index_type len;
407627f7eb2Smrg index_type dim;
408627f7eb2Smrg bool continue_loop;
409627f7eb2Smrg
410627f7eb2Smrg if (mask == NULL || *mask)
411627f7eb2Smrg {
412627f7eb2Smrg findloc1_r8 (retarray, array, value, pdim, back);
413627f7eb2Smrg return;
414627f7eb2Smrg }
415627f7eb2Smrg /* Make dim zero based to avoid confusion. */
416627f7eb2Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
417627f7eb2Smrg dim = (*pdim) - 1;
418627f7eb2Smrg
419627f7eb2Smrg if (unlikely (dim < 0 || dim > rank))
420627f7eb2Smrg {
421627f7eb2Smrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
422627f7eb2Smrg "is %ld, should be between 1 and %ld",
423627f7eb2Smrg (long int) dim + 1, (long int) rank + 1);
424627f7eb2Smrg }
425627f7eb2Smrg
426627f7eb2Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
427627f7eb2Smrg if (len < 0)
428627f7eb2Smrg len = 0;
429627f7eb2Smrg
430627f7eb2Smrg for (n = 0; n < dim; n++)
431627f7eb2Smrg {
432627f7eb2Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
433627f7eb2Smrg
434627f7eb2Smrg if (extent[n] <= 0)
435627f7eb2Smrg extent[n] = 0;
436627f7eb2Smrg }
437627f7eb2Smrg
438627f7eb2Smrg for (n = dim; n < rank; n++)
439627f7eb2Smrg {
440627f7eb2Smrg extent[n] =
441627f7eb2Smrg GFC_DESCRIPTOR_EXTENT(array,n + 1);
442627f7eb2Smrg
443627f7eb2Smrg if (extent[n] <= 0)
444627f7eb2Smrg extent[n] = 0;
445627f7eb2Smrg }
446627f7eb2Smrg
447627f7eb2Smrg
448627f7eb2Smrg if (retarray->base_addr == NULL)
449627f7eb2Smrg {
450627f7eb2Smrg size_t alloc_size, str;
451627f7eb2Smrg
452627f7eb2Smrg for (n = 0; n < rank; n++)
453627f7eb2Smrg {
454627f7eb2Smrg if (n == 0)
455627f7eb2Smrg str = 1;
456627f7eb2Smrg else
457627f7eb2Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
458627f7eb2Smrg
459627f7eb2Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
460627f7eb2Smrg }
461627f7eb2Smrg
462627f7eb2Smrg retarray->offset = 0;
463627f7eb2Smrg retarray->dtype.rank = rank;
464627f7eb2Smrg
465627f7eb2Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
466627f7eb2Smrg
467627f7eb2Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
468627f7eb2Smrg if (alloc_size == 0)
469627f7eb2Smrg {
470627f7eb2Smrg /* Make sure we have a zero-sized array. */
471627f7eb2Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
472627f7eb2Smrg return;
473627f7eb2Smrg }
474627f7eb2Smrg }
475627f7eb2Smrg else
476627f7eb2Smrg {
477627f7eb2Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
478627f7eb2Smrg runtime_error ("rank of return array incorrect in"
479627f7eb2Smrg " FINDLOC intrinsic: is %ld, should be %ld",
480627f7eb2Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
481627f7eb2Smrg (long int) rank);
482627f7eb2Smrg
483627f7eb2Smrg if (unlikely (compile_options.bounds_check))
484627f7eb2Smrg bounds_ifunction_return ((array_t *) retarray, extent,
485627f7eb2Smrg "return value", "FINDLOC");
486627f7eb2Smrg }
487627f7eb2Smrg
488627f7eb2Smrg for (n = 0; n < rank; n++)
489627f7eb2Smrg {
490627f7eb2Smrg count[n] = 0;
491627f7eb2Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
492627f7eb2Smrg if (extent[n] <= 0)
493627f7eb2Smrg return;
494627f7eb2Smrg }
495627f7eb2Smrg dest = retarray->base_addr;
496627f7eb2Smrg continue_loop = 1;
497627f7eb2Smrg
498627f7eb2Smrg while (continue_loop)
499627f7eb2Smrg {
500627f7eb2Smrg *dest = 0;
501627f7eb2Smrg
502627f7eb2Smrg count[0]++;
503627f7eb2Smrg dest += dstride[0];
504627f7eb2Smrg n = 0;
505627f7eb2Smrg while (count[n] == extent[n])
506627f7eb2Smrg {
507627f7eb2Smrg count[n] = 0;
508627f7eb2Smrg dest -= dstride[n] * extent[n];
509627f7eb2Smrg n++;
510627f7eb2Smrg if (n >= rank)
511627f7eb2Smrg {
512627f7eb2Smrg continue_loop = 0;
513627f7eb2Smrg break;
514627f7eb2Smrg }
515627f7eb2Smrg else
516627f7eb2Smrg {
517627f7eb2Smrg count[n]++;
518627f7eb2Smrg dest += dstride[n];
519627f7eb2Smrg }
520627f7eb2Smrg }
521627f7eb2Smrg }
522627f7eb2Smrg }
523627f7eb2Smrg #endif
524