blob: 3f6c59a8532ef4f5f980ca19fcbe11dae1bf4d88 [file] [log] [blame]
François-Xavier Coudert644cb692005-10-03 07:22:20 +00001/* Implementation of the MINLOC intrinsic
Jakub Jelinek83ffe9c2023-01-16 11:50:43 +01002 Copyright (C) 2002-2023 Free Software Foundation, Inc.
François-Xavier Coudert644cb692005-10-03 07:22:20 +00003 Contributed by Paul Brook <paul@nowt.org>
4
Tobias Burnus0cd05592010-08-27 21:17:45 +02005This file is part of the GNU Fortran runtime library (libgfortran).
François-Xavier Coudert644cb692005-10-03 07:22:20 +00006
7Libgfortran is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public
9License as published by the Free Software Foundation; either
Jakub Jelinek748086b2009-04-09 17:00:19 +020010version 3 of the License, or (at your option) any later version.
François-Xavier Coudert644cb692005-10-03 07:22:20 +000011
12Libgfortran is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
Jakub Jelinek748086b2009-04-09 17:00:19 +020017Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
François-Xavier Coudert644cb692005-10-03 07:22:20 +000025
Francois-Xavier Coudert36ae8a62007-08-31 14:01:34 +000026#include "libgfortran.h"
Thomas Koenig64b18062018-01-15 18:35:13 +000027#include <assert.h>
François-Xavier Coudert644cb692005-10-03 07:22:20 +000028
29
30#if defined (HAVE_GFC_REAL_10) && defined (HAVE_GFC_INTEGER_16)
31
Thomas Koenig64b18062018-01-15 18:35:13 +000032#define HAVE_BACK_ARG 1
33
François-Xavier Coudert644cb692005-10-03 07:22:20 +000034
Janne Blomqvist64acfd92005-11-27 23:03:33 +020035extern void minloc1_16_r10 (gfc_array_i16 * const restrict,
Thomas Koenig64b18062018-01-15 18:35:13 +000036 gfc_array_r10 * const restrict, const index_type * const restrict, GFC_LOGICAL_4 back);
François-Xavier Coudert644cb692005-10-03 07:22:20 +000037export_proto(minloc1_16_r10);
38
39void
Janne Blomqvist64acfd92005-11-27 23:03:33 +020040minloc1_16_r10 (gfc_array_i16 * const restrict retarray,
41 gfc_array_r10 * const restrict array,
Thomas Koenig64b18062018-01-15 18:35:13 +000042 const index_type * const restrict pdim, GFC_LOGICAL_4 back)
François-Xavier Coudert644cb692005-10-03 07:22:20 +000043{
44 index_type count[GFC_MAX_DIMENSIONS];
45 index_type extent[GFC_MAX_DIMENSIONS];
46 index_type sstride[GFC_MAX_DIMENSIONS];
47 index_type dstride[GFC_MAX_DIMENSIONS];
Janne Blomqvist64acfd92005-11-27 23:03:33 +020048 const GFC_REAL_10 * restrict base;
49 GFC_INTEGER_16 * restrict dest;
François-Xavier Coudert644cb692005-10-03 07:22:20 +000050 index_type rank;
51 index_type n;
52 index_type len;
53 index_type delta;
54 index_type dim;
Thomas Koenigda96f5a2008-05-04 19:07:28 +000055 int continue_loop;
François-Xavier Coudert644cb692005-10-03 07:22:20 +000056
57 /* Make dim zero based to avoid confusion. */
François-Xavier Coudert644cb692005-10-03 07:22:20 +000058 rank = GFC_DESCRIPTOR_RANK (array) - 1;
Thomas Koenigcfdf6ff2017-07-31 09:34:36 +000059 dim = (*pdim) - 1;
60
61 if (unlikely (dim < 0 || dim > rank))
62 {
63 runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
64 "is %ld, should be between 1 and %ld",
65 (long int) dim + 1, (long int) rank + 1);
66 }
François-Xavier Coudert644cb692005-10-03 07:22:20 +000067
Thomas Koenigdfb55fd2009-06-21 19:24:55 +000068 len = GFC_DESCRIPTOR_EXTENT(array,dim);
Thomas Koenigda96f5a2008-05-04 19:07:28 +000069 if (len < 0)
70 len = 0;
Thomas Koenigdfb55fd2009-06-21 19:24:55 +000071 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
François-Xavier Coudert644cb692005-10-03 07:22:20 +000072
73 for (n = 0; n < dim; n++)
74 {
Thomas Koenigdfb55fd2009-06-21 19:24:55 +000075 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
76 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
Thomas Koenig80ee04b2006-12-30 13:16:36 +000077
78 if (extent[n] < 0)
79 extent[n] = 0;
François-Xavier Coudert644cb692005-10-03 07:22:20 +000080 }
81 for (n = dim; n < rank; n++)
82 {
Thomas Koenigdfb55fd2009-06-21 19:24:55 +000083 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
84 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
Thomas Koenig80ee04b2006-12-30 13:16:36 +000085
86 if (extent[n] < 0)
87 extent[n] = 0;
François-Xavier Coudert644cb692005-10-03 07:22:20 +000088 }
89
Tobias Burnus21d13352012-03-10 18:22:31 +010090 if (retarray->base_addr == NULL)
François-Xavier Coudert644cb692005-10-03 07:22:20 +000091 {
Thomas Koenigdfb55fd2009-06-21 19:24:55 +000092 size_t alloc_size, str;
Thomas Koenig80ee04b2006-12-30 13:16:36 +000093
François-Xavier Coudert644cb692005-10-03 07:22:20 +000094 for (n = 0; n < rank; n++)
Jakub Jelinek80927a52009-07-24 09:57:13 +020095 {
96 if (n == 0)
Thomas Koenigdfb55fd2009-06-21 19:24:55 +000097 str = 1;
Jakub Jelinek80927a52009-07-24 09:57:13 +020098 else
99 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000100
101 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
102
Jakub Jelinek80927a52009-07-24 09:57:13 +0200103 }
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000104
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000105 retarray->offset = 0;
Steven G. Karglca708a22018-06-01 20:20:35 +0000106 retarray->dtype.rank = rank;
Thomas Koenig80ee04b2006-12-30 13:16:36 +0000107
Janne Blomqvist92e6f3a2014-06-17 06:50:34 +0300108 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
Thomas Koenig80ee04b2006-12-30 13:16:36 +0000109
Janne Blomqvist92e6f3a2014-06-17 06:50:34 +0300110 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
Thomas Koenig80ee04b2006-12-30 13:16:36 +0000111 if (alloc_size == 0)
Mikael Morin62715bf2023-11-07 11:24:04 +0100112 return;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000113 }
114 else
115 {
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000116 if (rank != GFC_DESCRIPTOR_RANK (retarray))
Thomas Koenigfd6590f2008-01-11 20:21:05 +0000117 runtime_error ("rank of return array incorrect in"
Thomas Koenigccacefc2008-01-13 22:13:52 +0000118 " MINLOC intrinsic: is %ld, should be %ld",
119 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
120 (long int) rank);
Thomas Koenigfd6590f2008-01-11 20:21:05 +0000121
Tobias Burnus9731c4a2008-09-06 16:53:26 +0200122 if (unlikely (compile_options.bounds_check))
Thomas Koenig16bff922009-07-19 15:07:21 +0000123 bounds_ifunction_return ((array_t *) retarray, extent,
124 "return value", "MINLOC");
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000125 }
126
127 for (n = 0; n < rank; n++)
128 {
129 count[n] = 0;
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000130 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000131 if (extent[n] <= 0)
Thomas Koenigfacc1282011-03-12 22:39:33 +0000132 return;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000133 }
134
Tobias Burnus21d13352012-03-10 18:22:31 +0100135 base = array->base_addr;
136 dest = retarray->base_addr;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000137
Thomas Koenigda96f5a2008-05-04 19:07:28 +0000138 continue_loop = 1;
139 while (continue_loop)
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000140 {
Janne Blomqvist64acfd92005-11-27 23:03:33 +0200141 const GFC_REAL_10 * restrict src;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000142 GFC_INTEGER_16 result;
143 src = base;
144 {
145
Jakub Jelinek80927a52009-07-24 09:57:13 +0200146 GFC_REAL_10 minval;
147#if defined (GFC_REAL_10_INFINITY)
148 minval = GFC_REAL_10_INFINITY;
149#else
150 minval = GFC_REAL_10_HUGE;
151#endif
152 result = 1;
153 if (len <= 0)
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000154 *dest = 0;
155 else
156 {
Thomas Koenigb573f932018-05-08 07:47:19 +0000157#if ! defined HAVE_BACK_ARG
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000158 for (n = 0; n < len; n++, src += delta)
159 {
Thomas Koenigb573f932018-05-08 07:47:19 +0000160#endif
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000161
Jakub Jelinek80927a52009-07-24 09:57:13 +0200162#if defined (GFC_REAL_10_QUIET_NAN)
Thomas Koenigb573f932018-05-08 07:47:19 +0000163 for (n = 0; n < len; n++, src += delta)
164 {
Jakub Jelinek80927a52009-07-24 09:57:13 +0200165 if (*src <= minval)
166 {
167 minval = *src;
168 result = (GFC_INTEGER_16)n + 1;
169 break;
170 }
171 }
Thomas Koenigb573f932018-05-08 07:47:19 +0000172#else
173 n = 0;
Jakub Jelinek80927a52009-07-24 09:57:13 +0200174#endif
Thomas Koenigb573f932018-05-08 07:47:19 +0000175 if (back)
176 for (; n < len; n++, src += delta)
177 {
178 if (unlikely (*src <= minval))
179 {
180 minval = *src;
181 result = (GFC_INTEGER_16)n + 1;
182 }
183 }
184 else
185 for (; n < len; n++, src += delta)
186 {
187 if (unlikely (*src < minval))
188 {
189 minval = *src;
190 result = (GFC_INTEGER_16) n + 1;
191 }
Jakub Jelinek80927a52009-07-24 09:57:13 +0200192 }
Tobias Burnus0cd05592010-08-27 21:17:45 +0200193
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000194 *dest = result;
195 }
196 }
197 /* Advance to the next element. */
198 count[0]++;
199 base += sstride[0];
200 dest += dstride[0];
201 n = 0;
202 while (count[n] == extent[n])
Jakub Jelinek80927a52009-07-24 09:57:13 +0200203 {
204 /* When we get to the end of a dimension, reset it and increment
205 the next dimension. */
206 count[n] = 0;
207 /* We could precalculate these products, but this is a less
208 frequently used path so probably not worth it. */
209 base -= sstride[n] * extent[n];
210 dest -= dstride[n] * extent[n];
211 n++;
Thomas Koenig80dd6312017-03-10 19:42:46 +0000212 if (n >= rank)
Jakub Jelinek80927a52009-07-24 09:57:13 +0200213 {
Thomas Koenig80dd6312017-03-10 19:42:46 +0000214 /* Break out of the loop. */
Thomas Koenigda96f5a2008-05-04 19:07:28 +0000215 continue_loop = 0;
216 break;
Jakub Jelinek80927a52009-07-24 09:57:13 +0200217 }
218 else
219 {
220 count[n]++;
221 base += sstride[n];
222 dest += dstride[n];
223 }
224 }
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000225 }
226}
227
228
Janne Blomqvist64acfd92005-11-27 23:03:33 +0200229extern void mminloc1_16_r10 (gfc_array_i16 * const restrict,
230 gfc_array_r10 * const restrict, const index_type * const restrict,
Thomas Koenig64b18062018-01-15 18:35:13 +0000231 gfc_array_l1 * const restrict, GFC_LOGICAL_4 back);
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000232export_proto(mminloc1_16_r10);
233
234void
Janne Blomqvist64acfd92005-11-27 23:03:33 +0200235mminloc1_16_r10 (gfc_array_i16 * const restrict retarray,
236 gfc_array_r10 * const restrict array,
237 const index_type * const restrict pdim,
Thomas Koenig64b18062018-01-15 18:35:13 +0000238 gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back)
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000239{
240 index_type count[GFC_MAX_DIMENSIONS];
241 index_type extent[GFC_MAX_DIMENSIONS];
242 index_type sstride[GFC_MAX_DIMENSIONS];
243 index_type dstride[GFC_MAX_DIMENSIONS];
244 index_type mstride[GFC_MAX_DIMENSIONS];
Janne Blomqvist64acfd92005-11-27 23:03:33 +0200245 GFC_INTEGER_16 * restrict dest;
246 const GFC_REAL_10 * restrict base;
Thomas Koenig28dc6b32007-08-24 16:16:16 +0000247 const GFC_LOGICAL_1 * restrict mbase;
Thomas Koenigcfdf6ff2017-07-31 09:34:36 +0000248 index_type rank;
249 index_type dim;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000250 index_type n;
251 index_type len;
252 index_type delta;
253 index_type mdelta;
Thomas Koenig28dc6b32007-08-24 16:16:16 +0000254 int mask_kind;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000255
Thomas Koenig2ea47ee2018-12-31 14:59:46 +0000256 if (mask == NULL)
257 {
258#ifdef HAVE_BACK_ARG
259 minloc1_16_r10 (retarray, array, pdim, back);
260#else
261 minloc1_16_r10 (retarray, array, pdim);
262#endif
263 return;
264 }
265
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000266 dim = (*pdim) - 1;
267 rank = GFC_DESCRIPTOR_RANK (array) - 1;
268
Thomas Koenigcfdf6ff2017-07-31 09:34:36 +0000269
270 if (unlikely (dim < 0 || dim > rank))
271 {
272 runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
273 "is %ld, should be between 1 and %ld",
274 (long int) dim + 1, (long int) rank + 1);
275 }
276
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000277 len = GFC_DESCRIPTOR_EXTENT(array,dim);
Mikael Morin85a96882023-11-07 11:24:03 +0100278 if (len < 0)
279 len = 0;
Thomas Koenig28dc6b32007-08-24 16:16:16 +0000280
Tobias Burnus21d13352012-03-10 18:22:31 +0100281 mbase = mask->base_addr;
Thomas Koenig28dc6b32007-08-24 16:16:16 +0000282
283 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
284
285 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
286#ifdef HAVE_GFC_LOGICAL_16
287 || mask_kind == 16
288#endif
289 )
290 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
291 else
292 runtime_error ("Funny sized logical array");
293
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000294 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
295 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000296
297 for (n = 0; n < dim; n++)
298 {
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000299 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
300 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
301 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
Thomas Koenig80ee04b2006-12-30 13:16:36 +0000302
303 if (extent[n] < 0)
304 extent[n] = 0;
305
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000306 }
307 for (n = dim; n < rank; n++)
308 {
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000309 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
310 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
311 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
Thomas Koenig80ee04b2006-12-30 13:16:36 +0000312
313 if (extent[n] < 0)
314 extent[n] = 0;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000315 }
316
Tobias Burnus21d13352012-03-10 18:22:31 +0100317 if (retarray->base_addr == NULL)
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000318 {
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000319 size_t alloc_size, str;
Thomas Koenig80ee04b2006-12-30 13:16:36 +0000320
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000321 for (n = 0; n < rank; n++)
Jakub Jelinek80927a52009-07-24 09:57:13 +0200322 {
323 if (n == 0)
324 str = 1;
325 else
326 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000327
328 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
329
Jakub Jelinek80927a52009-07-24 09:57:13 +0200330 }
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000331
Janne Blomqvist92e6f3a2014-06-17 06:50:34 +0300332 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
Thomas Koenig80ee04b2006-12-30 13:16:36 +0000333
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000334 retarray->offset = 0;
Steven G. Karglca708a22018-06-01 20:20:35 +0000335 retarray->dtype.rank = rank;
Thomas Koenig80ee04b2006-12-30 13:16:36 +0000336
Mikael Morind56bf412023-11-07 11:24:02 +0100337 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
Thomas Koenig80ee04b2006-12-30 13:16:36 +0000338 if (alloc_size == 0)
Mikael Morin62715bf2023-11-07 11:24:04 +0100339 return;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000340 }
341 else
342 {
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000343 if (rank != GFC_DESCRIPTOR_RANK (retarray))
Thomas Koenigfd6590f2008-01-11 20:21:05 +0000344 runtime_error ("rank of return array incorrect in MINLOC intrinsic");
345
Tobias Burnus9731c4a2008-09-06 16:53:26 +0200346 if (unlikely (compile_options.bounds_check))
Thomas Koenigfd6590f2008-01-11 20:21:05 +0000347 {
Thomas Koenig16bff922009-07-19 15:07:21 +0000348 bounds_ifunction_return ((array_t *) retarray, extent,
349 "return value", "MINLOC");
350 bounds_equal_extents ((array_t *) mask, (array_t *) array,
351 "MASK argument", "MINLOC");
Thomas Koenigfd6590f2008-01-11 20:21:05 +0000352 }
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000353 }
354
355 for (n = 0; n < rank; n++)
356 {
357 count[n] = 0;
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000358 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000359 if (extent[n] <= 0)
Jakub Jelinek80927a52009-07-24 09:57:13 +0200360 return;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000361 }
362
Tobias Burnus21d13352012-03-10 18:22:31 +0100363 dest = retarray->base_addr;
364 base = array->base_addr;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000365
366 while (base)
367 {
Janne Blomqvist64acfd92005-11-27 23:03:33 +0200368 const GFC_REAL_10 * restrict src;
Thomas Koenig28dc6b32007-08-24 16:16:16 +0000369 const GFC_LOGICAL_1 * restrict msrc;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000370 GFC_INTEGER_16 result;
371 src = base;
372 msrc = mbase;
373 {
374
Jakub Jelinek80927a52009-07-24 09:57:13 +0200375 GFC_REAL_10 minval;
376#if defined (GFC_REAL_10_INFINITY)
377 minval = GFC_REAL_10_INFINITY;
378#else
379 minval = GFC_REAL_10_HUGE;
380#endif
381#if defined (GFC_REAL_10_QUIET_NAN)
382 GFC_INTEGER_16 result2 = 0;
383#endif
384 result = 0;
Tobias Burnus036e1772012-10-28 17:54:44 +0100385 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000386 {
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000387
Jakub Jelinek80927a52009-07-24 09:57:13 +0200388 if (*msrc)
389 {
390#if defined (GFC_REAL_10_QUIET_NAN)
391 if (!result2)
392 result2 = (GFC_INTEGER_16)n + 1;
393 if (*src <= minval)
394#endif
395 {
396 minval = *src;
397 result = (GFC_INTEGER_16)n + 1;
398 break;
399 }
400 }
401 }
402#if defined (GFC_REAL_10_QUIET_NAN)
403 if (unlikely (n >= len))
404 result = result2;
405 else
406#endif
Thomas Koenigb573f932018-05-08 07:47:19 +0000407 if (back)
408 for (; n < len; n++, src += delta, msrc += mdelta)
409 {
410 if (*msrc && unlikely (*src <= minval))
411 {
412 minval = *src;
413 result = (GFC_INTEGER_16)n + 1;
414 }
415 }
416 else
417 for (; n < len; n++, src += delta, msrc += mdelta)
Jakub Jelinek80927a52009-07-24 09:57:13 +0200418 {
Thomas Koenigb573f932018-05-08 07:47:19 +0000419 if (*msrc && unlikely (*src < minval))
420 {
421 minval = *src;
422 result = (GFC_INTEGER_16) n + 1;
423 }
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000424 }
Tobias Burnus036e1772012-10-28 17:54:44 +0100425 *dest = result;
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000426 }
427 /* Advance to the next element. */
428 count[0]++;
429 base += sstride[0];
430 mbase += mstride[0];
431 dest += dstride[0];
432 n = 0;
433 while (count[n] == extent[n])
Jakub Jelinek80927a52009-07-24 09:57:13 +0200434 {
435 /* When we get to the end of a dimension, reset it and increment
436 the next dimension. */
437 count[n] = 0;
438 /* We could precalculate these products, but this is a less
439 frequently used path so probably not worth it. */
440 base -= sstride[n] * extent[n];
441 mbase -= mstride[n] * extent[n];
442 dest -= dstride[n] * extent[n];
443 n++;
Thomas Koenig80dd6312017-03-10 19:42:46 +0000444 if (n >= rank)
Jakub Jelinek80927a52009-07-24 09:57:13 +0200445 {
Thomas Koenig80dd6312017-03-10 19:42:46 +0000446 /* Break out of the loop. */
Jakub Jelinek80927a52009-07-24 09:57:13 +0200447 base = NULL;
448 break;
449 }
450 else
451 {
452 count[n]++;
453 base += sstride[n];
454 mbase += mstride[n];
455 dest += dstride[n];
456 }
457 }
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000458 }
459}
460
Thomas Koenig97a62032006-03-20 21:56:00 +0000461
462extern void sminloc1_16_r10 (gfc_array_i16 * const restrict,
463 gfc_array_r10 * const restrict, const index_type * const restrict,
Thomas Koenig64b18062018-01-15 18:35:13 +0000464 GFC_LOGICAL_4 *, GFC_LOGICAL_4 back);
Thomas Koenig97a62032006-03-20 21:56:00 +0000465export_proto(sminloc1_16_r10);
466
467void
468sminloc1_16_r10 (gfc_array_i16 * const restrict retarray,
469 gfc_array_r10 * const restrict array,
470 const index_type * const restrict pdim,
Thomas Koenig64b18062018-01-15 18:35:13 +0000471 GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
Thomas Koenig97a62032006-03-20 21:56:00 +0000472{
Thomas Koenig802367d2008-04-30 16:56:01 +0000473 index_type count[GFC_MAX_DIMENSIONS];
474 index_type extent[GFC_MAX_DIMENSIONS];
Thomas Koenig802367d2008-04-30 16:56:01 +0000475 index_type dstride[GFC_MAX_DIMENSIONS];
476 GFC_INTEGER_16 * restrict dest;
Thomas Koenig97a62032006-03-20 21:56:00 +0000477 index_type rank;
478 index_type n;
Thomas Koenig802367d2008-04-30 16:56:01 +0000479 index_type dim;
480
Thomas Koenig97a62032006-03-20 21:56:00 +0000481
Thomas Koenig2ea47ee2018-12-31 14:59:46 +0000482 if (mask == NULL || *mask)
Thomas Koenig97a62032006-03-20 21:56:00 +0000483 {
Thomas Koenig64b18062018-01-15 18:35:13 +0000484#ifdef HAVE_BACK_ARG
485 minloc1_16_r10 (retarray, array, pdim, back);
486#else
Thomas Koenig97a62032006-03-20 21:56:00 +0000487 minloc1_16_r10 (retarray, array, pdim);
Thomas Koenig64b18062018-01-15 18:35:13 +0000488#endif
Thomas Koenig97a62032006-03-20 21:56:00 +0000489 return;
490 }
Thomas Koenig802367d2008-04-30 16:56:01 +0000491 /* Make dim zero based to avoid confusion. */
492 dim = (*pdim) - 1;
493 rank = GFC_DESCRIPTOR_RANK (array) - 1;
494
Thomas Koenigcfdf6ff2017-07-31 09:34:36 +0000495 if (unlikely (dim < 0 || dim > rank))
496 {
497 runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
498 "is %ld, should be between 1 and %ld",
499 (long int) dim + 1, (long int) rank + 1);
500 }
501
Thomas Koenig802367d2008-04-30 16:56:01 +0000502 for (n = 0; n < dim; n++)
503 {
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000504 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
Thomas Koenig802367d2008-04-30 16:56:01 +0000505
506 if (extent[n] <= 0)
507 extent[n] = 0;
508 }
509
510 for (n = dim; n < rank; n++)
511 {
Thomas Koenig802367d2008-04-30 16:56:01 +0000512 extent[n] =
Jakub Jelinek80927a52009-07-24 09:57:13 +0200513 GFC_DESCRIPTOR_EXTENT(array,n + 1);
Thomas Koenig802367d2008-04-30 16:56:01 +0000514
515 if (extent[n] <= 0)
Jakub Jelinek80927a52009-07-24 09:57:13 +0200516 extent[n] = 0;
Thomas Koenig802367d2008-04-30 16:56:01 +0000517 }
Thomas Koenig97a62032006-03-20 21:56:00 +0000518
Tobias Burnus21d13352012-03-10 18:22:31 +0100519 if (retarray->base_addr == NULL)
Thomas Koenig97a62032006-03-20 21:56:00 +0000520 {
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000521 size_t alloc_size, str;
Thomas Koenig802367d2008-04-30 16:56:01 +0000522
523 for (n = 0; n < rank; n++)
Jakub Jelinek80927a52009-07-24 09:57:13 +0200524 {
525 if (n == 0)
526 str = 1;
527 else
528 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000529
530 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
531
Jakub Jelinek80927a52009-07-24 09:57:13 +0200532 }
Thomas Koenig802367d2008-04-30 16:56:01 +0000533
Thomas Koenig97a62032006-03-20 21:56:00 +0000534 retarray->offset = 0;
Steven G. Karglca708a22018-06-01 20:20:35 +0000535 retarray->dtype.rank = rank;
Thomas Koenig802367d2008-04-30 16:56:01 +0000536
Janne Blomqvist92e6f3a2014-06-17 06:50:34 +0300537 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
Thomas Koenig802367d2008-04-30 16:56:01 +0000538
Mikael Morind56bf412023-11-07 11:24:02 +0100539 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
Thomas Koenig802367d2008-04-30 16:56:01 +0000540 if (alloc_size == 0)
Mikael Morin62715bf2023-11-07 11:24:04 +0100541 return;
Thomas Koenig97a62032006-03-20 21:56:00 +0000542 }
543 else
544 {
Thomas Koenig802367d2008-04-30 16:56:01 +0000545 if (rank != GFC_DESCRIPTOR_RANK (retarray))
546 runtime_error ("rank of return array incorrect in"
547 " MINLOC intrinsic: is %ld, should be %ld",
548 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
549 (long int) rank);
550
Tobias Burnus9731c4a2008-09-06 16:53:26 +0200551 if (unlikely (compile_options.bounds_check))
Thomas Koenigfd6590f2008-01-11 20:21:05 +0000552 {
Thomas Koenig802367d2008-04-30 16:56:01 +0000553 for (n=0; n < rank; n++)
554 {
555 index_type ret_extent;
Thomas Koenig97a62032006-03-20 21:56:00 +0000556
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000557 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
Thomas Koenig802367d2008-04-30 16:56:01 +0000558 if (extent[n] != ret_extent)
559 runtime_error ("Incorrect extent in return value of"
560 " MINLOC intrinsic in dimension %ld:"
561 " is %ld, should be %ld", (long int) n + 1,
562 (long int) ret_extent, (long int) extent[n]);
563 }
Thomas Koenigfd6590f2008-01-11 20:21:05 +0000564 }
Thomas Koenig97a62032006-03-20 21:56:00 +0000565 }
Thomas Koenig97a62032006-03-20 21:56:00 +0000566
Thomas Koenig802367d2008-04-30 16:56:01 +0000567 for (n = 0; n < rank; n++)
568 {
569 count[n] = 0;
Thomas Koenigdfb55fd2009-06-21 19:24:55 +0000570 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
Thomas Koenig802367d2008-04-30 16:56:01 +0000571 }
572
Tobias Burnus21d13352012-03-10 18:22:31 +0100573 dest = retarray->base_addr;
Thomas Koenig802367d2008-04-30 16:56:01 +0000574
575 while(1)
576 {
577 *dest = 0;
578 count[0]++;
579 dest += dstride[0];
580 n = 0;
581 while (count[n] == extent[n])
Jakub Jelinek80927a52009-07-24 09:57:13 +0200582 {
Thomas Koenig802367d2008-04-30 16:56:01 +0000583 /* When we get to the end of a dimension, reset it and increment
Jakub Jelinek80927a52009-07-24 09:57:13 +0200584 the next dimension. */
585 count[n] = 0;
586 /* We could precalculate these products, but this is a less
587 frequently used path so probably not worth it. */
588 dest -= dstride[n] * extent[n];
589 n++;
Thomas Koenig80dd6312017-03-10 19:42:46 +0000590 if (n >= rank)
Thomas Koenig802367d2008-04-30 16:56:01 +0000591 return;
Jakub Jelinek80927a52009-07-24 09:57:13 +0200592 else
593 {
594 count[n]++;
595 dest += dstride[n];
596 }
Thomas Koenig802367d2008-04-30 16:56:01 +0000597 }
598 }
Thomas Koenig97a62032006-03-20 21:56:00 +0000599}
600
François-Xavier Coudert644cb692005-10-03 07:22:20 +0000601#endif