2017-12-07 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / libgfortran / generated / minloc0_16_s1.c
blobe43feaf2c4e07c6ae36a1b30708e7b8e023d5f45
1 /* Implementation of the MINLOC intrinsic
2 Copyright 2017 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"
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <limits.h>
33 #if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_16)
35 static inline int
36 compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
38 if (sizeof (GFC_INTEGER_1) == 1)
39 return memcmp (a, b, n);
40 else
41 return memcmp_char4 (a, b, n);
45 extern void minloc0_16_s1 (gfc_array_i16 * const restrict retarray,
46 gfc_array_s1 * const restrict array, gfc_charlen_type len);
47 export_proto(minloc0_16_s1);
49 void
50 minloc0_16_s1 (gfc_array_i16 * const restrict retarray,
51 gfc_array_s1 * const restrict array, gfc_charlen_type 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;
57 const GFC_INTEGER_1 *base;
58 GFC_INTEGER_16 * restrict dest;
59 index_type rank;
60 index_type n;
62 rank = GFC_DESCRIPTOR_RANK (array);
63 if (rank <= 0)
64 runtime_error ("Rank of array needs to be > 0");
66 if (retarray->base_addr == NULL)
68 GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
69 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
70 retarray->offset = 0;
71 retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
73 else
75 if (unlikely (compile_options.bounds_check))
76 bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
77 "MINLOC");
80 dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
81 dest = retarray->base_addr;
82 for (n = 0; n < rank; n++)
84 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
85 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
86 count[n] = 0;
87 if (extent[n] <= 0)
89 /* Set the return value. */
90 for (n = 0; n < rank; n++)
91 dest[n * dstride] = 0;
92 return;
96 base = array->base_addr;
98 /* Initialize the return value. */
99 for (n = 0; n < rank; n++)
100 dest[n * dstride] = 1;
103 const GFC_INTEGER_1 *minval;
104 minval = base;
106 while (base)
110 /* Implementation start. */
112 if (compare_fcn (base, minval, len) < 0)
114 minval = base;
115 for (n = 0; n < rank; n++)
116 dest[n * dstride] = count[n] + 1;
118 /* Implementation end. */
119 /* Advance to the next element. */
120 base += sstride[0];
122 while (++count[0] != extent[0]);
123 n = 0;
126 /* When we get to the end of a dimension, reset it and increment
127 the next dimension. */
128 count[n] = 0;
129 /* We could precalculate these products, but this is a less
130 frequently used path so probably not worth it. */
131 base -= sstride[n] * extent[n];
132 n++;
133 if (n >= rank)
135 /* Break out of the loop. */
136 base = NULL;
137 break;
139 else
141 count[n]++;
142 base += sstride[n];
145 while (count[n] == extent[n]);
151 extern void mminloc0_16_s1 (gfc_array_i16 * const restrict,
152 gfc_array_s1 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
153 export_proto(mminloc0_16_s1);
155 void
156 mminloc0_16_s1 (gfc_array_i16 * const restrict retarray,
157 gfc_array_s1 * const restrict array,
158 gfc_array_l1 * const restrict mask, gfc_charlen_type len)
160 index_type count[GFC_MAX_DIMENSIONS];
161 index_type extent[GFC_MAX_DIMENSIONS];
162 index_type sstride[GFC_MAX_DIMENSIONS];
163 index_type mstride[GFC_MAX_DIMENSIONS];
164 index_type dstride;
165 GFC_INTEGER_16 *dest;
166 const GFC_INTEGER_1 *base;
167 GFC_LOGICAL_1 *mbase;
168 int rank;
169 index_type n;
170 int mask_kind;
172 rank = GFC_DESCRIPTOR_RANK (array);
173 if (rank <= 0)
174 runtime_error ("Rank of array needs to be > 0");
176 if (retarray->base_addr == NULL)
178 GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
179 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
180 retarray->offset = 0;
181 retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
183 else
185 if (unlikely (compile_options.bounds_check))
188 bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
189 "MINLOC");
190 bounds_equal_extents ((array_t *) mask, (array_t *) array,
191 "MASK argument", "MINLOC");
195 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
197 mbase = mask->base_addr;
199 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
200 #ifdef HAVE_GFC_LOGICAL_16
201 || mask_kind == 16
202 #endif
204 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
205 else
206 runtime_error ("Funny sized logical array");
208 dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
209 dest = retarray->base_addr;
210 for (n = 0; n < rank; n++)
212 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
213 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
214 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
215 count[n] = 0;
216 if (extent[n] <= 0)
218 /* Set the return value. */
219 for (n = 0; n < rank; n++)
220 dest[n * dstride] = 0;
221 return;
225 base = array->base_addr;
227 /* Initialize the return value. */
228 for (n = 0; n < rank; n++)
229 dest[n * dstride] = 0;
232 const GFC_INTEGER_1 *minval;
234 minval = NULL;
236 while (base)
240 /* Implementation start. */
242 if (*mbase && (minval == NULL || compare_fcn (base, minval, len) < 0))
244 minval = base;
245 for (n = 0; n < rank; n++)
246 dest[n * dstride] = count[n] + 1;
248 /* Implementation end. */
249 /* Advance to the next element. */
250 base += sstride[0];
251 mbase += mstride[0];
253 while (++count[0] != extent[0]);
254 n = 0;
257 /* When we get to the end of a dimension, reset it and increment
258 the next dimension. */
259 count[n] = 0;
260 /* We could precalculate these products, but this is a less
261 frequently used path so probably not worth it. */
262 base -= sstride[n] * extent[n];
263 mbase -= mstride[n] * extent[n];
264 n++;
265 if (n >= rank)
267 /* Break out of the loop. */
268 base = NULL;
269 break;
271 else
273 count[n]++;
274 base += sstride[n];
275 mbase += mstride[n];
278 while (count[n] == extent[n]);
284 extern void sminloc0_16_s1 (gfc_array_i16 * const restrict,
285 gfc_array_s1 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
286 export_proto(sminloc0_16_s1);
288 void
289 sminloc0_16_s1 (gfc_array_i16 * const restrict retarray,
290 gfc_array_s1 * const restrict array,
291 GFC_LOGICAL_4 * mask, gfc_charlen_type len)
293 index_type rank;
294 index_type dstride;
295 index_type n;
296 GFC_INTEGER_16 *dest;
298 if (*mask)
300 minloc0_16_s1 (retarray, array, len);
301 return;
304 rank = GFC_DESCRIPTOR_RANK (array);
306 if (rank <= 0)
307 runtime_error ("Rank of array needs to be > 0");
309 if (retarray->base_addr == NULL)
311 GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
312 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
313 retarray->offset = 0;
314 retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
316 else if (unlikely (compile_options.bounds_check))
318 bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
319 "MINLOC");
322 dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
323 dest = retarray->base_addr;
324 for (n = 0; n<rank; n++)
325 dest[n * dstride] = 0 ;
327 #endif