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