1 `/* Implementation of the FINDLOC intrinsic
2 Copyright (C) 2018 Free Software Foundation, Inc.
3 Contributed by Thomas König <tk@tkoenig.net>
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
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.
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.
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.
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/>. */
26 #include "libgfortran.h"
29 #if defined (HAVE_'atype_name`)
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;
45 /* Make dim zero based to avoid confusion. */
46 rank = GFC_DESCRIPTOR_RANK (array) - 1;
49 if (unlikely (dim < 0 || dim > rank))
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);
56 len = GFC_DESCRIPTOR_EXTENT(array,dim);
59 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
61 for (n = 0; n < dim; n++)
63 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
64 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
69 for (n = dim; n < rank; n++)
71 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
72 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
78 if (retarray->base_addr == NULL)
80 size_t alloc_size, str;
82 for (n = 0; n < rank; n++)
87 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
89 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
94 retarray->dtype.rank = rank;
96 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
98 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
101 /* Make sure we have a zero-sized array. */
102 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
108 if (rank != GFC_DESCRIPTOR_RANK (retarray))
109 runtime_error ("rank of return array incorrect in"
110 " FINDLOC intrinsic: is %ld, should be %ld",
111 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
114 if (unlikely (compile_options.bounds_check))
115 bounds_ifunction_return ((array_t *) retarray, extent,
116 "return value", "FINDLOC");
119 for (n = 0; n < rank; n++)
122 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
127 dest = retarray->base_addr;
130 base = array->base_addr;
131 while (continue_loop)
133 const 'atype_name`'` * restrict src;
139 src = base + (len - 1) * delta * 'base_mult`;
140 for (n = len; n > 0; n--, src -= delta * 'base_mult`)
152 for (n = 1; n <= len; n++, src += delta * 'base_mult`)
164 base += sstride[0] * 'base_mult`;
167 while (count[n] == extent[n])
170 base -= sstride[n] * extent[n] * 'base_mult`;
171 dest -= dstride[n] * extent[n];
181 base += sstride[n] * 'base_mult`;
189 index_type count[GFC_MAX_DIMENSIONS];
190 index_type extent[GFC_MAX_DIMENSIONS];
191 index_type sstride[GFC_MAX_DIMENSIONS];
192 index_type mstride[GFC_MAX_DIMENSIONS];
193 index_type dstride[GFC_MAX_DIMENSIONS];
194 const 'atype_name`'` * restrict base;
195 const GFC_LOGICAL_1 * restrict mbase;
196 index_type * restrict dest;
206 /* Make dim zero based to avoid confusion. */
207 rank = GFC_DESCRIPTOR_RANK (array) - 1;
210 if (unlikely (dim < 0 || dim > rank))
212 runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
213 "is %ld, should be between 1 and %ld",
214 (long int) dim + 1, (long int) rank + 1);
217 len = GFC_DESCRIPTOR_EXTENT(array,dim);
221 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
222 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
224 mbase = mask->base_addr;
226 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
228 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
229 #ifdef HAVE_GFC_LOGICAL_16
233 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
235 internal_error (NULL, "Funny sized logical array");
237 for (n = 0; n < dim; n++)
239 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
240 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
241 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
246 for (n = dim; n < rank; n++)
248 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
249 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
250 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
256 if (retarray->base_addr == NULL)
258 size_t alloc_size, str;
260 for (n = 0; n < rank; n++)
265 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
267 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
271 retarray->offset = 0;
272 retarray->dtype.rank = rank;
274 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
276 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
279 /* Make sure we have a zero-sized array. */
280 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
286 if (rank != GFC_DESCRIPTOR_RANK (retarray))
287 runtime_error ("rank of return array incorrect in"
288 " FINDLOC intrinsic: is %ld, should be %ld",
289 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
292 if (unlikely (compile_options.bounds_check))
293 bounds_ifunction_return ((array_t *) retarray, extent,
294 "return value", "FINDLOC");
297 for (n = 0; n < rank; n++)
300 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
305 dest = retarray->base_addr;
308 base = array->base_addr;
309 while (continue_loop)
311 const 'atype_name`'` * restrict src;
312 const GFC_LOGICAL_1 * restrict msrc;
318 src = base + (len - 1) * delta * 'base_mult`;
319 msrc = mbase + (len - 1) * mdelta;
320 for (n = len; n > 0; n--, src -= delta * 'base_mult`, msrc -= mdelta)
322 if (*msrc && 'comparison`'`)
333 for (n = 1; n <= len; n++, src += delta * 'base_mult`, msrc += mdelta)
335 if (*msrc && 'comparison`'`)
345 base += sstride[0] * 'base_mult`;
349 while (count[n] == extent[n])
352 base -= sstride[n] * extent[n] * 'base_mult`;
353 mbase -= mstride[n] * extent[n];
354 dest -= dstride[n] * extent[n];
364 base += sstride[n] * 'base_mult`;
372 index_type count[GFC_MAX_DIMENSIONS];
373 index_type extent[GFC_MAX_DIMENSIONS];
374 index_type dstride[GFC_MAX_DIMENSIONS];
375 index_type * restrict dest;
384 findloc1_'atype_code`'` (retarray, array, value, pdim, back'len_arg`'`);
387 /* Make dim zero based to avoid confusion. */
388 rank = GFC_DESCRIPTOR_RANK (array) - 1;
391 if (unlikely (dim < 0 || dim > rank))
393 runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
394 "is %ld, should be between 1 and %ld",
395 (long int) dim + 1, (long int) rank + 1);
398 len = GFC_DESCRIPTOR_EXTENT(array,dim);
402 for (n = 0; n < dim; n++)
404 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
410 for (n = dim; n < rank; n++)
413 GFC_DESCRIPTOR_EXTENT(array,n + 1);
420 if (retarray->base_addr == NULL)
422 size_t alloc_size, str;
424 for (n = 0; n < rank; n++)
429 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
431 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
434 retarray->offset = 0;
435 retarray->dtype.rank = rank;
437 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
439 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
442 /* Make sure we have a zero-sized array. */
443 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
449 if (rank != GFC_DESCRIPTOR_RANK (retarray))
450 runtime_error ("rank of return array incorrect in"
451 " FINDLOC intrinsic: is %ld, should be %ld",
452 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
455 if (unlikely (compile_options.bounds_check))
456 bounds_ifunction_return ((array_t *) retarray, extent,
457 "return value", "FINDLOC");
460 for (n = 0; n < rank; n++)
463 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
467 dest = retarray->base_addr;
470 while (continue_loop)
477 while (count[n] == extent[n])
480 dest -= dstride[n] * extent[n];