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