minloc2s.m4 revision 1.1.1.4 1 1.1 mrg `/* Implementation of the MINLOC intrinsic
2 1.1.1.3 mrg Copyright (C) 2017-2022 Free Software Foundation, Inc.
3 1.1 mrg Contributed by Thomas Koenig
4 1.1 mrg
5 1.1 mrg This file is part of the GNU Fortran runtime library (libgfortran).
6 1.1 mrg
7 1.1 mrg Libgfortran is free software; you can redistribute it and/or
8 1.1 mrg modify it under the terms of the GNU General Public
9 1.1 mrg License as published by the Free Software Foundation; either
10 1.1 mrg version 3 of the License, or (at your option) any later version.
11 1.1 mrg
12 1.1 mrg Libgfortran is distributed in the hope that it will be useful,
13 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 mrg GNU General Public License for more details.
16 1.1 mrg
17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
18 1.1 mrg permissions described in the GCC Runtime Library Exception, version
19 1.1 mrg 3.1, as published by the Free Software Foundation.
20 1.1 mrg
21 1.1 mrg You should have received a copy of the GNU General Public License and
22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 1.1 mrg <http://www.gnu.org/licenses/>. */
25 1.1 mrg
26 1.1 mrg #include "libgfortran.h"
27 1.1 mrg #include <stdlib.h>
28 1.1 mrg #include <string.h>
29 1.1 mrg #include <assert.h>'
30 1.1 mrg include(iparm.m4)dnl
31 1.1 mrg
32 1.1 mrg `#if defined (HAVE_'atype_name`) && defined (HAVE_'rtype_name`)
33 1.1 mrg
34 1.1 mrg static inline int
35 1.1 mrg compare_fcn (const 'atype_name` *a, const 'atype_name` *b, gfc_charlen_type n)
36 1.1 mrg {
37 1.1 mrg if (sizeof ('atype_name`) == 1)
38 1.1 mrg return memcmp (a, b, n);
39 1.1 mrg else
40 1.1 mrg return memcmp_char4 (a, b, n);
41 1.1 mrg }
42 1.1 mrg
43 1.1 mrg extern 'rtype_name` 'name`'rtype_qual`_'atype_code` ('atype` * const restrict'back_arg`,
44 1.1 mrg gfc_charlen_type);
45 1.1 mrg export_proto('name`'rtype_qual`_'atype_code`);
46 1.1 mrg
47 1.1 mrg 'rtype_name`
48 1.1 mrg 'name`'rtype_qual`_'atype_code` ('atype` * const restrict array'back_arg`,
49 1.1 mrg gfc_charlen_type len)
50 1.1 mrg {
51 1.1 mrg index_type ret;
52 1.1 mrg index_type sstride;
53 1.1 mrg index_type extent;
54 1.1 mrg const 'atype_name` *src;
55 1.1 mrg const 'atype_name` *minval;
56 1.1 mrg index_type i;
57 1.1 mrg
58 1.1 mrg extent = GFC_DESCRIPTOR_EXTENT(array,0);
59 1.1 mrg if (extent <= 0)
60 1.1 mrg return 0;
61 1.1 mrg
62 1.1 mrg sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
63 1.1 mrg
64 1.1 mrg ret = 1;
65 1.1 mrg src = array->base_addr;
66 1.1 mrg minval = NULL;
67 1.1 mrg for (i=1; i<=extent; i++)
68 1.1 mrg {
69 1.1 mrg if (minval == NULL || (back ? compare_fcn (src, minval, len) <= 0 :
70 1.1 mrg compare_fcn (src, minval, len) < 0))
71 1.1 mrg {
72 1.1 mrg ret = i;
73 1.1 mrg minval = src;
74 1.1 mrg }
75 1.1 mrg src += sstride;
76 1.1 mrg }
77 1.1 mrg return ret;
78 1.1 mrg }
79 1.1 mrg
80 1.1 mrg extern 'rtype_name` m'name`'rtype_qual`_'atype_code` ('atype` * const restrict,
81 1.1 mrg gfc_array_l1 *const restrict mask'back_arg`,
82 1.1 mrg gfc_charlen_type);
83 1.1 mrg export_proto(m'name`'rtype_qual`_'atype_code`);
84 1.1 mrg
85 1.1 mrg 'rtype_name`
86 1.1 mrg m'name`'rtype_qual`_'atype_code` ('atype` * const restrict array,
87 1.1 mrg gfc_array_l1 * const restrict mask'back_arg`,
88 1.1 mrg gfc_charlen_type len)
89 1.1 mrg {
90 1.1 mrg index_type ret;
91 1.1 mrg index_type sstride;
92 1.1 mrg index_type extent;
93 1.1 mrg const 'atype_name` *src;
94 1.1 mrg const 'atype_name` *maxval;
95 1.1 mrg index_type i, j;
96 1.1 mrg GFC_LOGICAL_1 *mbase;
97 1.1 mrg int mask_kind;
98 1.1 mrg index_type mstride;
99 1.1 mrg
100 1.1 mrg extent = GFC_DESCRIPTOR_EXTENT(array,0);
101 1.1 mrg if (extent <= 0)
102 1.1 mrg return 0;
103 1.1 mrg
104 1.1 mrg sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
105 1.1 mrg
106 1.1 mrg mask_kind = GFC_DESCRIPTOR_SIZE (mask);
107 1.1 mrg mbase = mask->base_addr;
108 1.1 mrg
109 1.1 mrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
110 1.1 mrg #ifdef HAVE_GFC_LOGICAL_16
111 1.1 mrg || mask_kind == 16
112 1.1 mrg #endif
113 1.1 mrg )
114 1.1 mrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
115 1.1 mrg else
116 1.1 mrg internal_error (NULL, "Funny sized logical array");
117 1.1 mrg
118 1.1 mrg mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
119 1.1 mrg
120 1.1 mrg /* Search for the first occurrence of a true element in mask. */
121 1.1 mrg for (j=0; j<extent; j++)
122 1.1 mrg {
123 1.1 mrg if (*mbase)
124 1.1 mrg break;
125 1.1 mrg mbase += mstride;
126 1.1 mrg }
127 1.1 mrg
128 1.1 mrg if (j == extent)
129 1.1 mrg return 0;
130 1.1 mrg
131 1.1 mrg ret = j + 1;
132 1.1 mrg src = array->base_addr + j * sstride;
133 1.1 mrg maxval = src;
134 1.1 mrg
135 1.1 mrg for (i=j+1; i<=extent; i++)
136 1.1 mrg {
137 1.1 mrg
138 1.1 mrg if (*mbase && (back ? compare_fcn (src, maxval, len) <= 0 :
139 1.1 mrg compare_fcn (src, maxval, len) < 0))
140 1.1 mrg {
141 1.1 mrg ret = i;
142 1.1 mrg maxval = src;
143 1.1 mrg }
144 1.1 mrg src += sstride;
145 1.1 mrg mbase += mstride;
146 1.1 mrg }
147 1.1 mrg return ret;
148 1.1 mrg }
149 1.1 mrg
150 1.1 mrg extern 'rtype_name` s'name`'rtype_qual`_'atype_code` ('atype` * const restrict,
151 1.1 mrg GFC_LOGICAL_4 *mask'back_arg`, gfc_charlen_type);
152 1.1 mrg export_proto(s'name`'rtype_qual`_'atype_code`);
153 1.1 mrg
154 1.1 mrg 'rtype_name`
155 1.1 mrg s'name`'rtype_qual`_'atype_code` ('atype` * const restrict array,
156 1.1 mrg GFC_LOGICAL_4 *mask'back_arg`, gfc_charlen_type len)
157 1.1 mrg {
158 1.1.1.4 mrg if (mask == NULL || *mask)
159 1.1.1.4 mrg return 'name`'rtype_qual`_'atype_code` (array, back, len);
160 1.1 mrg else
161 1.1 mrg return 0;
162 1.1 mrg }
163 1.1 mrg
164 1.1 mrg #endif'
165