1 /* Implementation of the MAXVAL intrinsic
2 Copyright (C) 2017-2024 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_1) && defined (HAVE_GFC_UINTEGER_1)
35 compare_fcn (const GFC_UINTEGER_1
*a
, const GFC_UINTEGER_1
*b
, gfc_charlen_type n
)
37 if (sizeof (GFC_UINTEGER_1
) == 1)
38 return memcmp (a
, b
, n
);
40 return memcmp_char4 (a
, b
, n
);
43 extern void maxval1_s1 (gfc_array_s1
* const restrict
,
44 gfc_charlen_type
, gfc_array_s1
* const restrict
,
45 const index_type
* const restrict
, gfc_charlen_type
);
46 export_proto(maxval1_s1
);
49 maxval1_s1 (gfc_array_s1
* const restrict retarray
,
50 gfc_charlen_type xlen
, gfc_array_s1
* const restrict array
,
51 const index_type
* const restrict pdim
, gfc_charlen_type string_len
)
53 index_type count
[GFC_MAX_DIMENSIONS
];
54 index_type extent
[GFC_MAX_DIMENSIONS
];
55 index_type sstride
[GFC_MAX_DIMENSIONS
];
56 index_type dstride
[GFC_MAX_DIMENSIONS
];
57 const GFC_UINTEGER_1
* restrict base
;
58 GFC_UINTEGER_1
* restrict dest
;
66 assert (xlen
== string_len
);
67 /* Make dim zero based to avoid confusion. */
68 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
71 if (unlikely (dim
< 0 || dim
> rank
))
73 runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
74 "is %ld, should be between 1 and %ld",
75 (long int) dim
+ 1, (long int) rank
+ 1);
78 len
= GFC_DESCRIPTOR_EXTENT(array
,dim
);
82 delta
= GFC_DESCRIPTOR_STRIDE(array
,dim
) * string_len
;
84 for (n
= 0; n
< dim
; n
++)
86 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
) * string_len
;
87 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
92 for (n
= dim
; n
< rank
; n
++)
94 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
, n
+ 1) * string_len
;
95 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
, n
+ 1);
101 if (retarray
->base_addr
== NULL
)
103 size_t alloc_size
, str
;
105 for (n
= 0; n
< rank
; n
++)
110 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
112 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
116 retarray
->offset
= 0;
117 retarray
->dtype
.rank
= rank
;
119 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1]
122 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (GFC_UINTEGER_1
));
128 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
129 runtime_error ("rank of return array incorrect in"
130 " MAXVAL intrinsic: is %ld, should be %ld",
131 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
134 if (unlikely (compile_options
.bounds_check
))
135 bounds_ifunction_return ((array_t
*) retarray
, extent
,
136 "return value", "MAXVAL");
139 for (n
= 0; n
< rank
; n
++)
142 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
) * string_len
;
147 base
= array
->base_addr
;
148 dest
= retarray
->base_addr
;
151 while (continue_loop
)
153 const GFC_UINTEGER_1
* restrict src
;
157 const GFC_UINTEGER_1
*retval
;
160 memset (dest
, 0, sizeof (*dest
) * string_len
);
163 for (n
= 0; n
< len
; n
++, src
+= delta
)
166 if (compare_fcn (src
, retval
, string_len
) > 0)
172 memcpy (dest
, retval
, sizeof (*dest
) * string_len
);
175 /* Advance to the next element. */
180 while (count
[n
] == extent
[n
])
182 /* When we get to the end of a dimension, reset it and increment
183 the next dimension. */
185 /* We could precalculate these products, but this is a less
186 frequently used path so probably not worth it. */
187 base
-= sstride
[n
] * extent
[n
];
188 dest
-= dstride
[n
] * extent
[n
];
192 /* Break out of the loop. */
207 extern void mmaxval1_s1 (gfc_array_s1
* const restrict
,
208 gfc_charlen_type
, gfc_array_s1
* const restrict
,
209 const index_type
* const restrict
,
210 gfc_array_l1
* const restrict
, gfc_charlen_type
);
211 export_proto(mmaxval1_s1
);
214 mmaxval1_s1 (gfc_array_s1
* const restrict retarray
,
215 gfc_charlen_type xlen
, gfc_array_s1
* const restrict array
,
216 const index_type
* const restrict pdim
,
217 gfc_array_l1
* const restrict mask
,
218 gfc_charlen_type string_len
)
221 index_type count
[GFC_MAX_DIMENSIONS
];
222 index_type extent
[GFC_MAX_DIMENSIONS
];
223 index_type sstride
[GFC_MAX_DIMENSIONS
];
224 index_type dstride
[GFC_MAX_DIMENSIONS
];
225 index_type mstride
[GFC_MAX_DIMENSIONS
];
226 GFC_UINTEGER_1
* restrict dest
;
227 const GFC_UINTEGER_1
* restrict base
;
228 const GFC_LOGICAL_1
* restrict mbase
;
239 maxval1_s1 (retarray
, xlen
, array
, pdim
, string_len
);
243 assert (xlen
== string_len
);
246 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
248 if (unlikely (dim
< 0 || dim
> rank
))
250 runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
251 "is %ld, should be between 1 and %ld",
252 (long int) dim
+ 1, (long int) rank
+ 1);
255 len
= GFC_DESCRIPTOR_EXTENT(array
,dim
);
259 mbase
= mask
->base_addr
;
261 mask_kind
= GFC_DESCRIPTOR_SIZE (mask
);
263 if (mask_kind
== 1 || mask_kind
== 2 || mask_kind
== 4 || mask_kind
== 8
264 #ifdef HAVE_GFC_LOGICAL_16
268 mbase
= GFOR_POINTER_TO_L1 (mbase
, mask_kind
);
270 runtime_error ("Funny sized logical array");
272 delta
= GFC_DESCRIPTOR_STRIDE(array
,dim
) * string_len
;
273 mdelta
= GFC_DESCRIPTOR_STRIDE_BYTES(mask
,dim
);
275 for (n
= 0; n
< dim
; n
++)
277 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
) * string_len
;
278 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
,n
);
279 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
285 for (n
= dim
; n
< rank
; n
++)
287 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
+ 1) * string_len
;
288 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
, n
+ 1);
289 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
, n
+ 1);
295 if (retarray
->base_addr
== NULL
)
297 size_t alloc_size
, str
;
299 for (n
= 0; n
< rank
; n
++)
304 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
306 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
310 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1]
313 retarray
->offset
= 0;
314 retarray
->dtype
.rank
= rank
;
316 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (GFC_UINTEGER_1
));
322 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
323 runtime_error ("rank of return array incorrect in MAXVAL intrinsic");
325 if (unlikely (compile_options
.bounds_check
))
327 bounds_ifunction_return ((array_t
*) retarray
, extent
,
328 "return value", "MAXVAL");
329 bounds_equal_extents ((array_t
*) mask
, (array_t
*) array
,
330 "MASK argument", "MAXVAL");
334 for (n
= 0; n
< rank
; n
++)
337 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
) * string_len
;
342 dest
= retarray
->base_addr
;
343 base
= array
->base_addr
;
347 const GFC_UINTEGER_1
* restrict src
;
348 const GFC_LOGICAL_1
* restrict msrc
;
354 const GFC_UINTEGER_1
*retval
;
355 memset (dest
, 0, sizeof (*dest
) * string_len
);
357 for (n
= 0; n
< len
; n
++, src
+= delta
, msrc
+= mdelta
)
366 for (; n
< len
; n
++, src
+= delta
, msrc
+= mdelta
)
368 if (*msrc
&& compare_fcn (src
, retval
, string_len
) > 0)
374 memcpy (dest
, retval
, sizeof (*dest
) * string_len
);
376 /* Advance to the next element. */
382 while (count
[n
] == extent
[n
])
384 /* When we get to the end of a dimension, reset it and increment
385 the next dimension. */
387 /* We could precalculate these products, but this is a less
388 frequently used path so probably not worth it. */
389 base
-= sstride
[n
] * extent
[n
];
390 mbase
-= mstride
[n
] * extent
[n
];
391 dest
-= dstride
[n
] * extent
[n
];
395 /* Break out of the loop. */
411 void smaxval1_s1 (gfc_array_s1
* const restrict
,
412 gfc_charlen_type
, gfc_array_s1
* const restrict
,
413 const index_type
* const restrict
,
414 GFC_LOGICAL_4
*, gfc_charlen_type
);
416 export_proto(smaxval1_s1
);
419 smaxval1_s1 (gfc_array_s1
* const restrict retarray
,
420 gfc_charlen_type xlen
, gfc_array_s1
* const restrict array
,
421 const index_type
* const restrict pdim
,
422 GFC_LOGICAL_4
*mask
, gfc_charlen_type string_len
)
425 index_type count
[GFC_MAX_DIMENSIONS
];
426 index_type extent
[GFC_MAX_DIMENSIONS
];
427 index_type dstride
[GFC_MAX_DIMENSIONS
];
428 GFC_UINTEGER_1
* restrict dest
;
434 if (mask
== NULL
|| *mask
)
436 maxval1_s1 (retarray
, xlen
, array
, pdim
, string_len
);
439 /* Make dim zero based to avoid confusion. */
441 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
443 if (unlikely (dim
< 0 || dim
> rank
))
445 runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
446 "is %ld, should be between 1 and %ld",
447 (long int) dim
+ 1, (long int) rank
+ 1);
450 for (n
= 0; n
< dim
; n
++)
452 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
458 for (n
= dim
; n
< rank
; n
++)
461 GFC_DESCRIPTOR_EXTENT(array
,n
+ 1);
467 if (retarray
->base_addr
== NULL
)
469 size_t alloc_size
, str
;
471 for (n
= 0; n
< rank
; n
++)
476 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
478 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
482 retarray
->offset
= 0;
483 retarray
->dtype
.rank
= rank
;
485 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1]
488 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (GFC_UINTEGER_1
));
494 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
495 runtime_error ("rank of return array incorrect in"
496 " MAXVAL intrinsic: is %ld, should be %ld",
497 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
500 if (unlikely (compile_options
.bounds_check
))
502 for (n
=0; n
< rank
; n
++)
504 index_type ret_extent
;
506 ret_extent
= GFC_DESCRIPTOR_EXTENT(retarray
,n
);
507 if (extent
[n
] != ret_extent
)
508 runtime_error ("Incorrect extent in return value of"
509 " MAXVAL intrinsic in dimension %ld:"
510 " is %ld, should be %ld", (long int) n
+ 1,
511 (long int) ret_extent
, (long int) extent
[n
]);
516 for (n
= 0; n
< rank
; n
++)
519 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
) * string_len
;
522 dest
= retarray
->base_addr
;
526 memset (dest
, 0, sizeof (*dest
) * string_len
);
530 while (count
[n
] == extent
[n
])
532 /* When we get to the end of a dimension, reset it and increment
533 the next dimension. */
535 /* We could precalculate these products, but this is a less
536 frequently used path so probably not worth it. */
537 dest
-= dstride
[n
] * extent
[n
];