1181254a7Smrg /* Implementation of the MAXLOC intrinsic
2*b1e83836Smrg Copyright (C) 2017-2022 Free Software Foundation, Inc.
3181254a7Smrg Contributed by Thomas Koenig
4181254a7Smrg
5181254a7Smrg This file is part of the GNU Fortran runtime library (libgfortran).
6181254a7Smrg
7181254a7Smrg Libgfortran is free software; you can redistribute it and/or
8181254a7Smrg modify it under the terms of the GNU General Public
9181254a7Smrg License as published by the Free Software Foundation; either
10181254a7Smrg version 3 of the License, or (at your option) any later version.
11181254a7Smrg
12181254a7Smrg Libgfortran is distributed in the hope that it will be useful,
13181254a7Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14181254a7Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15181254a7Smrg GNU General Public License for more details.
16181254a7Smrg
17181254a7Smrg Under Section 7 of GPL version 3, you are granted additional
18181254a7Smrg permissions described in the GCC Runtime Library Exception, version
19181254a7Smrg 3.1, as published by the Free Software Foundation.
20181254a7Smrg
21181254a7Smrg You should have received a copy of the GNU General Public License and
22181254a7Smrg a copy of the GCC Runtime Library Exception along with this program;
23181254a7Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24181254a7Smrg <http://www.gnu.org/licenses/>. */
25181254a7Smrg
26181254a7Smrg #include "libgfortran.h"
27181254a7Smrg #include <stdlib.h>
28181254a7Smrg #include <string.h>
29181254a7Smrg #include <assert.h>
30181254a7Smrg
31181254a7Smrg #if defined (HAVE_GFC_UINTEGER_1) && defined (HAVE_GFC_INTEGER_8)
32181254a7Smrg
33181254a7Smrg static inline int
compare_fcn(const GFC_UINTEGER_1 * a,const GFC_UINTEGER_1 * b,gfc_charlen_type n)34181254a7Smrg compare_fcn (const GFC_UINTEGER_1 *a, const GFC_UINTEGER_1 *b, gfc_charlen_type n)
35181254a7Smrg {
36181254a7Smrg if (sizeof (GFC_UINTEGER_1) == 1)
37181254a7Smrg return memcmp (a, b, n);
38181254a7Smrg else
39181254a7Smrg return memcmp_char4 (a, b, n);
40181254a7Smrg }
41181254a7Smrg
42181254a7Smrg extern GFC_INTEGER_8 maxloc2_8_s1 (gfc_array_s1 * const restrict, GFC_LOGICAL_4 back,
43181254a7Smrg gfc_charlen_type);
44181254a7Smrg export_proto(maxloc2_8_s1);
45181254a7Smrg
46181254a7Smrg GFC_INTEGER_8
maxloc2_8_s1(gfc_array_s1 * const restrict array,GFC_LOGICAL_4 back,gfc_charlen_type len)47181254a7Smrg maxloc2_8_s1 (gfc_array_s1 * const restrict array, GFC_LOGICAL_4 back, gfc_charlen_type len)
48181254a7Smrg {
49181254a7Smrg index_type ret;
50181254a7Smrg index_type sstride;
51181254a7Smrg index_type extent;
52181254a7Smrg const GFC_UINTEGER_1 *src;
53181254a7Smrg const GFC_UINTEGER_1 *maxval;
54181254a7Smrg index_type i;
55181254a7Smrg
56181254a7Smrg extent = GFC_DESCRIPTOR_EXTENT(array,0);
57181254a7Smrg if (extent <= 0)
58181254a7Smrg return 0;
59181254a7Smrg
60181254a7Smrg sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
61181254a7Smrg
62181254a7Smrg ret = 1;
63181254a7Smrg src = array->base_addr;
64181254a7Smrg maxval = NULL;
65181254a7Smrg for (i=1; i<=extent; i++)
66181254a7Smrg {
67181254a7Smrg if (maxval == NULL || (back ? compare_fcn (src, maxval, len) >= 0 :
68181254a7Smrg compare_fcn (src, maxval, len) > 0))
69181254a7Smrg {
70181254a7Smrg ret = i;
71181254a7Smrg maxval = src;
72181254a7Smrg }
73181254a7Smrg src += sstride;
74181254a7Smrg }
75181254a7Smrg return ret;
76181254a7Smrg }
77181254a7Smrg
78181254a7Smrg extern GFC_INTEGER_8 mmaxloc2_8_s1 (gfc_array_s1 * const restrict,
79181254a7Smrg gfc_array_l1 *const restrict mask, GFC_LOGICAL_4 back,
80181254a7Smrg gfc_charlen_type);
81181254a7Smrg export_proto(mmaxloc2_8_s1);
82181254a7Smrg
83181254a7Smrg GFC_INTEGER_8
mmaxloc2_8_s1(gfc_array_s1 * const restrict array,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back,gfc_charlen_type len)84181254a7Smrg mmaxloc2_8_s1 (gfc_array_s1 * const restrict array,
85181254a7Smrg gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back,
86181254a7Smrg gfc_charlen_type len)
87181254a7Smrg {
88181254a7Smrg index_type ret;
89181254a7Smrg index_type sstride;
90181254a7Smrg index_type extent;
91181254a7Smrg const GFC_UINTEGER_1 *src;
92181254a7Smrg const GFC_UINTEGER_1 *maxval;
93181254a7Smrg index_type i, j;
94181254a7Smrg GFC_LOGICAL_1 *mbase;
95181254a7Smrg int mask_kind;
96181254a7Smrg index_type mstride;
97181254a7Smrg
98181254a7Smrg extent = GFC_DESCRIPTOR_EXTENT(array,0);
99181254a7Smrg if (extent <= 0)
100181254a7Smrg return 0;
101181254a7Smrg
102181254a7Smrg sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
103181254a7Smrg
104181254a7Smrg mask_kind = GFC_DESCRIPTOR_SIZE (mask);
105181254a7Smrg mbase = mask->base_addr;
106181254a7Smrg
107181254a7Smrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
108181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
109181254a7Smrg || mask_kind == 16
110181254a7Smrg #endif
111181254a7Smrg )
112181254a7Smrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
113181254a7Smrg else
114181254a7Smrg internal_error (NULL, "Funny sized logical array");
115181254a7Smrg
116181254a7Smrg mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
117181254a7Smrg
118181254a7Smrg /* Search for the first occurrence of a true element in mask. */
119181254a7Smrg for (j=0; j<extent; j++)
120181254a7Smrg {
121181254a7Smrg if (*mbase)
122181254a7Smrg break;
123181254a7Smrg mbase += mstride;
124181254a7Smrg }
125181254a7Smrg
126181254a7Smrg if (j == extent)
127181254a7Smrg return 0;
128181254a7Smrg
129181254a7Smrg ret = j + 1;
130181254a7Smrg src = array->base_addr + j * sstride;
131181254a7Smrg maxval = src;
132181254a7Smrg
133181254a7Smrg for (i=j+1; i<=extent; i++)
134181254a7Smrg {
135181254a7Smrg if (*mbase && (back ? compare_fcn (src, maxval, len) >= 0 :
136181254a7Smrg compare_fcn (src, maxval, len) > 0))
137181254a7Smrg {
138181254a7Smrg ret = i;
139181254a7Smrg maxval = src;
140181254a7Smrg }
141181254a7Smrg src += sstride;
142181254a7Smrg mbase += mstride;
143181254a7Smrg }
144181254a7Smrg return ret;
145181254a7Smrg }
146181254a7Smrg
147181254a7Smrg extern GFC_INTEGER_8 smaxloc2_8_s1 (gfc_array_s1 * const restrict,
148181254a7Smrg GFC_LOGICAL_4 *mask, GFC_LOGICAL_4 back, gfc_charlen_type);
149181254a7Smrg export_proto(smaxloc2_8_s1);
150181254a7Smrg
151181254a7Smrg GFC_INTEGER_8
smaxloc2_8_s1(gfc_array_s1 * const restrict array,GFC_LOGICAL_4 * mask,GFC_LOGICAL_4 back,gfc_charlen_type len)152181254a7Smrg smaxloc2_8_s1 (gfc_array_s1 * const restrict array,
153181254a7Smrg GFC_LOGICAL_4 *mask, GFC_LOGICAL_4 back, gfc_charlen_type len)
154181254a7Smrg {
155181254a7Smrg if (mask)
156181254a7Smrg return maxloc2_8_s1 (array, len, back);
157181254a7Smrg else
158181254a7Smrg return 0;
159181254a7Smrg }
160181254a7Smrg
161181254a7Smrg #endif
162