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