1 dnl Support macro file for intrinsic functions.
2 dnl Contains the generic sections of the array functions.
3 dnl This file is part of the GNU Fortran Runtime Library (libgfortran)
4 dnl Distributed under the GNU GPL with exception. See COPYING for details.
6 dnl Pass the implementation for a single section as the parameter to
7 dnl {MASK_}ARRAY_FUNCTION.
8 dnl The variables base, delta, and len describe the input section.
9 dnl For masked section the mask is described by mbase and mdelta.
10 dnl These should not be modified. The result should be stored in *dest.
11 dnl The names count, extent, sstride, dstride, base, dest, rank, dim
12 dnl retarray, array, pdim and mstride should not be used.
13 dnl The variable n is declared as index_type and may be used.
14 dnl Other variable declarations may be placed at the start of the code,
15 dnl The types of the array parameter and the return value are
16 dnl atype_name and rtype_name respectively.
17 dnl Execution should be allowed to continue to the end of the block.
18 dnl You should not return or break from the inner loop of the implementation.
19 dnl Care should also be taken to avoid using the names defined in iparm.m4
20 define(START_ARRAY_FUNCTION,
22 extern void name`'rtype_qual`_'atype_code (rtype * const restrict,
23 atype * const restrict, const index_type * const restrict);
24 export_proto(name`'rtype_qual`_'atype_code);
27 name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
28 atype * const restrict array,
29 const index_type * const restrict pdim)
31 index_type count[GFC_MAX_DIMENSIONS];
32 index_type extent[GFC_MAX_DIMENSIONS];
33 index_type sstride[GFC_MAX_DIMENSIONS];
34 index_type dstride[GFC_MAX_DIMENSIONS];
35 const atype_name * restrict base;
36 rtype_name * restrict dest;
44 /* Make dim zero based to avoid confusion. */
45 rank = GFC_DESCRIPTOR_RANK (array) - 1;
48 if (unlikely (dim < 0 || dim > rank))
50 runtime_error ("Dim argument incorrect in u_name intrinsic: "
51 "is %ld, should be between 1 and %ld",
52 (long int) dim + 1, (long int) rank + 1);
55 len = GFC_DESCRIPTOR_EXTENT(array,dim);
58 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
60 for (n = 0; n < dim; n++)
62 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
63 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
68 for (n = dim; n < rank; n++)
70 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
71 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
77 if (retarray->base_addr == NULL)
79 size_t alloc_size, str;
81 for (n = 0; n < rank; n++)
86 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
88 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
93 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
95 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
97 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
100 /* Make sure we have a zero-sized array. */
101 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
108 if (rank != GFC_DESCRIPTOR_RANK (retarray))
109 runtime_error ("rank of return array incorrect in"
110 " u_name intrinsic: is %ld, should be %ld",
111 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
114 if (unlikely (compile_options.bounds_check))
115 bounds_ifunction_return ((array_t *) retarray, extent,
116 "return value", "u_name");
119 for (n = 0; n < rank; n++)
122 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
127 base = array->base_addr;
128 dest = retarray->base_addr;
131 while (continue_loop)
133 const atype_name * restrict src;
138 define(START_ARRAY_BLOCK,
143 for (n = 0; n < len; n++, src += delta)
146 define(FINISH_ARRAY_FUNCTION,
152 /* Advance to the next element. */
157 while (count[n] == extent[n])
159 /* When we get to the end of a dimension, reset it and increment
160 the next dimension. */
162 /* We could precalculate these products, but this is a less
163 frequently used path so probably not worth it. */
164 base -= sstride[n] * extent[n];
165 dest -= dstride[n] * extent[n];
169 /* Break out of the loop. */
182 define(START_MASKED_ARRAY_FUNCTION,
184 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
185 atype * const restrict, const index_type * const restrict,
186 gfc_array_l1 * const restrict);
187 export_proto(`m'name`'rtype_qual`_'atype_code);
190 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
191 atype * const restrict array,
192 const index_type * const restrict pdim,
193 gfc_array_l1 * const restrict mask)
195 index_type count[GFC_MAX_DIMENSIONS];
196 index_type extent[GFC_MAX_DIMENSIONS];
197 index_type sstride[GFC_MAX_DIMENSIONS];
198 index_type dstride[GFC_MAX_DIMENSIONS];
199 index_type mstride[GFC_MAX_DIMENSIONS];
200 rtype_name * restrict dest;
201 const atype_name * restrict base;
202 const GFC_LOGICAL_1 * restrict mbase;
212 rank = GFC_DESCRIPTOR_RANK (array) - 1;
215 if (unlikely (dim < 0 || dim > rank))
217 runtime_error ("Dim argument incorrect in u_name intrinsic: "
218 "is %ld, should be between 1 and %ld",
219 (long int) dim + 1, (long int) rank + 1);
222 len = GFC_DESCRIPTOR_EXTENT(array,dim);
226 mbase = mask->base_addr;
228 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
230 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
231 #ifdef HAVE_GFC_LOGICAL_16
235 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
237 runtime_error ("Funny sized logical array");
239 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
240 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
242 for (n = 0; n < dim; n++)
244 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
245 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
246 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
252 for (n = dim; n < rank; n++)
254 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
255 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
256 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
262 if (retarray->base_addr == NULL)
264 size_t alloc_size, str;
266 for (n = 0; n < rank; n++)
271 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
273 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
277 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
279 retarray->offset = 0;
280 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
284 /* Make sure we have a zero-sized array. */
285 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
289 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
294 if (rank != GFC_DESCRIPTOR_RANK (retarray))
295 runtime_error ("rank of return array incorrect in u_name intrinsic");
297 if (unlikely (compile_options.bounds_check))
299 bounds_ifunction_return ((array_t *) retarray, extent,
300 "return value", "u_name");
301 bounds_equal_extents ((array_t *) mask, (array_t *) array,
302 "MASK argument", "u_name");
306 for (n = 0; n < rank; n++)
309 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
314 dest = retarray->base_addr;
315 base = array->base_addr;
319 const atype_name * restrict src;
320 const GFC_LOGICAL_1 * restrict msrc;
326 define(START_MASKED_ARRAY_BLOCK,
327 ` for (n = 0; n < len; n++, src += delta, msrc += mdelta)
330 define(FINISH_MASKED_ARRAY_FUNCTION,
334 /* Advance to the next element. */
340 while (count[n] == extent[n])
342 /* When we get to the end of a dimension, reset it and increment
343 the next dimension. */
345 /* We could precalculate these products, but this is a less
346 frequently used path so probably not worth it. */
347 base -= sstride[n] * extent[n];
348 mbase -= mstride[n] * extent[n];
349 dest -= dstride[n] * extent[n];
353 /* Break out of the loop. */
367 define(SCALAR_ARRAY_FUNCTION,
369 extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
370 atype * const restrict, const index_type * const restrict,
372 export_proto(`s'name`'rtype_qual`_'atype_code);
375 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
376 atype * const restrict array,
377 const index_type * const restrict pdim,
378 GFC_LOGICAL_4 * mask)
380 index_type count[GFC_MAX_DIMENSIONS];
381 index_type extent[GFC_MAX_DIMENSIONS];
382 index_type dstride[GFC_MAX_DIMENSIONS];
383 rtype_name * restrict dest;
391 name`'rtype_qual`_'atype_code (retarray, array, pdim);
394 /* Make dim zero based to avoid confusion. */
396 rank = GFC_DESCRIPTOR_RANK (array) - 1;
398 if (unlikely (dim < 0 || dim > rank))
400 runtime_error ("Dim argument incorrect in u_name intrinsic: "
401 "is %ld, should be between 1 and %ld",
402 (long int) dim + 1, (long int) rank + 1);
405 for (n = 0; n < dim; n++)
407 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
413 for (n = dim; n < rank; n++)
416 GFC_DESCRIPTOR_EXTENT(array,n + 1);
422 if (retarray->base_addr == NULL)
424 size_t alloc_size, str;
426 for (n = 0; n < rank; n++)
431 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
433 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
437 retarray->offset = 0;
438 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
440 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
444 /* Make sure we have a zero-sized array. */
445 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
449 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
453 if (rank != GFC_DESCRIPTOR_RANK (retarray))
454 runtime_error ("rank of return array incorrect in"
455 " u_name intrinsic: is %ld, should be %ld",
456 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
459 if (unlikely (compile_options.bounds_check))
461 for (n=0; n < rank; n++)
463 index_type ret_extent;
465 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
466 if (extent[n] != ret_extent)
467 runtime_error ("Incorrect extent in return value of"
468 " u_name intrinsic in dimension %ld:"
469 " is %ld, should be %ld", (long int) n + 1,
470 (long int) ret_extent, (long int) extent[n]);
475 for (n = 0; n < rank; n++)
478 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
481 dest = retarray->base_addr;
489 while (count[n] == extent[n])
491 /* When we get to the end of a dimension, reset it and increment
492 the next dimension. */
494 /* We could precalculate these products, but this is a less
495 frequently used path so probably not worth it. */
496 dest -= dstride[n] * extent[n];
508 define(ARRAY_FUNCTION,
509 `START_ARRAY_FUNCTION
511 START_ARRAY_BLOCK($1)
513 FINISH_ARRAY_FUNCTION($4)')dnl
514 define(MASKED_ARRAY_FUNCTION,
515 `START_MASKED_ARRAY_FUNCTION
517 START_MASKED_ARRAY_BLOCK
519 FINISH_MASKED_ARRAY_FUNCTION')dnl