ifindloc0.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;
36 1.1 mrg const 'atype_name` *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 sz;
41 1.1 mrg
42 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array);
43 1.1 mrg if (rank <= 0)
44 1.1 mrg runtime_error ("Rank of array needs to be > 0");
45 1.1 mrg
46 1.1 mrg if (retarray->base_addr == NULL)
47 1.1 mrg {
48 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
49 1.1 mrg retarray->dtype.rank = 1;
50 1.1 mrg retarray->offset = 0;
51 1.1 mrg retarray->base_addr = xmallocarray (rank, sizeof (index_type));
52 1.1 mrg }
53 1.1 mrg else
54 1.1 mrg {
55 1.1 mrg if (unlikely (compile_options.bounds_check))
56 1.1 mrg bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
57 1.1 mrg "FINDLOC");
58 1.1 mrg }
59 1.1 mrg
60 1.1 mrg dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
61 1.1 mrg dest = retarray->base_addr;
62 1.1 mrg
63 1.1 mrg /* Set the return value. */
64 1.1 mrg for (n = 0; n < rank; n++)
65 1.1 mrg dest[n * dstride] = 0;
66 1.1 mrg
67 1.1 mrg sz = 1;
68 1.1 mrg for (n = 0; n < rank; n++)
69 1.1 mrg {
70 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
71 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
72 1.1 mrg sz *= extent[n];
73 1.1 mrg if (extent[n] <= 0)
74 1.1 mrg return;
75 1.1 mrg }
76 1.1 mrg
77 1.1 mrg for (n = 0; n < rank; n++)
78 1.1 mrg count[n] = 0;
79 1.1 mrg
80 1.1 mrg if (back)
81 1.1 mrg {
82 1.1 mrg base = array->base_addr + (sz - 1) * 'base_mult`'`;
83 1.1 mrg
84 1.1 mrg while (1)
85 1.1 mrg {
86 1.1 mrg do
87 1.1 mrg {
88 1.1 mrg if (unlikely('comparison`))
89 1.1 mrg {
90 1.1 mrg for (n = 0; n < rank; n++)
91 1.1 mrg dest[n * dstride] = extent[n] - count[n];
92 1.1 mrg
93 1.1 mrg return;
94 1.1 mrg }
95 1.1 mrg base -= sstride[0] * 'base_mult`'`;
96 1.1 mrg } while(++count[0] != extent[0]);
97 1.1 mrg
98 1.1 mrg n = 0;
99 1.1 mrg do
100 1.1 mrg {
101 1.1 mrg /* When we get to the end of a dimension, reset it and increment
102 1.1 mrg the next dimension. */
103 1.1 mrg count[n] = 0;
104 1.1 mrg /* We could precalculate these products, but this is a less
105 1.1 mrg frequently used path so probably not worth it. */
106 1.1 mrg base += sstride[n] * extent[n] * 'base_mult`'`;
107 1.1 mrg n++;
108 1.1 mrg if (n >= rank)
109 1.1 mrg return;
110 1.1 mrg else
111 1.1 mrg {
112 1.1 mrg count[n]++;
113 1.1 mrg base -= sstride[n] * 'base_mult`'`;
114 1.1 mrg }
115 1.1 mrg } while (count[n] == extent[n]);
116 1.1 mrg }
117 1.1 mrg }
118 1.1 mrg else
119 1.1 mrg {
120 1.1 mrg base = array->base_addr;
121 1.1 mrg while (1)
122 1.1 mrg {
123 1.1 mrg do
124 1.1 mrg {
125 1.1 mrg if (unlikely('comparison`))
126 1.1 mrg {
127 1.1 mrg for (n = 0; n < rank; n++)
128 1.1 mrg dest[n * dstride] = count[n] + 1;
129 1.1 mrg
130 1.1 mrg return;
131 1.1 mrg }
132 1.1 mrg base += sstride[0] * 'base_mult`'`;
133 1.1 mrg } while(++count[0] != extent[0]);
134 1.1 mrg
135 1.1 mrg n = 0;
136 1.1 mrg do
137 1.1 mrg {
138 1.1 mrg /* When we get to the end of a dimension, reset it and increment
139 1.1 mrg the next dimension. */
140 1.1 mrg count[n] = 0;
141 1.1 mrg /* We could precalculate these products, but this is a less
142 1.1 mrg frequently used path so probably not worth it. */
143 1.1 mrg base -= sstride[n] * extent[n] * 'base_mult`'`;
144 1.1 mrg n++;
145 1.1 mrg if (n >= rank)
146 1.1 mrg return;
147 1.1 mrg else
148 1.1 mrg {
149 1.1 mrg count[n]++;
150 1.1 mrg base += sstride[n] * 'base_mult`'`;
151 1.1 mrg }
152 1.1 mrg } while (count[n] == extent[n]);
153 1.1 mrg }
154 1.1 mrg }
155 1.1 mrg return;
156 1.1 mrg }
157 1.1 mrg
158 1.1 mrg 'header2`
159 1.1 mrg {
160 1.1 mrg index_type count[GFC_MAX_DIMENSIONS];
161 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS];
162 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS];
163 1.1 mrg index_type mstride[GFC_MAX_DIMENSIONS];
164 1.1 mrg index_type dstride;
165 1.1 mrg const 'atype_name` *base;
166 1.1 mrg index_type * restrict dest;
167 1.1 mrg GFC_LOGICAL_1 *mbase;
168 1.1 mrg index_type rank;
169 1.1 mrg index_type n;
170 1.1 mrg int mask_kind;
171 1.1 mrg index_type sz;
172 1.1 mrg
173 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array);
174 1.1 mrg if (rank <= 0)
175 1.1 mrg runtime_error ("Rank of array needs to be > 0");
176 1.1 mrg
177 1.1 mrg if (retarray->base_addr == NULL)
178 1.1 mrg {
179 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
180 1.1 mrg retarray->dtype.rank = 1;
181 1.1 mrg retarray->offset = 0;
182 1.1 mrg retarray->base_addr = xmallocarray (rank, sizeof (index_type));
183 1.1 mrg }
184 1.1 mrg else
185 1.1 mrg {
186 1.1 mrg if (unlikely (compile_options.bounds_check))
187 1.1 mrg {
188 1.1 mrg bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
189 1.1 mrg "FINDLOC");
190 1.1 mrg bounds_equal_extents ((array_t *) mask, (array_t *) array,
191 1.1 mrg "MASK argument", "FINDLOC");
192 1.1 mrg }
193 1.1 mrg }
194 1.1 mrg
195 1.1 mrg mask_kind = GFC_DESCRIPTOR_SIZE (mask);
196 1.1 mrg
197 1.1 mrg mbase = mask->base_addr;
198 1.1 mrg
199 1.1 mrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
200 1.1 mrg #ifdef HAVE_GFC_LOGICAL_16
201 1.1 mrg || mask_kind == 16
202 1.1 mrg #endif
203 1.1 mrg )
204 1.1 mrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
205 1.1 mrg else
206 1.1 mrg internal_error (NULL, "Funny sized logical array");
207 1.1 mrg
208 1.1 mrg dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
209 1.1 mrg dest = retarray->base_addr;
210 1.1 mrg
211 1.1 mrg /* Set the return value. */
212 1.1 mrg for (n = 0; n < rank; n++)
213 1.1 mrg dest[n * dstride] = 0;
214 1.1 mrg
215 1.1 mrg sz = 1;
216 1.1 mrg for (n = 0; n < rank; n++)
217 1.1 mrg {
218 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
219 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
220 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
221 1.1 mrg sz *= extent[n];
222 1.1 mrg if (extent[n] <= 0)
223 1.1 mrg return;
224 1.1 mrg }
225 1.1 mrg
226 1.1 mrg for (n = 0; n < rank; n++)
227 1.1 mrg count[n] = 0;
228 1.1 mrg
229 1.1 mrg if (back)
230 1.1 mrg {
231 1.1 mrg base = array->base_addr + (sz - 1) * 'base_mult`'`;
232 1.1 mrg mbase = mbase + (sz - 1) * mask_kind;
233 1.1 mrg while (1)
234 1.1 mrg {
235 1.1 mrg do
236 1.1 mrg {
237 1.1 mrg if (unlikely(*mbase && 'comparison`))
238 1.1 mrg {
239 1.1 mrg for (n = 0; n < rank; n++)
240 1.1 mrg dest[n * dstride] = extent[n] - count[n];
241 1.1 mrg
242 1.1 mrg return;
243 1.1 mrg }
244 1.1 mrg base -= sstride[0] * 'base_mult`'`;
245 1.1 mrg mbase -= mstride[0];
246 1.1 mrg } while(++count[0] != extent[0]);
247 1.1 mrg
248 1.1 mrg n = 0;
249 1.1 mrg do
250 1.1 mrg {
251 1.1 mrg /* When we get to the end of a dimension, reset it and increment
252 1.1 mrg the next dimension. */
253 1.1 mrg count[n] = 0;
254 1.1 mrg /* We could precalculate these products, but this is a less
255 1.1 mrg frequently used path so probably not worth it. */
256 1.1 mrg base += sstride[n] * extent[n] * 'base_mult`'`;
257 1.1 mrg mbase -= mstride[n] * extent[n];
258 1.1 mrg n++;
259 1.1 mrg if (n >= rank)
260 1.1 mrg return;
261 1.1 mrg else
262 1.1 mrg {
263 1.1 mrg count[n]++;
264 1.1 mrg base -= sstride[n] * 'base_mult`'`;
265 1.1 mrg mbase += mstride[n];
266 1.1 mrg }
267 1.1 mrg } while (count[n] == extent[n]);
268 1.1 mrg }
269 1.1 mrg }
270 1.1 mrg else
271 1.1 mrg {
272 1.1 mrg base = array->base_addr;
273 1.1 mrg while (1)
274 1.1 mrg {
275 1.1 mrg do
276 1.1 mrg {
277 1.1 mrg if (unlikely(*mbase && 'comparison`))
278 1.1 mrg {
279 1.1 mrg for (n = 0; n < rank; n++)
280 1.1 mrg dest[n * dstride] = count[n] + 1;
281 1.1 mrg
282 1.1 mrg return;
283 1.1 mrg }
284 1.1 mrg base += sstride[0] * 'base_mult`'`;
285 1.1 mrg mbase += mstride[0];
286 1.1 mrg } while(++count[0] != extent[0]);
287 1.1 mrg
288 1.1 mrg n = 0;
289 1.1 mrg do
290 1.1 mrg {
291 1.1 mrg /* When we get to the end of a dimension, reset it and increment
292 1.1 mrg the next dimension. */
293 1.1 mrg count[n] = 0;
294 1.1 mrg /* We could precalculate these products, but this is a less
295 1.1 mrg frequently used path so probably not worth it. */
296 1.1 mrg base -= sstride[n] * extent[n] * 'base_mult`'`;
297 1.1 mrg mbase -= mstride[n] * extent[n];
298 1.1 mrg n++;
299 1.1 mrg if (n >= rank)
300 1.1 mrg return;
301 1.1 mrg else
302 1.1 mrg {
303 1.1 mrg count[n]++;
304 1.1 mrg base += sstride[n]* 'base_mult`'`;
305 1.1 mrg mbase += mstride[n];
306 1.1 mrg }
307 1.1 mrg } while (count[n] == extent[n]);
308 1.1 mrg }
309 1.1 mrg }
310 1.1 mrg return;
311 1.1 mrg }
312 1.1 mrg
313 1.1 mrg 'header3`
314 1.1 mrg {
315 1.1 mrg index_type rank;
316 1.1 mrg index_type dstride;
317 1.1 mrg index_type * restrict dest;
318 1.1 mrg index_type n;
319 1.1 mrg
320 1.1 mrg if (mask == NULL || *mask)
321 1.1 mrg {
322 1.1 mrg findloc0_'atype_code` (retarray, array, value, back'len_arg`);
323 1.1 mrg return;
324 1.1 mrg }
325 1.1 mrg
326 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array);
327 1.1 mrg
328 1.1 mrg if (rank <= 0)
329 1.1 mrg internal_error (NULL, "Rank of array needs to be > 0");
330 1.1 mrg
331 1.1 mrg if (retarray->base_addr == NULL)
332 1.1 mrg {
333 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
334 1.1 mrg retarray->dtype.rank = 1;
335 1.1 mrg retarray->offset = 0;
336 1.1 mrg retarray->base_addr = xmallocarray (rank, sizeof (index_type));
337 1.1 mrg }
338 1.1 mrg else if (unlikely (compile_options.bounds_check))
339 1.1 mrg {
340 1.1 mrg bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
341 1.1 mrg "FINDLOC");
342 1.1 mrg }
343 1.1 mrg
344 1.1 mrg dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
345 1.1 mrg dest = retarray->base_addr;
346 1.1 mrg for (n = 0; n<rank; n++)
347 1.1 mrg dest[n * dstride] = 0 ;
348 1.1 mrg }
349 1.1 mrg
350 1.1 mrg #endif'
351