ifindloc1.m4 revision 1.1 1 1.1 mrg `/* Implementation of the FINDLOC intrinsic
2 1.1 mrg Copyright (C) 2018-2019 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 mrg {
101 1.1 mrg /* Make sure we have a zero-sized array. */
102 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
103 1.1 mrg return;
104 1.1 mrg }
105 1.1 mrg }
106 1.1 mrg else
107 1.1 mrg {
108 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
109 1.1 mrg runtime_error ("rank of return array incorrect in"
110 1.1 mrg " FINDLOC intrinsic: is %ld, should be %ld",
111 1.1 mrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
112 1.1 mrg (long int) rank);
113 1.1 mrg
114 1.1 mrg if (unlikely (compile_options.bounds_check))
115 1.1 mrg bounds_ifunction_return ((array_t *) retarray, extent,
116 1.1 mrg "return value", "FINDLOC");
117 1.1 mrg }
118 1.1 mrg
119 1.1 mrg for (n = 0; n < rank; n++)
120 1.1 mrg {
121 1.1 mrg count[n] = 0;
122 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
123 1.1 mrg if (extent[n] <= 0)
124 1.1 mrg return;
125 1.1 mrg }
126 1.1 mrg
127 1.1 mrg dest = retarray->base_addr;
128 1.1 mrg continue_loop = 1;
129 1.1 mrg
130 1.1 mrg base = array->base_addr;
131 1.1 mrg while (continue_loop)
132 1.1 mrg {
133 1.1 mrg const 'atype_name`'` * restrict src;
134 1.1 mrg index_type result;
135 1.1 mrg
136 1.1 mrg result = 0;
137 1.1 mrg if (back)
138 1.1 mrg {
139 1.1 mrg src = base + (len - 1) * delta * 'base_mult`;
140 1.1 mrg for (n = len; n > 0; n--, src -= delta * 'base_mult`)
141 1.1 mrg {
142 1.1 mrg if ('comparison`'`)
143 1.1 mrg {
144 1.1 mrg result = n;
145 1.1 mrg break;
146 1.1 mrg }
147 1.1 mrg }
148 1.1 mrg }
149 1.1 mrg else
150 1.1 mrg {
151 1.1 mrg src = base;
152 1.1 mrg for (n = 1; n <= len; n++, src += delta * 'base_mult`)
153 1.1 mrg {
154 1.1 mrg if ('comparison`'`)
155 1.1 mrg {
156 1.1 mrg result = n;
157 1.1 mrg break;
158 1.1 mrg }
159 1.1 mrg }
160 1.1 mrg }
161 1.1 mrg *dest = result;
162 1.1 mrg
163 1.1 mrg count[0]++;
164 1.1 mrg base += sstride[0] * 'base_mult`;
165 1.1 mrg dest += dstride[0];
166 1.1 mrg n = 0;
167 1.1 mrg while (count[n] == extent[n])
168 1.1 mrg {
169 1.1 mrg count[n] = 0;
170 1.1 mrg base -= sstride[n] * extent[n] * 'base_mult`;
171 1.1 mrg dest -= dstride[n] * extent[n];
172 1.1 mrg n++;
173 1.1 mrg if (n >= rank)
174 1.1 mrg {
175 1.1 mrg continue_loop = 0;
176 1.1 mrg break;
177 1.1 mrg }
178 1.1 mrg else
179 1.1 mrg {
180 1.1 mrg count[n]++;
181 1.1 mrg base += sstride[n] * 'base_mult`;
182 1.1 mrg dest += dstride[n];
183 1.1 mrg }
184 1.1 mrg }
185 1.1 mrg }
186 1.1 mrg }
187 1.1 mrg 'header2`'`
188 1.1 mrg {
189 1.1 mrg index_type count[GFC_MAX_DIMENSIONS];
190 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS];
191 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS];
192 1.1 mrg index_type mstride[GFC_MAX_DIMENSIONS];
193 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS];
194 1.1 mrg const 'atype_name`'` * restrict base;
195 1.1 mrg const GFC_LOGICAL_1 * restrict mbase;
196 1.1 mrg index_type * restrict dest;
197 1.1 mrg index_type rank;
198 1.1 mrg index_type n;
199 1.1 mrg index_type len;
200 1.1 mrg index_type delta;
201 1.1 mrg index_type mdelta;
202 1.1 mrg index_type dim;
203 1.1 mrg int mask_kind;
204 1.1 mrg int continue_loop;
205 1.1 mrg
206 1.1 mrg /* Make dim zero based to avoid confusion. */
207 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
208 1.1 mrg dim = (*pdim) - 1;
209 1.1 mrg
210 1.1 mrg if (unlikely (dim < 0 || dim > rank))
211 1.1 mrg {
212 1.1 mrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
213 1.1 mrg "is %ld, should be between 1 and %ld",
214 1.1 mrg (long int) dim + 1, (long int) rank + 1);
215 1.1 mrg }
216 1.1 mrg
217 1.1 mrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
218 1.1 mrg if (len < 0)
219 1.1 mrg len = 0;
220 1.1 mrg
221 1.1 mrg delta = GFC_DESCRIPTOR_STRIDE(array,dim);
222 1.1 mrg mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
223 1.1 mrg
224 1.1 mrg mbase = mask->base_addr;
225 1.1 mrg
226 1.1 mrg mask_kind = GFC_DESCRIPTOR_SIZE (mask);
227 1.1 mrg
228 1.1 mrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
229 1.1 mrg #ifdef HAVE_GFC_LOGICAL_16
230 1.1 mrg || mask_kind == 16
231 1.1 mrg #endif
232 1.1 mrg )
233 1.1 mrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
234 1.1 mrg else
235 1.1 mrg internal_error (NULL, "Funny sized logical array");
236 1.1 mrg
237 1.1 mrg for (n = 0; n < dim; n++)
238 1.1 mrg {
239 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
240 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
241 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
242 1.1 mrg
243 1.1 mrg if (extent[n] < 0)
244 1.1 mrg extent[n] = 0;
245 1.1 mrg }
246 1.1 mrg for (n = dim; n < rank; n++)
247 1.1 mrg {
248 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
249 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
250 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
251 1.1 mrg
252 1.1 mrg if (extent[n] < 0)
253 1.1 mrg extent[n] = 0;
254 1.1 mrg }
255 1.1 mrg
256 1.1 mrg if (retarray->base_addr == NULL)
257 1.1 mrg {
258 1.1 mrg size_t alloc_size, str;
259 1.1 mrg
260 1.1 mrg for (n = 0; n < rank; n++)
261 1.1 mrg {
262 1.1 mrg if (n == 0)
263 1.1 mrg str = 1;
264 1.1 mrg else
265 1.1 mrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
266 1.1 mrg
267 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
268 1.1 mrg
269 1.1 mrg }
270 1.1 mrg
271 1.1 mrg retarray->offset = 0;
272 1.1 mrg retarray->dtype.rank = rank;
273 1.1 mrg
274 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
275 1.1 mrg
276 1.1 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
277 1.1 mrg if (alloc_size == 0)
278 1.1 mrg {
279 1.1 mrg /* Make sure we have a zero-sized array. */
280 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
281 1.1 mrg return;
282 1.1 mrg }
283 1.1 mrg }
284 1.1 mrg else
285 1.1 mrg {
286 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
287 1.1 mrg runtime_error ("rank of return array incorrect in"
288 1.1 mrg " FINDLOC intrinsic: is %ld, should be %ld",
289 1.1 mrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
290 1.1 mrg (long int) rank);
291 1.1 mrg
292 1.1 mrg if (unlikely (compile_options.bounds_check))
293 1.1 mrg bounds_ifunction_return ((array_t *) retarray, extent,
294 1.1 mrg "return value", "FINDLOC");
295 1.1 mrg }
296 1.1 mrg
297 1.1 mrg for (n = 0; n < rank; n++)
298 1.1 mrg {
299 1.1 mrg count[n] = 0;
300 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
301 1.1 mrg if (extent[n] <= 0)
302 1.1 mrg return;
303 1.1 mrg }
304 1.1 mrg
305 1.1 mrg dest = retarray->base_addr;
306 1.1 mrg continue_loop = 1;
307 1.1 mrg
308 1.1 mrg base = array->base_addr;
309 1.1 mrg while (continue_loop)
310 1.1 mrg {
311 1.1 mrg const 'atype_name`'` * restrict src;
312 1.1 mrg const GFC_LOGICAL_1 * restrict msrc;
313 1.1 mrg index_type result;
314 1.1 mrg
315 1.1 mrg result = 0;
316 1.1 mrg if (back)
317 1.1 mrg {
318 1.1 mrg src = base + (len - 1) * delta * 'base_mult`;
319 1.1 mrg msrc = mbase + (len - 1) * mdelta;
320 1.1 mrg for (n = len; n > 0; n--, src -= delta * 'base_mult`, msrc -= mdelta)
321 1.1 mrg {
322 1.1 mrg if (*msrc && 'comparison`'`)
323 1.1 mrg {
324 1.1 mrg result = n;
325 1.1 mrg break;
326 1.1 mrg }
327 1.1 mrg }
328 1.1 mrg }
329 1.1 mrg else
330 1.1 mrg {
331 1.1 mrg src = base;
332 1.1 mrg msrc = mbase;
333 1.1 mrg for (n = 1; n <= len; n++, src += delta * 'base_mult`, msrc += mdelta)
334 1.1 mrg {
335 1.1 mrg if (*msrc && 'comparison`'`)
336 1.1 mrg {
337 1.1 mrg result = n;
338 1.1 mrg break;
339 1.1 mrg }
340 1.1 mrg }
341 1.1 mrg }
342 1.1 mrg *dest = result;
343 1.1 mrg
344 1.1 mrg count[0]++;
345 1.1 mrg base += sstride[0] * 'base_mult`;
346 1.1 mrg mbase += mstride[0];
347 1.1 mrg dest += dstride[0];
348 1.1 mrg n = 0;
349 1.1 mrg while (count[n] == extent[n])
350 1.1 mrg {
351 1.1 mrg count[n] = 0;
352 1.1 mrg base -= sstride[n] * extent[n] * 'base_mult`;
353 1.1 mrg mbase -= mstride[n] * extent[n];
354 1.1 mrg dest -= dstride[n] * extent[n];
355 1.1 mrg n++;
356 1.1 mrg if (n >= rank)
357 1.1 mrg {
358 1.1 mrg continue_loop = 0;
359 1.1 mrg break;
360 1.1 mrg }
361 1.1 mrg else
362 1.1 mrg {
363 1.1 mrg count[n]++;
364 1.1 mrg base += sstride[n] * 'base_mult`;
365 1.1 mrg dest += dstride[n];
366 1.1 mrg }
367 1.1 mrg }
368 1.1 mrg }
369 1.1 mrg }
370 1.1 mrg 'header3`'`
371 1.1 mrg {
372 1.1 mrg index_type count[GFC_MAX_DIMENSIONS];
373 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS];
374 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS];
375 1.1 mrg index_type * restrict dest;
376 1.1 mrg index_type rank;
377 1.1 mrg index_type n;
378 1.1 mrg index_type len;
379 1.1 mrg index_type dim;
380 1.1 mrg bool continue_loop;
381 1.1 mrg
382 1.1 mrg if (mask == NULL || *mask)
383 1.1 mrg {
384 1.1 mrg findloc1_'atype_code`'` (retarray, array, value, pdim, back'len_arg`'`);
385 1.1 mrg return;
386 1.1 mrg }
387 1.1 mrg /* Make dim zero based to avoid confusion. */
388 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
389 1.1 mrg dim = (*pdim) - 1;
390 1.1 mrg
391 1.1 mrg if (unlikely (dim < 0 || dim > rank))
392 1.1 mrg {
393 1.1 mrg runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
394 1.1 mrg "is %ld, should be between 1 and %ld",
395 1.1 mrg (long int) dim + 1, (long int) rank + 1);
396 1.1 mrg }
397 1.1 mrg
398 1.1 mrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
399 1.1 mrg if (len < 0)
400 1.1 mrg len = 0;
401 1.1 mrg
402 1.1 mrg for (n = 0; n < dim; n++)
403 1.1 mrg {
404 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
405 1.1 mrg
406 1.1 mrg if (extent[n] <= 0)
407 1.1 mrg extent[n] = 0;
408 1.1 mrg }
409 1.1 mrg
410 1.1 mrg for (n = dim; n < rank; n++)
411 1.1 mrg {
412 1.1 mrg extent[n] =
413 1.1 mrg GFC_DESCRIPTOR_EXTENT(array,n + 1);
414 1.1 mrg
415 1.1 mrg if (extent[n] <= 0)
416 1.1 mrg extent[n] = 0;
417 1.1 mrg }
418 1.1 mrg
419 1.1 mrg
420 1.1 mrg if (retarray->base_addr == NULL)
421 1.1 mrg {
422 1.1 mrg size_t alloc_size, str;
423 1.1 mrg
424 1.1 mrg for (n = 0; n < rank; n++)
425 1.1 mrg {
426 1.1 mrg if (n == 0)
427 1.1 mrg str = 1;
428 1.1 mrg else
429 1.1 mrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
430 1.1 mrg
431 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
432 1.1 mrg }
433 1.1 mrg
434 1.1 mrg retarray->offset = 0;
435 1.1 mrg retarray->dtype.rank = rank;
436 1.1 mrg
437 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
438 1.1 mrg
439 1.1 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
440 1.1 mrg if (alloc_size == 0)
441 1.1 mrg {
442 1.1 mrg /* Make sure we have a zero-sized array. */
443 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
444 1.1 mrg return;
445 1.1 mrg }
446 1.1 mrg }
447 1.1 mrg else
448 1.1 mrg {
449 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
450 1.1 mrg runtime_error ("rank of return array incorrect in"
451 1.1 mrg " FINDLOC intrinsic: is %ld, should be %ld",
452 1.1 mrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
453 1.1 mrg (long int) rank);
454 1.1 mrg
455 1.1 mrg if (unlikely (compile_options.bounds_check))
456 1.1 mrg bounds_ifunction_return ((array_t *) retarray, extent,
457 1.1 mrg "return value", "FINDLOC");
458 1.1 mrg }
459 1.1 mrg
460 1.1 mrg for (n = 0; n < rank; n++)
461 1.1 mrg {
462 1.1 mrg count[n] = 0;
463 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
464 1.1 mrg if (extent[n] <= 0)
465 1.1 mrg return;
466 1.1 mrg }
467 1.1 mrg dest = retarray->base_addr;
468 1.1 mrg continue_loop = 1;
469 1.1 mrg
470 1.1 mrg while (continue_loop)
471 1.1 mrg {
472 1.1 mrg *dest = 0;
473 1.1 mrg
474 1.1 mrg count[0]++;
475 1.1 mrg dest += dstride[0];
476 1.1 mrg n = 0;
477 1.1 mrg while (count[n] == extent[n])
478 1.1 mrg {
479 1.1 mrg count[n] = 0;
480 1.1 mrg dest -= dstride[n] * extent[n];
481 1.1 mrg n++;
482 1.1 mrg if (n >= rank)
483 1.1 mrg {
484 1.1 mrg continue_loop = 0;
485 1.1 mrg break;
486 1.1 mrg }
487 1.1 mrg else
488 1.1 mrg {
489 1.1 mrg count[n]++;
490 1.1 mrg dest += dstride[n];
491 1.1 mrg }
492 1.1 mrg }
493 1.1 mrg }
494 1.1 mrg }
495 1.1 mrg #endif'
496