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,
24 compare_fcn (const atype_name *a, const atype_name *b, gfc_charlen_type n)
26 if (sizeof ('atype_name`) == 1)
27 return memcmp (a, b, n);
29 return memcmp_char4 (a, b, n);
32 extern void name`'rtype_qual`_'atype_code (rtype * const restrict,
33 atype * const restrict, const index_type * const restrict,
35 export_proto(name`'rtype_qual`_'atype_code);
38 name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
39 atype * const restrict array,
40 const index_type * const restrict pdim, gfc_charlen_type string_len)
42 index_type count[GFC_MAX_DIMENSIONS];
43 index_type extent[GFC_MAX_DIMENSIONS];
44 index_type sstride[GFC_MAX_DIMENSIONS];
45 index_type dstride[GFC_MAX_DIMENSIONS];
46 const atype_name * restrict base;
47 rtype_name * restrict dest;
55 /* Make dim zero based to avoid confusion. */
56 rank = GFC_DESCRIPTOR_RANK (array) - 1;
59 if (unlikely (dim < 0 || dim > rank))
61 runtime_error ("Dim argument incorrect in u_name intrinsic: "
62 "is %ld, should be between 1 and %ld",
63 (long int) dim + 1, (long int) rank + 1);
66 len = GFC_DESCRIPTOR_EXTENT(array,dim);
69 delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
71 for (n = 0; n < dim; n++)
73 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
74 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
79 for (n = dim; n < rank; n++)
81 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
82 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
88 if (retarray->base_addr == NULL)
90 size_t alloc_size, str;
92 for (n = 0; n < rank; n++)
97 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
99 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
103 retarray->offset = 0;
104 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
106 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
108 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
111 /* Make sure we have a zero-sized array. */
112 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
119 if (rank != GFC_DESCRIPTOR_RANK (retarray))
120 runtime_error ("rank of return array incorrect in"
121 " u_name intrinsic: is %ld, should be %ld",
122 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
125 if (unlikely (compile_options.bounds_check))
126 bounds_ifunction_return ((array_t *) retarray, extent,
127 "return value", "u_name");
130 for (n = 0; n < rank; n++)
133 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
138 base = array->base_addr;
139 dest = retarray->base_addr;
142 while (continue_loop)
144 const atype_name * restrict src;
149 define(START_ARRAY_BLOCK,
154 for (n = 0; n < len; n++, src += delta)
157 define(FINISH_ARRAY_FUNCTION,
163 /* Advance to the next element. */
168 while (count[n] == extent[n])
170 /* When we get to the end of a dimension, reset it and increment
171 the next dimension. */
173 /* We could precalculate these products, but this is a less
174 frequently used path so probably not worth it. */
175 base -= sstride[n] * extent[n];
176 dest -= dstride[n] * extent[n];
180 /* Break out of the loop. */
193 define(START_MASKED_ARRAY_FUNCTION,
195 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
196 atype * const restrict, const index_type * const restrict,
197 gfc_array_l1 * const restrict, gfc_charlen_type);
198 export_proto(`m'name`'rtype_qual`_'atype_code);
201 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
202 atype * const restrict array,
203 const index_type * const restrict pdim,
204 gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
206 index_type count[GFC_MAX_DIMENSIONS];
207 index_type extent[GFC_MAX_DIMENSIONS];
208 index_type sstride[GFC_MAX_DIMENSIONS];
209 index_type dstride[GFC_MAX_DIMENSIONS];
210 index_type mstride[GFC_MAX_DIMENSIONS];
211 rtype_name * restrict dest;
212 const atype_name * restrict base;
213 const GFC_LOGICAL_1 * restrict mbase;
223 rank = GFC_DESCRIPTOR_RANK (array) - 1;
226 if (unlikely (dim < 0 || dim > rank))
228 runtime_error ("Dim argument incorrect in u_name intrinsic: "
229 "is %ld, should be between 1 and %ld",
230 (long int) dim + 1, (long int) rank + 1);
233 len = GFC_DESCRIPTOR_EXTENT(array,dim);
237 mbase = mask->base_addr;
239 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
241 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
242 #ifdef HAVE_GFC_LOGICAL_16
246 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
248 runtime_error ("Funny sized logical array");
250 delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
251 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
253 for (n = 0; n < dim; n++)
255 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
256 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
257 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
263 for (n = dim; n < rank; n++)
265 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
266 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
267 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
273 if (retarray->base_addr == NULL)
275 size_t alloc_size, str;
277 for (n = 0; n < rank; n++)
282 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
284 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
288 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
290 retarray->offset = 0;
291 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
295 /* Make sure we have a zero-sized array. */
296 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
300 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
305 if (rank != GFC_DESCRIPTOR_RANK (retarray))
306 runtime_error ("rank of return array incorrect in u_name intrinsic");
308 if (unlikely (compile_options.bounds_check))
310 bounds_ifunction_return ((array_t *) retarray, extent,
311 "return value", "u_name");
312 bounds_equal_extents ((array_t *) mask, (array_t *) array,
313 "MASK argument", "u_name");
317 for (n = 0; n < rank; n++)
320 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
325 dest = retarray->base_addr;
326 base = array->base_addr;
330 const atype_name * restrict src;
331 const GFC_LOGICAL_1 * restrict msrc;
337 define(START_MASKED_ARRAY_BLOCK,
338 ` for (n = 0; n < len; n++, src += delta, msrc += mdelta)
341 define(FINISH_MASKED_ARRAY_FUNCTION,
345 /* Advance to the next element. */
351 while (count[n] == extent[n])
353 /* When we get to the end of a dimension, reset it and increment
354 the next dimension. */
356 /* We could precalculate these products, but this is a less
357 frequently used path so probably not worth it. */
358 base -= sstride[n] * extent[n];
359 mbase -= mstride[n] * extent[n];
360 dest -= dstride[n] * extent[n];
364 /* Break out of the loop. */
378 define(SCALAR_ARRAY_FUNCTION,
380 extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
381 atype * const restrict, const index_type * const restrict,
382 GFC_LOGICAL_4 *, gfc_charlen_type);
383 export_proto(`s'name`'rtype_qual`_'atype_code);
386 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
387 atype * const restrict array,
388 const index_type * const restrict pdim,
389 GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
391 index_type count[GFC_MAX_DIMENSIONS];
392 index_type extent[GFC_MAX_DIMENSIONS];
393 index_type dstride[GFC_MAX_DIMENSIONS];
394 rtype_name * restrict dest;
402 name`'rtype_qual`_'atype_code (retarray, array, pdim, string_len);
405 /* Make dim zero based to avoid confusion. */
407 rank = GFC_DESCRIPTOR_RANK (array) - 1;
409 if (unlikely (dim < 0 || dim > rank))
411 runtime_error ("Dim argument incorrect in u_name intrinsic: "
412 "is %ld, should be between 1 and %ld",
413 (long int) dim + 1, (long int) rank + 1);
416 for (n = 0; n < dim; n++)
418 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
424 for (n = dim; n < rank; n++)
427 GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
433 if (retarray->base_addr == NULL)
435 size_t alloc_size, str;
437 for (n = 0; n < rank; n++)
442 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
444 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
448 retarray->offset = 0;
449 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
451 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
455 /* Make sure we have a zero-sized array. */
456 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
460 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
464 if (rank != GFC_DESCRIPTOR_RANK (retarray))
465 runtime_error ("rank of return array incorrect in"
466 " u_name intrinsic: is %ld, should be %ld",
467 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
470 if (unlikely (compile_options.bounds_check))
472 for (n=0; n < rank; n++)
474 index_type ret_extent;
476 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
477 if (extent[n] != ret_extent)
478 runtime_error ("Incorrect extent in return value of"
479 " u_name intrinsic in dimension %ld:"
480 " is %ld, should be %ld", (long int) n + 1,
481 (long int) ret_extent, (long int) extent[n]);
486 for (n = 0; n < rank; n++)
489 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
492 dest = retarray->base_addr;
500 while (count[n] == extent[n])
502 /* When we get to the end of a dimension, reset it and increment
503 the next dimension. */
505 /* We could precalculate these products, but this is a less
506 frequently used path so probably not worth it. */
507 dest -= dstride[n] * extent[n];
519 define(ARRAY_FUNCTION,
520 `START_ARRAY_FUNCTION
522 START_ARRAY_BLOCK($1)
524 FINISH_ARRAY_FUNCTION($4)')dnl
525 define(MASKED_ARRAY_FUNCTION,
526 `START_MASKED_ARRAY_FUNCTION
528 START_MASKED_ARRAY_BLOCK
530 FINISH_MASKED_ARRAY_FUNCTION')dnl