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;
216 name`'rtype_qual`_'atype_code (retarray, array, pdim, back);
218 name`'rtype_qual`_'atype_code (retarray, array, pdim);
224 rank = GFC_DESCRIPTOR_RANK (array) - 1;
227 if (unlikely (dim < 0 || dim > rank))
229 runtime_error ("Dim argument incorrect in u_name intrinsic: "
230 "is %ld, should be between 1 and %ld",
231 (long int) dim + 1, (long int) rank + 1);
234 len = GFC_DESCRIPTOR_EXTENT(array,dim);
238 mbase = mask->base_addr;
240 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
242 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
243 #ifdef HAVE_GFC_LOGICAL_16
247 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
249 runtime_error ("Funny sized logical array");
251 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
252 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
254 for (n = 0; n < dim; n++)
256 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
257 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
258 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
264 for (n = dim; n < rank; n++)
266 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
267 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
268 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
274 if (retarray->base_addr == NULL)
276 size_t alloc_size, str;
278 for (n = 0; n < rank; n++)
283 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
285 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
289 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
291 retarray->offset = 0;
292 retarray->dtype.rank = rank;
296 /* Make sure we have a zero-sized array. */
297 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
301 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
306 if (rank != GFC_DESCRIPTOR_RANK (retarray))
307 runtime_error ("rank of return array incorrect in u_name intrinsic");
309 if (unlikely (compile_options.bounds_check))
311 bounds_ifunction_return ((array_t *) retarray, extent,
312 "return value", "u_name");
313 bounds_equal_extents ((array_t *) mask, (array_t *) array,
314 "MASK argument", "u_name");
318 for (n = 0; n < rank; n++)
321 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
326 dest = retarray->base_addr;
327 base = array->base_addr;
331 const atype_name * restrict src;
332 const GFC_LOGICAL_1 * restrict msrc;
338 define(START_MASKED_ARRAY_BLOCK,
339 ` for (n = 0; n < len; n++, src += delta, msrc += mdelta)
342 define(FINISH_MASKED_ARRAY_FUNCTION,
346 /* Advance to the next element. */
352 while (count[n] == extent[n])
354 /* When we get to the end of a dimension, reset it and increment
355 the next dimension. */
357 /* We could precalculate these products, but this is a less
358 frequently used path so probably not worth it. */
359 base -= sstride[n] * extent[n];
360 mbase -= mstride[n] * extent[n];
361 dest -= dstride[n] * extent[n];
365 /* Break out of the loop. */
379 define(SCALAR_ARRAY_FUNCTION,
381 extern void `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict,
382 'atype` * const restrict, const index_type * const restrict,
383 GFC_LOGICAL_4 *'back_arg`);
384 export_proto(s'name`'rtype_qual`_'atype_code);
387 `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray,
388 'atype` * const restrict array,
389 const index_type * const restrict pdim,
390 GFC_LOGICAL_4 * mask'back_arg`)
392 index_type count[GFC_MAX_DIMENSIONS];
393 index_type extent[GFC_MAX_DIMENSIONS];
394 index_type dstride[GFC_MAX_DIMENSIONS];
395 'rtype_name * restrict dest;
401 if (mask == NULL || *mask)
404 name`'rtype_qual`_'atype_code (retarray, array, pdim, back);
406 name`'rtype_qual`_'atype_code (retarray, array, pdim);
410 /* Make dim zero based to avoid confusion. */
412 rank = GFC_DESCRIPTOR_RANK (array) - 1;
414 if (unlikely (dim < 0 || dim > rank))
416 runtime_error ("Dim argument incorrect in u_name intrinsic: "
417 "is %ld, should be between 1 and %ld",
418 (long int) dim + 1, (long int) rank + 1);
421 for (n = 0; n < dim; n++)
423 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
429 for (n = dim; n < rank; n++)
432 GFC_DESCRIPTOR_EXTENT(array,n + 1);
438 if (retarray->base_addr == NULL)
440 size_t alloc_size, str;
442 for (n = 0; n < rank; n++)
447 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
449 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
453 retarray->offset = 0;
454 retarray->dtype.rank = rank;
456 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
460 /* Make sure we have a zero-sized array. */
461 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
465 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
469 if (rank != GFC_DESCRIPTOR_RANK (retarray))
470 runtime_error ("rank of return array incorrect in"
471 " u_name intrinsic: is %ld, should be %ld",
472 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
475 if (unlikely (compile_options.bounds_check))
477 for (n=0; n < rank; n++)
479 index_type ret_extent;
481 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
482 if (extent[n] != ret_extent)
483 runtime_error ("Incorrect extent in return value of"
484 " u_name intrinsic in dimension %ld:"
485 " is %ld, should be %ld", (long int) n + 1,
486 (long int) ret_extent, (long int) extent[n]);
491 for (n = 0; n < rank; n++)
494 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
497 dest = retarray->base_addr;
505 while (count[n] == extent[n])
507 /* When we get to the end of a dimension, reset it and increment
508 the next dimension. */
510 /* We could precalculate these products, but this is a less
511 frequently used path so probably not worth it. */
512 dest -= dstride[n] * extent[n];
524 define(ARRAY_FUNCTION,
525 `START_ARRAY_FUNCTION
527 START_ARRAY_BLOCK($1)
529 FINISH_ARRAY_FUNCTION($4)')dnl
530 define(MASKED_ARRAY_FUNCTION,
531 `START_MASKED_ARRAY_FUNCTION
533 START_MASKED_ARRAY_BLOCK
535 FINISH_MASKED_ARRAY_FUNCTION')dnl