2 /* Implementation of the FINDLOC intrinsic
3 Copyright (C) 2018-2024 Free Software Foundation, Inc.
4 Contributed by Thomas König <tk@tkoenig.net>
6 This file is part of the GNU Fortran 95 runtime library (libgfortran).
8 Libgfortran is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public
10 License as published by the Free Software Foundation; either
11 version 3 of the License, or (at your option) any later version.
13 Libgfortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
27 #include "libgfortran.h"
30 #if defined (HAVE_GFC_UINTEGER_1)
31 extern void findloc0_s1 (gfc_array_index_type
* const restrict retarray
,
32 gfc_array_s1
* const restrict array
, GFC_UINTEGER_1
*value
,
33 GFC_LOGICAL_4 back
, gfc_charlen_type len_array
, gfc_charlen_type len_value
);
35 export_proto(findloc0_s1
);
38 findloc0_s1 (gfc_array_index_type
* const restrict retarray
,
39 gfc_array_s1
* const restrict array
, GFC_UINTEGER_1
*value
,
40 GFC_LOGICAL_4 back
, gfc_charlen_type len_array
, gfc_charlen_type len_value
)
42 index_type count
[GFC_MAX_DIMENSIONS
];
43 index_type extent
[GFC_MAX_DIMENSIONS
];
44 index_type sstride
[GFC_MAX_DIMENSIONS
];
46 const GFC_UINTEGER_1
*base
;
47 index_type
* restrict dest
;
52 rank
= GFC_DESCRIPTOR_RANK (array
);
54 runtime_error ("Rank of array needs to be > 0");
56 if (retarray
->base_addr
== NULL
)
58 GFC_DIMENSION_SET(retarray
->dim
[0], 0, rank
-1, 1);
59 retarray
->dtype
.rank
= 1;
61 retarray
->base_addr
= xmallocarray (rank
, sizeof (index_type
));
65 if (unlikely (compile_options
.bounds_check
))
66 bounds_iforeach_return ((array_t
*) retarray
, (array_t
*) array
,
70 dstride
= GFC_DESCRIPTOR_STRIDE(retarray
,0);
71 dest
= retarray
->base_addr
;
73 /* Set the return value. */
74 for (n
= 0; n
< rank
; n
++)
75 dest
[n
* dstride
] = 0;
78 for (n
= 0; n
< rank
; n
++)
80 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
);
81 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
87 for (n
= 0; n
< rank
; n
++)
92 base
= array
->base_addr
+ (sz
- 1) * len_array
;
98 if (unlikely(compare_string (len_array
, (char *) base
, len_value
, (char *) value
) == 0))
100 for (n
= 0; n
< rank
; n
++)
101 dest
[n
* dstride
] = extent
[n
] - count
[n
];
105 base
-= sstride
[0] * len_array
;
106 } while(++count
[0] != extent
[0]);
111 /* When we get to the end of a dimension, reset it and increment
112 the next dimension. */
114 /* We could precalculate these products, but this is a less
115 frequently used path so probably not worth it. */
116 base
+= sstride
[n
] * extent
[n
] * len_array
;
123 base
-= sstride
[n
] * len_array
;
125 } while (count
[n
] == extent
[n
]);
130 base
= array
->base_addr
;
135 if (unlikely(compare_string (len_array
, (char *) base
, len_value
, (char *) value
) == 0))
137 for (n
= 0; n
< rank
; n
++)
138 dest
[n
* dstride
] = count
[n
] + 1;
142 base
+= sstride
[0] * len_array
;
143 } while(++count
[0] != extent
[0]);
148 /* When we get to the end of a dimension, reset it and increment
149 the next dimension. */
151 /* We could precalculate these products, but this is a less
152 frequently used path so probably not worth it. */
153 base
-= sstride
[n
] * extent
[n
] * len_array
;
160 base
+= sstride
[n
] * len_array
;
162 } while (count
[n
] == extent
[n
]);
168 extern void mfindloc0_s1 (gfc_array_index_type
* const restrict retarray
,
169 gfc_array_s1
* const restrict array
, GFC_UINTEGER_1
*value
,
170 gfc_array_l1
*const restrict
, GFC_LOGICAL_4 back
, gfc_charlen_type len_array
,
171 gfc_charlen_type len_value
);
172 export_proto(mfindloc0_s1
);
175 mfindloc0_s1 (gfc_array_index_type
* const restrict retarray
,
176 gfc_array_s1
* const restrict array
, GFC_UINTEGER_1
*value
,
177 gfc_array_l1
*const restrict mask
, GFC_LOGICAL_4 back
,
178 gfc_charlen_type len_array
, gfc_charlen_type len_value
)
180 index_type count
[GFC_MAX_DIMENSIONS
];
181 index_type extent
[GFC_MAX_DIMENSIONS
];
182 index_type sstride
[GFC_MAX_DIMENSIONS
];
183 index_type mstride
[GFC_MAX_DIMENSIONS
];
185 const GFC_UINTEGER_1
*base
;
186 index_type
* restrict dest
;
187 GFC_LOGICAL_1
*mbase
;
193 rank
= GFC_DESCRIPTOR_RANK (array
);
195 runtime_error ("Rank of array needs to be > 0");
197 if (retarray
->base_addr
== NULL
)
199 GFC_DIMENSION_SET(retarray
->dim
[0], 0, rank
-1, 1);
200 retarray
->dtype
.rank
= 1;
201 retarray
->offset
= 0;
202 retarray
->base_addr
= xmallocarray (rank
, sizeof (index_type
));
206 if (unlikely (compile_options
.bounds_check
))
208 bounds_iforeach_return ((array_t
*) retarray
, (array_t
*) array
,
210 bounds_equal_extents ((array_t
*) mask
, (array_t
*) array
,
211 "MASK argument", "FINDLOC");
215 mask_kind
= GFC_DESCRIPTOR_SIZE (mask
);
217 mbase
= mask
->base_addr
;
219 if (mask_kind
== 1 || mask_kind
== 2 || mask_kind
== 4 || mask_kind
== 8
220 #ifdef HAVE_GFC_LOGICAL_16
224 mbase
= GFOR_POINTER_TO_L1 (mbase
, mask_kind
);
226 internal_error (NULL
, "Funny sized logical array");
228 dstride
= GFC_DESCRIPTOR_STRIDE(retarray
,0);
229 dest
= retarray
->base_addr
;
231 /* Set the return value. */
232 for (n
= 0; n
< rank
; n
++)
233 dest
[n
* dstride
] = 0;
236 for (n
= 0; n
< rank
; n
++)
238 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
);
239 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
,n
);
240 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
246 for (n
= 0; n
< rank
; n
++)
251 base
= array
->base_addr
+ (sz
- 1) * len_array
;
252 mbase
= mbase
+ (sz
- 1) * mask_kind
;
257 if (unlikely(*mbase
&& compare_string (len_array
, (char *) base
, len_value
, (char *) value
) == 0))
259 for (n
= 0; n
< rank
; n
++)
260 dest
[n
* dstride
] = extent
[n
] - count
[n
];
264 base
-= sstride
[0] * len_array
;
266 } while(++count
[0] != extent
[0]);
271 /* When we get to the end of a dimension, reset it and increment
272 the next dimension. */
274 /* We could precalculate these products, but this is a less
275 frequently used path so probably not worth it. */
276 base
+= sstride
[n
] * extent
[n
] * len_array
;
277 mbase
-= mstride
[n
] * extent
[n
];
284 base
-= sstride
[n
] * len_array
;
287 } while (count
[n
] == extent
[n
]);
292 base
= array
->base_addr
;
297 if (unlikely(*mbase
&& compare_string (len_array
, (char *) base
, len_value
, (char *) value
) == 0))
299 for (n
= 0; n
< rank
; n
++)
300 dest
[n
* dstride
] = count
[n
] + 1;
304 base
+= sstride
[0] * len_array
;
306 } while(++count
[0] != extent
[0]);
311 /* When we get to the end of a dimension, reset it and increment
312 the next dimension. */
314 /* We could precalculate these products, but this is a less
315 frequently used path so probably not worth it. */
316 base
-= sstride
[n
] * extent
[n
] * len_array
;
317 mbase
-= mstride
[n
] * extent
[n
];
324 base
+= sstride
[n
]* len_array
;
327 } while (count
[n
] == extent
[n
]);
333 extern void sfindloc0_s1 (gfc_array_index_type
* const restrict retarray
,
334 gfc_array_s1
* const restrict array
, GFC_UINTEGER_1
*value
,
335 GFC_LOGICAL_4
*, GFC_LOGICAL_4 back
, gfc_charlen_type len_array
,
336 gfc_charlen_type len_value
);
337 export_proto(sfindloc0_s1
);
340 sfindloc0_s1 (gfc_array_index_type
* const restrict retarray
,
341 gfc_array_s1
* const restrict array
, GFC_UINTEGER_1
*value
,
342 GFC_LOGICAL_4
* mask
, GFC_LOGICAL_4 back
, gfc_charlen_type len_array
,
343 gfc_charlen_type len_value
)
347 index_type
* restrict dest
;
350 if (mask
== NULL
|| *mask
)
352 findloc0_s1 (retarray
, array
, value
, back
, len_array
, len_value
);
356 rank
= GFC_DESCRIPTOR_RANK (array
);
359 internal_error (NULL
, "Rank of array needs to be > 0");
361 if (retarray
->base_addr
== NULL
)
363 GFC_DIMENSION_SET(retarray
->dim
[0], 0, rank
-1, 1);
364 retarray
->dtype
.rank
= 1;
365 retarray
->offset
= 0;
366 retarray
->base_addr
= xmallocarray (rank
, sizeof (index_type
));
368 else if (unlikely (compile_options
.bounds_check
))
370 bounds_iforeach_return ((array_t
*) retarray
, (array_t
*) array
,
374 dstride
= GFC_DESCRIPTOR_STRIDE(retarray
,0);
375 dest
= retarray
->base_addr
;
376 for (n
= 0; n
<rank
; n
++)
377 dest
[n
* dstride
] = 0 ;