]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/generated/minloc1_4_i8.c
re PR libfortran/34670 (bounds checking for array intrinsics)
[thirdparty/gcc.git] / libgfortran / generated / minloc1_4_i8.c
1 /* Implementation of the MINLOC intrinsic
2 Copyright 2002, 2007 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6
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 2 of the License, or (at your option) any later version.
11
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
19 executable.)
20
21 Libgfortran is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public
27 License along with libgfortran; see the file COPYING. If not,
28 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
29 Boston, MA 02110-1301, USA. */
30
31 #include "libgfortran.h"
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <limits.h>
35
36
37 #if defined (HAVE_GFC_INTEGER_8) && defined (HAVE_GFC_INTEGER_4)
38
39
40 extern void minloc1_4_i8 (gfc_array_i4 * const restrict,
41 gfc_array_i8 * const restrict, const index_type * const restrict);
42 export_proto(minloc1_4_i8);
43
44 void
45 minloc1_4_i8 (gfc_array_i4 * const restrict retarray,
46 gfc_array_i8 * const restrict array,
47 const index_type * const restrict pdim)
48 {
49 index_type count[GFC_MAX_DIMENSIONS];
50 index_type extent[GFC_MAX_DIMENSIONS];
51 index_type sstride[GFC_MAX_DIMENSIONS];
52 index_type dstride[GFC_MAX_DIMENSIONS];
53 const GFC_INTEGER_8 * restrict base;
54 GFC_INTEGER_4 * restrict dest;
55 index_type rank;
56 index_type n;
57 index_type len;
58 index_type delta;
59 index_type dim;
60
61 /* Make dim zero based to avoid confusion. */
62 dim = (*pdim) - 1;
63 rank = GFC_DESCRIPTOR_RANK (array) - 1;
64
65 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
66 delta = array->dim[dim].stride;
67
68 for (n = 0; n < dim; n++)
69 {
70 sstride[n] = array->dim[n].stride;
71 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
72
73 if (extent[n] < 0)
74 extent[n] = 0;
75 }
76 for (n = dim; n < rank; n++)
77 {
78 sstride[n] = array->dim[n + 1].stride;
79 extent[n] =
80 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
81
82 if (extent[n] < 0)
83 extent[n] = 0;
84 }
85
86 if (retarray->data == NULL)
87 {
88 size_t alloc_size;
89
90 for (n = 0; n < rank; n++)
91 {
92 retarray->dim[n].lbound = 0;
93 retarray->dim[n].ubound = extent[n]-1;
94 if (n == 0)
95 retarray->dim[n].stride = 1;
96 else
97 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
98 }
99
100 retarray->offset = 0;
101 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
102
103 alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
104 * extent[rank-1];
105
106 if (alloc_size == 0)
107 {
108 /* Make sure we have a zero-sized array. */
109 retarray->dim[0].lbound = 0;
110 retarray->dim[0].ubound = -1;
111 return;
112 }
113 else
114 retarray->data = internal_malloc_size (alloc_size);
115 }
116 else
117 {
118 if (rank != GFC_DESCRIPTOR_RANK (retarray))
119 runtime_error ("rank of return array incorrect in"
120 " MINLOC intrinsic: is %d, should be %d",
121 GFC_DESCRIPTOR_RANK (retarray), rank);
122
123 if (compile_options.bounds_check)
124 {
125 for (n=0; n < rank; n++)
126 {
127 index_type ret_extent;
128
129 ret_extent = retarray->dim[n].ubound + 1
130 - retarray->dim[n].lbound;
131 if (extent[n] != ret_extent)
132 runtime_error ("Incorrect extent in return value of"
133 " MINLOC intrinsic in dimension %d:"
134 " is %ld, should be %ld", n + 1,
135 (long int) ret_extent, (long int) extent[n]);
136 }
137 }
138 }
139
140 for (n = 0; n < rank; n++)
141 {
142 count[n] = 0;
143 dstride[n] = retarray->dim[n].stride;
144 if (extent[n] <= 0)
145 len = 0;
146 }
147
148 base = array->data;
149 dest = retarray->data;
150
151 while (base)
152 {
153 const GFC_INTEGER_8 * restrict src;
154 GFC_INTEGER_4 result;
155 src = base;
156 {
157
158 GFC_INTEGER_8 minval;
159 minval = GFC_INTEGER_8_HUGE;
160 result = 0;
161 if (len <= 0)
162 *dest = 0;
163 else
164 {
165 for (n = 0; n < len; n++, src += delta)
166 {
167
168 if (*src < minval || !result)
169 {
170 minval = *src;
171 result = (GFC_INTEGER_4)n + 1;
172 }
173 }
174 *dest = result;
175 }
176 }
177 /* Advance to the next element. */
178 count[0]++;
179 base += sstride[0];
180 dest += dstride[0];
181 n = 0;
182 while (count[n] == extent[n])
183 {
184 /* When we get to the end of a dimension, reset it and increment
185 the next dimension. */
186 count[n] = 0;
187 /* We could precalculate these products, but this is a less
188 frequently used path so probably not worth it. */
189 base -= sstride[n] * extent[n];
190 dest -= dstride[n] * extent[n];
191 n++;
192 if (n == rank)
193 {
194 /* Break out of the look. */
195 base = NULL;
196 break;
197 }
198 else
199 {
200 count[n]++;
201 base += sstride[n];
202 dest += dstride[n];
203 }
204 }
205 }
206 }
207
208
209 extern void mminloc1_4_i8 (gfc_array_i4 * const restrict,
210 gfc_array_i8 * const restrict, const index_type * const restrict,
211 gfc_array_l1 * const restrict);
212 export_proto(mminloc1_4_i8);
213
214 void
215 mminloc1_4_i8 (gfc_array_i4 * const restrict retarray,
216 gfc_array_i8 * const restrict array,
217 const index_type * const restrict pdim,
218 gfc_array_l1 * const restrict mask)
219 {
220 index_type count[GFC_MAX_DIMENSIONS];
221 index_type extent[GFC_MAX_DIMENSIONS];
222 index_type sstride[GFC_MAX_DIMENSIONS];
223 index_type dstride[GFC_MAX_DIMENSIONS];
224 index_type mstride[GFC_MAX_DIMENSIONS];
225 GFC_INTEGER_4 * restrict dest;
226 const GFC_INTEGER_8 * restrict base;
227 const GFC_LOGICAL_1 * restrict mbase;
228 int rank;
229 int dim;
230 index_type n;
231 index_type len;
232 index_type delta;
233 index_type mdelta;
234 int mask_kind;
235
236 dim = (*pdim) - 1;
237 rank = GFC_DESCRIPTOR_RANK (array) - 1;
238
239 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
240 if (len <= 0)
241 return;
242
243 mbase = mask->data;
244
245 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
246
247 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
248 #ifdef HAVE_GFC_LOGICAL_16
249 || mask_kind == 16
250 #endif
251 )
252 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
253 else
254 runtime_error ("Funny sized logical array");
255
256 delta = array->dim[dim].stride;
257 mdelta = mask->dim[dim].stride * mask_kind;
258
259 for (n = 0; n < dim; n++)
260 {
261 sstride[n] = array->dim[n].stride;
262 mstride[n] = mask->dim[n].stride * mask_kind;
263 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
264
265 if (extent[n] < 0)
266 extent[n] = 0;
267
268 }
269 for (n = dim; n < rank; n++)
270 {
271 sstride[n] = array->dim[n + 1].stride;
272 mstride[n] = mask->dim[n + 1].stride * mask_kind;
273 extent[n] =
274 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
275
276 if (extent[n] < 0)
277 extent[n] = 0;
278 }
279
280 if (retarray->data == NULL)
281 {
282 size_t alloc_size;
283
284 for (n = 0; n < rank; n++)
285 {
286 retarray->dim[n].lbound = 0;
287 retarray->dim[n].ubound = extent[n]-1;
288 if (n == 0)
289 retarray->dim[n].stride = 1;
290 else
291 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
292 }
293
294 alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
295 * extent[rank-1];
296
297 retarray->offset = 0;
298 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
299
300 if (alloc_size == 0)
301 {
302 /* Make sure we have a zero-sized array. */
303 retarray->dim[0].lbound = 0;
304 retarray->dim[0].ubound = -1;
305 return;
306 }
307 else
308 retarray->data = internal_malloc_size (alloc_size);
309
310 }
311 else
312 {
313 if (rank != GFC_DESCRIPTOR_RANK (retarray))
314 runtime_error ("rank of return array incorrect in MINLOC intrinsic");
315
316 if (compile_options.bounds_check)
317 {
318 for (n=0; n < rank; n++)
319 {
320 index_type ret_extent;
321
322 ret_extent = retarray->dim[n].ubound + 1
323 - retarray->dim[n].lbound;
324 if (extent[n] != ret_extent)
325 runtime_error ("Incorrect extent in return value of"
326 " MINLOC intrinsic in dimension %d:"
327 " is %ld, should be %ld", n + 1,
328 (long int) ret_extent, (long int) extent[n]);
329 }
330 for (n=0; n<= rank; n++)
331 {
332 index_type mask_extent, array_extent;
333
334 array_extent = array->dim[n].ubound + 1 - array->dim[n].lbound;
335 mask_extent = mask->dim[n].ubound + 1 - mask->dim[n].lbound;
336 if (array_extent != mask_extent)
337 runtime_error ("Incorrect extent in MASK argument of"
338 " MINLOC intrinsic in dimension %d:"
339 " is %ld, should be %ld", n + 1,
340 (long int) mask_extent, (long int) array_extent);
341 }
342 }
343 }
344
345 for (n = 0; n < rank; n++)
346 {
347 count[n] = 0;
348 dstride[n] = retarray->dim[n].stride;
349 if (extent[n] <= 0)
350 return;
351 }
352
353 dest = retarray->data;
354 base = array->data;
355
356 while (base)
357 {
358 const GFC_INTEGER_8 * restrict src;
359 const GFC_LOGICAL_1 * restrict msrc;
360 GFC_INTEGER_4 result;
361 src = base;
362 msrc = mbase;
363 {
364
365 GFC_INTEGER_8 minval;
366 minval = GFC_INTEGER_8_HUGE;
367 result = 0;
368 if (len <= 0)
369 *dest = 0;
370 else
371 {
372 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
373 {
374
375 if (*msrc && (*src < minval || !result))
376 {
377 minval = *src;
378 result = (GFC_INTEGER_4)n + 1;
379 }
380 }
381 *dest = result;
382 }
383 }
384 /* Advance to the next element. */
385 count[0]++;
386 base += sstride[0];
387 mbase += mstride[0];
388 dest += dstride[0];
389 n = 0;
390 while (count[n] == extent[n])
391 {
392 /* When we get to the end of a dimension, reset it and increment
393 the next dimension. */
394 count[n] = 0;
395 /* We could precalculate these products, but this is a less
396 frequently used path so probably not worth it. */
397 base -= sstride[n] * extent[n];
398 mbase -= mstride[n] * extent[n];
399 dest -= dstride[n] * extent[n];
400 n++;
401 if (n == rank)
402 {
403 /* Break out of the look. */
404 base = NULL;
405 break;
406 }
407 else
408 {
409 count[n]++;
410 base += sstride[n];
411 mbase += mstride[n];
412 dest += dstride[n];
413 }
414 }
415 }
416 }
417
418
419 extern void sminloc1_4_i8 (gfc_array_i4 * const restrict,
420 gfc_array_i8 * const restrict, const index_type * const restrict,
421 GFC_LOGICAL_4 *);
422 export_proto(sminloc1_4_i8);
423
424 void
425 sminloc1_4_i8 (gfc_array_i4 * const restrict retarray,
426 gfc_array_i8 * const restrict array,
427 const index_type * const restrict pdim,
428 GFC_LOGICAL_4 * mask)
429 {
430 index_type rank;
431 index_type n;
432 index_type dstride;
433 GFC_INTEGER_4 *dest;
434
435 if (*mask)
436 {
437 minloc1_4_i8 (retarray, array, pdim);
438 return;
439 }
440 rank = GFC_DESCRIPTOR_RANK (array);
441 if (rank <= 0)
442 runtime_error ("Rank of array needs to be > 0");
443
444 if (retarray->data == NULL)
445 {
446 retarray->dim[0].lbound = 0;
447 retarray->dim[0].ubound = rank-1;
448 retarray->dim[0].stride = 1;
449 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
450 retarray->offset = 0;
451 retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
452 }
453 else
454 {
455 if (compile_options.bounds_check)
456 {
457 int ret_rank;
458 index_type ret_extent;
459
460 ret_rank = GFC_DESCRIPTOR_RANK (retarray);
461 if (ret_rank != 1)
462 runtime_error ("rank of return array in MINLOC intrinsic"
463 " should be 1, is %d", ret_rank);
464
465 ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
466 if (ret_extent != rank)
467 runtime_error ("dimension of return array incorrect");
468 }
469 }
470 dstride = retarray->dim[0].stride;
471 dest = retarray->data;
472
473 for (n = 0; n < rank; n++)
474 dest[n * dstride] = 0 ;
475 }
476
477 #endif