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