Skip gnat.dg/prot7.adb on hppa.
[official-gcc.git] / libgfortran / generated / minloc1_16_s4.c
blobaad2f87386fba3c28fab7754f50a7716ecc253cb
1 /* Implementation of the MINLOC intrinsic
2 Copyright (C) 2017-2023 Free Software Foundation, Inc.
3 Contributed by Thomas Koenig
5 This file is part of the GNU Fortran 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_GFC_UINTEGER_4) && defined (HAVE_GFC_INTEGER_16)
31 #define HAVE_BACK_ARG 1
33 #include <string.h>
34 #include <assert.h>
36 static inline int
37 compare_fcn (const GFC_UINTEGER_4 *a, const GFC_UINTEGER_4 *b, gfc_charlen_type n)
39 if (sizeof (GFC_UINTEGER_4) == 1)
40 return memcmp (a, b, n);
41 else
42 return memcmp_char4 (a, b, n);
45 extern void minloc1_16_s4 (gfc_array_i16 * const restrict,
46 gfc_array_s4 * const restrict, const index_type * const restrict , GFC_LOGICAL_4 back,
47 gfc_charlen_type);
48 export_proto(minloc1_16_s4);
50 void
51 minloc1_16_s4 (gfc_array_i16 * const restrict retarray,
52 gfc_array_s4 * const restrict array,
53 const index_type * const restrict pdim, GFC_LOGICAL_4 back,
54 gfc_charlen_type string_len)
56 index_type count[GFC_MAX_DIMENSIONS];
57 index_type extent[GFC_MAX_DIMENSIONS];
58 index_type sstride[GFC_MAX_DIMENSIONS];
59 index_type dstride[GFC_MAX_DIMENSIONS];
60 const GFC_UINTEGER_4 * restrict base;
61 GFC_INTEGER_16 * restrict dest;
62 index_type rank;
63 index_type n;
64 index_type len;
65 index_type delta;
66 index_type dim;
67 int continue_loop;
69 /* Make dim zero based to avoid confusion. */
70 rank = GFC_DESCRIPTOR_RANK (array) - 1;
71 dim = (*pdim) - 1;
73 if (unlikely (dim < 0 || dim > rank))
75 runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
76 "is %ld, should be between 1 and %ld",
77 (long int) dim + 1, (long int) rank + 1);
80 len = GFC_DESCRIPTOR_EXTENT(array,dim);
81 if (len < 0)
82 len = 0;
83 delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
85 for (n = 0; n < dim; n++)
87 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
88 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
90 if (extent[n] < 0)
91 extent[n] = 0;
93 for (n = dim; n < rank; n++)
95 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
96 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
98 if (extent[n] < 0)
99 extent[n] = 0;
102 if (retarray->base_addr == NULL)
104 size_t alloc_size, str;
106 for (n = 0; n < rank; n++)
108 if (n == 0)
109 str = 1;
110 else
111 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
113 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
117 retarray->offset = 0;
118 retarray->dtype.rank = rank;
120 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
122 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
123 if (alloc_size == 0)
125 /* Make sure we have a zero-sized array. */
126 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
127 return;
131 else
133 if (rank != GFC_DESCRIPTOR_RANK (retarray))
134 runtime_error ("rank of return array incorrect in"
135 " MINLOC intrinsic: is %ld, should be %ld",
136 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
137 (long int) rank);
139 if (unlikely (compile_options.bounds_check))
140 bounds_ifunction_return ((array_t *) retarray, extent,
141 "return value", "MINLOC");
144 for (n = 0; n < rank; n++)
146 count[n] = 0;
147 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
148 if (extent[n] <= 0)
149 return;
152 base = array->base_addr;
153 dest = retarray->base_addr;
155 continue_loop = 1;
156 while (continue_loop)
158 const GFC_UINTEGER_4 * restrict src;
159 GFC_INTEGER_16 result;
160 src = base;
163 const GFC_UINTEGER_4 *minval;
164 minval = NULL;
165 result = 0;
166 if (len <= 0)
167 *dest = 0;
168 else
170 for (n = 0; n < len; n++, src += delta)
173 if (minval == NULL || (back ? compare_fcn (src, minval, string_len) <= 0 :
174 compare_fcn (src, minval, string_len) < 0))
176 minval = src;
177 result = (GFC_INTEGER_16)n + 1;
181 *dest = result;
184 /* Advance to the next element. */
185 count[0]++;
186 base += sstride[0];
187 dest += dstride[0];
188 n = 0;
189 while (count[n] == extent[n])
191 /* When we get to the end of a dimension, reset it and increment
192 the next dimension. */
193 count[n] = 0;
194 /* We could precalculate these products, but this is a less
195 frequently used path so probably not worth it. */
196 base -= sstride[n] * extent[n];
197 dest -= dstride[n] * extent[n];
198 n++;
199 if (n >= rank)
201 /* Break out of the loop. */
202 continue_loop = 0;
203 break;
205 else
207 count[n]++;
208 base += sstride[n];
209 dest += dstride[n];
216 extern void mminloc1_16_s4 (gfc_array_i16 * const restrict,
217 gfc_array_s4 * const restrict, const index_type * const restrict,
218 gfc_array_l1 * const restrict, GFC_LOGICAL_4 back, gfc_charlen_type);
219 export_proto(mminloc1_16_s4);
221 void
222 mminloc1_16_s4 (gfc_array_i16 * const restrict retarray,
223 gfc_array_s4 * const restrict array,
224 const index_type * const restrict pdim,
225 gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back,
226 gfc_charlen_type string_len)
228 index_type count[GFC_MAX_DIMENSIONS];
229 index_type extent[GFC_MAX_DIMENSIONS];
230 index_type sstride[GFC_MAX_DIMENSIONS];
231 index_type dstride[GFC_MAX_DIMENSIONS];
232 index_type mstride[GFC_MAX_DIMENSIONS];
233 GFC_INTEGER_16 * restrict dest;
234 const GFC_UINTEGER_4 * restrict base;
235 const GFC_LOGICAL_1 * restrict mbase;
236 index_type rank;
237 index_type dim;
238 index_type n;
239 index_type len;
240 index_type delta;
241 index_type mdelta;
242 int mask_kind;
244 if (mask == NULL)
246 #ifdef HAVE_BACK_ARG
247 minloc1_16_s4 (retarray, array, pdim, back, string_len);
248 #else
249 minloc1_16_s4 (retarray, array, pdim, string_len);
250 #endif
251 return;
254 dim = (*pdim) - 1;
255 rank = GFC_DESCRIPTOR_RANK (array) - 1;
258 if (unlikely (dim < 0 || dim > rank))
260 runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
261 "is %ld, should be between 1 and %ld",
262 (long int) dim + 1, (long int) rank + 1);
265 len = GFC_DESCRIPTOR_EXTENT(array,dim);
266 if (len <= 0)
267 return;
269 mbase = mask->base_addr;
271 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
273 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
274 #ifdef HAVE_GFC_LOGICAL_16
275 || mask_kind == 16
276 #endif
278 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
279 else
280 runtime_error ("Funny sized logical array");
282 delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
283 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
285 for (n = 0; n < dim; n++)
287 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
288 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
289 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
291 if (extent[n] < 0)
292 extent[n] = 0;
295 for (n = dim; n < rank; n++)
297 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
298 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
299 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
301 if (extent[n] < 0)
302 extent[n] = 0;
305 if (retarray->base_addr == NULL)
307 size_t alloc_size, str;
309 for (n = 0; n < rank; n++)
311 if (n == 0)
312 str = 1;
313 else
314 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
316 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
320 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
322 retarray->offset = 0;
323 retarray->dtype.rank = rank;
325 if (alloc_size == 0)
327 /* Make sure we have a zero-sized array. */
328 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
329 return;
331 else
332 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
335 else
337 if (rank != GFC_DESCRIPTOR_RANK (retarray))
338 runtime_error ("rank of return array incorrect in MINLOC intrinsic");
340 if (unlikely (compile_options.bounds_check))
342 bounds_ifunction_return ((array_t *) retarray, extent,
343 "return value", "MINLOC");
344 bounds_equal_extents ((array_t *) mask, (array_t *) array,
345 "MASK argument", "MINLOC");
349 for (n = 0; n < rank; n++)
351 count[n] = 0;
352 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
353 if (extent[n] <= 0)
354 return;
357 dest = retarray->base_addr;
358 base = array->base_addr;
360 while (base)
362 const GFC_UINTEGER_4 * restrict src;
363 const GFC_LOGICAL_1 * restrict msrc;
364 GFC_INTEGER_16 result;
365 src = base;
366 msrc = mbase;
369 const GFC_UINTEGER_4 *minval;
370 minval = base;
371 result = 0;
372 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
375 if (*msrc)
377 minval = src;
378 result = (GFC_INTEGER_16)n + 1;
379 break;
382 for (; n < len; n++, src += delta, msrc += mdelta)
384 if (*msrc && (back ? compare_fcn (src, minval, string_len) <= 0 :
385 compare_fcn (src, minval, string_len) < 0))
387 minval = src;
388 result = (GFC_INTEGER_16)n + 1;
392 *dest = result;
394 /* Advance to the next element. */
395 count[0]++;
396 base += sstride[0];
397 mbase += mstride[0];
398 dest += dstride[0];
399 n = 0;
400 while (count[n] == extent[n])
402 /* When we get to the end of a dimension, reset it and increment
403 the next dimension. */
404 count[n] = 0;
405 /* We could precalculate these products, but this is a less
406 frequently used path so probably not worth it. */
407 base -= sstride[n] * extent[n];
408 mbase -= mstride[n] * extent[n];
409 dest -= dstride[n] * extent[n];
410 n++;
411 if (n >= rank)
413 /* Break out of the loop. */
414 base = NULL;
415 break;
417 else
419 count[n]++;
420 base += sstride[n];
421 mbase += mstride[n];
422 dest += dstride[n];
429 extern void sminloc1_16_s4 (gfc_array_i16 * const restrict,
430 gfc_array_s4 * const restrict, const index_type * const restrict,
431 GFC_LOGICAL_4 *, GFC_LOGICAL_4 back, gfc_charlen_type);
432 export_proto(sminloc1_16_s4);
434 void
435 sminloc1_16_s4 (gfc_array_i16 * const restrict retarray,
436 gfc_array_s4 * const restrict array,
437 const index_type * const restrict pdim,
438 GFC_LOGICAL_4 * mask , GFC_LOGICAL_4 back, gfc_charlen_type string_len)
440 index_type count[GFC_MAX_DIMENSIONS];
441 index_type extent[GFC_MAX_DIMENSIONS];
442 index_type dstride[GFC_MAX_DIMENSIONS];
443 GFC_INTEGER_16 * restrict dest;
444 index_type rank;
445 index_type n;
446 index_type dim;
449 if (mask == NULL || *mask)
451 #ifdef HAVE_BACK_ARG
452 minloc1_16_s4 (retarray, array, pdim, back, string_len);
453 #else
454 minloc1_16_s4 (retarray, array, pdim, string_len);
455 #endif
456 return;
458 /* Make dim zero based to avoid confusion. */
459 dim = (*pdim) - 1;
460 rank = GFC_DESCRIPTOR_RANK (array) - 1;
462 if (unlikely (dim < 0 || dim > rank))
464 runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
465 "is %ld, should be between 1 and %ld",
466 (long int) dim + 1, (long int) rank + 1);
469 for (n = 0; n < dim; n++)
471 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
473 if (extent[n] <= 0)
474 extent[n] = 0;
477 for (n = dim; n < rank; n++)
479 extent[n] =
480 GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
482 if (extent[n] <= 0)
483 extent[n] = 0;
486 if (retarray->base_addr == NULL)
488 size_t alloc_size, str;
490 for (n = 0; n < rank; n++)
492 if (n == 0)
493 str = 1;
494 else
495 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
497 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
501 retarray->offset = 0;
502 retarray->dtype.rank = rank;
504 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
506 if (alloc_size == 0)
508 /* Make sure we have a zero-sized array. */
509 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
510 return;
512 else
513 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
515 else
517 if (rank != GFC_DESCRIPTOR_RANK (retarray))
518 runtime_error ("rank of return array incorrect in"
519 " MINLOC intrinsic: is %ld, should be %ld",
520 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
521 (long int) rank);
523 if (unlikely (compile_options.bounds_check))
525 for (n=0; n < rank; n++)
527 index_type ret_extent;
529 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
530 if (extent[n] != ret_extent)
531 runtime_error ("Incorrect extent in return value of"
532 " MINLOC intrinsic in dimension %ld:"
533 " is %ld, should be %ld", (long int) n + 1,
534 (long int) ret_extent, (long int) extent[n]);
539 for (n = 0; n < rank; n++)
541 count[n] = 0;
542 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
545 dest = retarray->base_addr;
547 while(1)
549 *dest = 0;
550 count[0]++;
551 dest += dstride[0];
552 n = 0;
553 while (count[n] == extent[n])
555 /* When we get to the end of a dimension, reset it and increment
556 the next dimension. */
557 count[n] = 0;
558 /* We could precalculate these products, but this is a less
559 frequently used path so probably not worth it. */
560 dest -= dstride[n] * extent[n];
561 n++;
562 if (n >= rank)
563 return;
564 else
566 count[n]++;
567 dest += dstride[n];
573 #endif