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'back_arg`);
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'back_arg`)
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.rank = 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 #if ! defined HAVE_BACK_ARG
144 for (n = 0; n < len; n++, src += delta)
148 define(FINISH_ARRAY_FUNCTION,
154 /* Advance to the next element. */
159 while (count[n] == extent[n])
161 /* When we get to the end of a dimension, reset it and increment
162 the next dimension. */
164 /* We could precalculate these products, but this is a less
165 frequently used path so probably not worth it. */
166 base -= sstride[n] * extent[n];
167 dest -= dstride[n] * extent[n];
171 /* Break out of the loop. */
184 define(START_MASKED_ARRAY_FUNCTION,
186 extern void `m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict,
187 'atype` * const restrict, const 'index_type` * const restrict,
188 gfc_array_l1 * const restrict'back_arg`);
189 export_proto(m'name`'rtype_qual`_'atype_code`);
192 m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray,
193 'atype` * const restrict array,
194 const index_type * const restrict pdim,
195 gfc_array_l1 * const restrict mask'back_arg`)
197 index_type count[GFC_MAX_DIMENSIONS];
198 index_type extent[GFC_MAX_DIMENSIONS];
199 index_type sstride[GFC_MAX_DIMENSIONS];
200 index_type dstride[GFC_MAX_DIMENSIONS];
201 index_type mstride[GFC_MAX_DIMENSIONS];
202 'rtype_name * restrict dest;
203 const atype_name * restrict base;
204 const GFC_LOGICAL_1 * restrict mbase;
214 rank = GFC_DESCRIPTOR_RANK (array) - 1;
217 if (unlikely (dim < 0 || dim > rank))
219 runtime_error ("Dim argument incorrect in u_name intrinsic: "
220 "is %ld, should be between 1 and %ld",
221 (long int) dim + 1, (long int) rank + 1);
224 len = GFC_DESCRIPTOR_EXTENT(array,dim);
228 mbase = mask->base_addr;
230 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
232 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
233 #ifdef HAVE_GFC_LOGICAL_16
237 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
239 runtime_error ("Funny sized logical array");
241 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
242 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
244 for (n = 0; n < dim; n++)
246 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
247 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
248 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
254 for (n = dim; n < rank; n++)
256 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
257 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
258 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
264 if (retarray->base_addr == NULL)
266 size_t alloc_size, str;
268 for (n = 0; n < rank; n++)
273 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
275 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
279 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
281 retarray->offset = 0;
282 retarray->dtype.rank = rank;
286 /* Make sure we have a zero-sized array. */
287 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
291 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
296 if (rank != GFC_DESCRIPTOR_RANK (retarray))
297 runtime_error ("rank of return array incorrect in u_name intrinsic");
299 if (unlikely (compile_options.bounds_check))
301 bounds_ifunction_return ((array_t *) retarray, extent,
302 "return value", "u_name");
303 bounds_equal_extents ((array_t *) mask, (array_t *) array,
304 "MASK argument", "u_name");
308 for (n = 0; n < rank; n++)
311 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
316 dest = retarray->base_addr;
317 base = array->base_addr;
321 const atype_name * restrict src;
322 const GFC_LOGICAL_1 * restrict msrc;
328 define(START_MASKED_ARRAY_BLOCK,
329 ` for (n = 0; n < len; n++, src += delta, msrc += mdelta)
332 define(FINISH_MASKED_ARRAY_FUNCTION,
336 /* Advance to the next element. */
342 while (count[n] == extent[n])
344 /* When we get to the end of a dimension, reset it and increment
345 the next dimension. */
347 /* We could precalculate these products, but this is a less
348 frequently used path so probably not worth it. */
349 base -= sstride[n] * extent[n];
350 mbase -= mstride[n] * extent[n];
351 dest -= dstride[n] * extent[n];
355 /* Break out of the loop. */
369 define(SCALAR_ARRAY_FUNCTION,
371 extern void `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict,
372 'atype` * const restrict, const index_type * const restrict,
373 GFC_LOGICAL_4 *'back_arg`);
374 export_proto(s'name`'rtype_qual`_'atype_code);
377 `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray,
378 'atype` * const restrict array,
379 const index_type * const restrict pdim,
380 GFC_LOGICAL_4 * mask'back_arg`)
382 index_type count[GFC_MAX_DIMENSIONS];
383 index_type extent[GFC_MAX_DIMENSIONS];
384 index_type dstride[GFC_MAX_DIMENSIONS];
385 'rtype_name * restrict dest;
394 name`'rtype_qual`_'atype_code (retarray, array, pdim, back);
396 name`'rtype_qual`_'atype_code (retarray, array, pdim);
400 /* Make dim zero based to avoid confusion. */
402 rank = GFC_DESCRIPTOR_RANK (array) - 1;
404 if (unlikely (dim < 0 || dim > rank))
406 runtime_error ("Dim argument incorrect in u_name intrinsic: "
407 "is %ld, should be between 1 and %ld",
408 (long int) dim + 1, (long int) rank + 1);
411 for (n = 0; n < dim; n++)
413 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
419 for (n = dim; n < rank; n++)
422 GFC_DESCRIPTOR_EXTENT(array,n + 1);
428 if (retarray->base_addr == NULL)
430 size_t alloc_size, str;
432 for (n = 0; n < rank; n++)
437 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
439 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
443 retarray->offset = 0;
444 retarray->dtype.rank = rank;
446 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
450 /* Make sure we have a zero-sized array. */
451 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
455 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
459 if (rank != GFC_DESCRIPTOR_RANK (retarray))
460 runtime_error ("rank of return array incorrect in"
461 " u_name intrinsic: is %ld, should be %ld",
462 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
465 if (unlikely (compile_options.bounds_check))
467 for (n=0; n < rank; n++)
469 index_type ret_extent;
471 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
472 if (extent[n] != ret_extent)
473 runtime_error ("Incorrect extent in return value of"
474 " u_name intrinsic in dimension %ld:"
475 " is %ld, should be %ld", (long int) n + 1,
476 (long int) ret_extent, (long int) extent[n]);
481 for (n = 0; n < rank; n++)
484 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
487 dest = retarray->base_addr;
495 while (count[n] == extent[n])
497 /* When we get to the end of a dimension, reset it and increment
498 the next dimension. */
500 /* We could precalculate these products, but this is a less
501 frequently used path so probably not worth it. */
502 dest -= dstride[n] * extent[n];
514 define(ARRAY_FUNCTION,
515 `START_ARRAY_FUNCTION
517 START_ARRAY_BLOCK($1)
519 FINISH_ARRAY_FUNCTION($4)')dnl
520 define(MASKED_ARRAY_FUNCTION,
521 `START_MASKED_ARRAY_FUNCTION
523 START_MASKED_ARRAY_BLOCK
525 FINISH_MASKED_ARRAY_FUNCTION')dnl