Small ChangeLog tweak.
[official-gcc.git] / libgfortran / generated / minval_i4.c
blob73de782ef0941ca938ee07fcad565d0edd218d09
1 /* Implementation of the MINVAL intrinsic
2 Copyright (C) 2002-2017 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
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_INTEGER_4) && defined (HAVE_GFC_INTEGER_4)
32 extern void minval_i4 (gfc_array_i4 * const restrict,
33 gfc_array_i4 * const restrict, const index_type * const restrict);
34 export_proto(minval_i4);
36 void
37 minval_i4 (gfc_array_i4 * const restrict retarray,
38 gfc_array_i4 * const restrict array,
39 const index_type * const restrict pdim)
41 index_type count[GFC_MAX_DIMENSIONS];
42 index_type extent[GFC_MAX_DIMENSIONS];
43 index_type sstride[GFC_MAX_DIMENSIONS];
44 index_type dstride[GFC_MAX_DIMENSIONS];
45 const GFC_INTEGER_4 * restrict base;
46 GFC_INTEGER_4 * restrict dest;
47 index_type rank;
48 index_type n;
49 index_type len;
50 index_type delta;
51 index_type dim;
52 int continue_loop;
54 /* Make dim zero based to avoid confusion. */
55 dim = (*pdim) - 1;
56 rank = GFC_DESCRIPTOR_RANK (array) - 1;
58 len = GFC_DESCRIPTOR_EXTENT(array,dim);
59 if (len < 0)
60 len = 0;
61 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
63 for (n = 0; n < dim; n++)
65 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
66 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
68 if (extent[n] < 0)
69 extent[n] = 0;
71 for (n = dim; n < rank; n++)
73 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
74 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
76 if (extent[n] < 0)
77 extent[n] = 0;
80 if (retarray->base_addr == NULL)
82 size_t alloc_size, str;
84 for (n = 0; n < rank; n++)
86 if (n == 0)
87 str = 1;
88 else
89 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
91 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
95 retarray->offset = 0;
96 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
98 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
100 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
101 if (alloc_size == 0)
103 /* Make sure we have a zero-sized array. */
104 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
105 return;
109 else
111 if (rank != GFC_DESCRIPTOR_RANK (retarray))
112 runtime_error ("rank of return array incorrect in"
113 " MINVAL intrinsic: is %ld, should be %ld",
114 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
115 (long int) rank);
117 if (unlikely (compile_options.bounds_check))
118 bounds_ifunction_return ((array_t *) retarray, extent,
119 "return value", "MINVAL");
122 for (n = 0; n < rank; n++)
124 count[n] = 0;
125 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
126 if (extent[n] <= 0)
127 return;
130 base = array->base_addr;
131 dest = retarray->base_addr;
133 continue_loop = 1;
134 while (continue_loop)
136 const GFC_INTEGER_4 * restrict src;
137 GFC_INTEGER_4 result;
138 src = base;
141 #if defined (GFC_INTEGER_4_INFINITY)
142 result = GFC_INTEGER_4_INFINITY;
143 #else
144 result = GFC_INTEGER_4_HUGE;
145 #endif
146 if (len <= 0)
147 *dest = GFC_INTEGER_4_HUGE;
148 else
150 for (n = 0; n < len; n++, src += delta)
153 #if defined (GFC_INTEGER_4_QUIET_NAN)
154 if (*src <= result)
155 break;
157 if (unlikely (n >= len))
158 result = GFC_INTEGER_4_QUIET_NAN;
159 else for (; n < len; n++, src += delta)
161 #endif
162 if (*src < result)
163 result = *src;
166 *dest = result;
169 /* Advance to the next element. */
170 count[0]++;
171 base += sstride[0];
172 dest += dstride[0];
173 n = 0;
174 while (count[n] == extent[n])
176 /* When we get to the end of a dimension, reset it and increment
177 the next dimension. */
178 count[n] = 0;
179 /* We could precalculate these products, but this is a less
180 frequently used path so probably not worth it. */
181 base -= sstride[n] * extent[n];
182 dest -= dstride[n] * extent[n];
183 n++;
184 if (n >= rank)
186 /* Break out of the loop. */
187 continue_loop = 0;
188 break;
190 else
192 count[n]++;
193 base += sstride[n];
194 dest += dstride[n];
201 extern void mminval_i4 (gfc_array_i4 * const restrict,
202 gfc_array_i4 * const restrict, const index_type * const restrict,
203 gfc_array_l1 * const restrict);
204 export_proto(mminval_i4);
206 void
207 mminval_i4 (gfc_array_i4 * const restrict retarray,
208 gfc_array_i4 * const restrict array,
209 const index_type * const restrict pdim,
210 gfc_array_l1 * const restrict mask)
212 index_type count[GFC_MAX_DIMENSIONS];
213 index_type extent[GFC_MAX_DIMENSIONS];
214 index_type sstride[GFC_MAX_DIMENSIONS];
215 index_type dstride[GFC_MAX_DIMENSIONS];
216 index_type mstride[GFC_MAX_DIMENSIONS];
217 GFC_INTEGER_4 * restrict dest;
218 const GFC_INTEGER_4 * restrict base;
219 const GFC_LOGICAL_1 * restrict mbase;
220 int rank;
221 int dim;
222 index_type n;
223 index_type len;
224 index_type delta;
225 index_type mdelta;
226 int mask_kind;
228 dim = (*pdim) - 1;
229 rank = GFC_DESCRIPTOR_RANK (array) - 1;
231 len = GFC_DESCRIPTOR_EXTENT(array,dim);
232 if (len <= 0)
233 return;
235 mbase = mask->base_addr;
237 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
239 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
240 #ifdef HAVE_GFC_LOGICAL_16
241 || mask_kind == 16
242 #endif
244 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
245 else
246 runtime_error ("Funny sized logical array");
248 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
249 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
251 for (n = 0; n < dim; n++)
253 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
254 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
255 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
257 if (extent[n] < 0)
258 extent[n] = 0;
261 for (n = dim; n < rank; n++)
263 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
264 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
265 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
267 if (extent[n] < 0)
268 extent[n] = 0;
271 if (retarray->base_addr == NULL)
273 size_t alloc_size, str;
275 for (n = 0; n < rank; n++)
277 if (n == 0)
278 str = 1;
279 else
280 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
282 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
286 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
288 retarray->offset = 0;
289 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
291 if (alloc_size == 0)
293 /* Make sure we have a zero-sized array. */
294 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
295 return;
297 else
298 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
301 else
303 if (rank != GFC_DESCRIPTOR_RANK (retarray))
304 runtime_error ("rank of return array incorrect in MINVAL intrinsic");
306 if (unlikely (compile_options.bounds_check))
308 bounds_ifunction_return ((array_t *) retarray, extent,
309 "return value", "MINVAL");
310 bounds_equal_extents ((array_t *) mask, (array_t *) array,
311 "MASK argument", "MINVAL");
315 for (n = 0; n < rank; n++)
317 count[n] = 0;
318 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
319 if (extent[n] <= 0)
320 return;
323 dest = retarray->base_addr;
324 base = array->base_addr;
326 while (base)
328 const GFC_INTEGER_4 * restrict src;
329 const GFC_LOGICAL_1 * restrict msrc;
330 GFC_INTEGER_4 result;
331 src = base;
332 msrc = mbase;
335 #if defined (GFC_INTEGER_4_INFINITY)
336 result = GFC_INTEGER_4_INFINITY;
337 #else
338 result = GFC_INTEGER_4_HUGE;
339 #endif
340 #if defined (GFC_INTEGER_4_QUIET_NAN)
341 int non_empty_p = 0;
342 #endif
343 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
346 #if defined (GFC_INTEGER_4_INFINITY) || defined (GFC_INTEGER_4_QUIET_NAN)
347 if (*msrc)
349 #if defined (GFC_INTEGER_4_QUIET_NAN)
350 non_empty_p = 1;
351 if (*src <= result)
352 #endif
353 break;
356 if (unlikely (n >= len))
358 #if defined (GFC_INTEGER_4_QUIET_NAN)
359 result = non_empty_p ? GFC_INTEGER_4_QUIET_NAN : GFC_INTEGER_4_HUGE;
360 #else
361 result = GFC_INTEGER_4_HUGE;
362 #endif
364 else for (; n < len; n++, src += delta, msrc += mdelta)
366 #endif
367 if (*msrc && *src < result)
368 result = *src;
370 *dest = result;
372 /* Advance to the next element. */
373 count[0]++;
374 base += sstride[0];
375 mbase += mstride[0];
376 dest += dstride[0];
377 n = 0;
378 while (count[n] == extent[n])
380 /* When we get to the end of a dimension, reset it and increment
381 the next dimension. */
382 count[n] = 0;
383 /* We could precalculate these products, but this is a less
384 frequently used path so probably not worth it. */
385 base -= sstride[n] * extent[n];
386 mbase -= mstride[n] * extent[n];
387 dest -= dstride[n] * extent[n];
388 n++;
389 if (n >= rank)
391 /* Break out of the loop. */
392 base = NULL;
393 break;
395 else
397 count[n]++;
398 base += sstride[n];
399 mbase += mstride[n];
400 dest += dstride[n];
407 extern void sminval_i4 (gfc_array_i4 * const restrict,
408 gfc_array_i4 * const restrict, const index_type * const restrict,
409 GFC_LOGICAL_4 *);
410 export_proto(sminval_i4);
412 void
413 sminval_i4 (gfc_array_i4 * const restrict retarray,
414 gfc_array_i4 * const restrict array,
415 const index_type * const restrict pdim,
416 GFC_LOGICAL_4 * mask)
418 index_type count[GFC_MAX_DIMENSIONS];
419 index_type extent[GFC_MAX_DIMENSIONS];
420 index_type dstride[GFC_MAX_DIMENSIONS];
421 GFC_INTEGER_4 * restrict dest;
422 index_type rank;
423 index_type n;
424 index_type dim;
427 if (*mask)
429 minval_i4 (retarray, array, pdim);
430 return;
432 /* Make dim zero based to avoid confusion. */
433 dim = (*pdim) - 1;
434 rank = GFC_DESCRIPTOR_RANK (array) - 1;
436 for (n = 0; n < dim; n++)
438 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
440 if (extent[n] <= 0)
441 extent[n] = 0;
444 for (n = dim; n < rank; n++)
446 extent[n] =
447 GFC_DESCRIPTOR_EXTENT(array,n + 1);
449 if (extent[n] <= 0)
450 extent[n] = 0;
453 if (retarray->base_addr == NULL)
455 size_t alloc_size, str;
457 for (n = 0; n < rank; n++)
459 if (n == 0)
460 str = 1;
461 else
462 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
464 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
468 retarray->offset = 0;
469 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
471 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
473 if (alloc_size == 0)
475 /* Make sure we have a zero-sized array. */
476 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
477 return;
479 else
480 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
482 else
484 if (rank != GFC_DESCRIPTOR_RANK (retarray))
485 runtime_error ("rank of return array incorrect in"
486 " MINVAL intrinsic: is %ld, should be %ld",
487 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
488 (long int) rank);
490 if (unlikely (compile_options.bounds_check))
492 for (n=0; n < rank; n++)
494 index_type ret_extent;
496 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
497 if (extent[n] != ret_extent)
498 runtime_error ("Incorrect extent in return value of"
499 " MINVAL intrinsic in dimension %ld:"
500 " is %ld, should be %ld", (long int) n + 1,
501 (long int) ret_extent, (long int) extent[n]);
506 for (n = 0; n < rank; n++)
508 count[n] = 0;
509 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
512 dest = retarray->base_addr;
514 while(1)
516 *dest = GFC_INTEGER_4_HUGE;
517 count[0]++;
518 dest += dstride[0];
519 n = 0;
520 while (count[n] == extent[n])
522 /* When we get to the end of a dimension, reset it and increment
523 the next dimension. */
524 count[n] = 0;
525 /* We could precalculate these products, but this is a less
526 frequently used path so probably not worth it. */
527 dest -= dstride[n] * extent[n];
528 n++;
529 if (n >= rank)
530 return;
531 else
533 count[n]++;
534 dest += dstride[n];
540 #endif