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,
25 compare_fcn (const atype_name *a, const atype_name *b, gfc_charlen_type n)
27 if (sizeof ('atype_name`) == 1)
28 return memcmp (a, b, n);
30 return memcmp_char4 (a, b, n);
33 extern void name`'rtype_qual`_'atype_code (rtype * const restrict,
34 gfc_charlen_type, atype * const restrict,
35 const index_type * const restrict, gfc_charlen_type);
36 export_proto(name`'rtype_qual`_'atype_code);
39 name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
40 gfc_charlen_type xlen, atype * const restrict array,
41 const index_type * const restrict pdim, gfc_charlen_type string_len)
43 index_type count[GFC_MAX_DIMENSIONS];
44 index_type extent[GFC_MAX_DIMENSIONS];
45 index_type sstride[GFC_MAX_DIMENSIONS];
46 index_type dstride[GFC_MAX_DIMENSIONS];
47 const atype_name * restrict base;
48 rtype_name * restrict dest;
56 assert (xlen == string_len);
57 /* Make dim zero based to avoid confusion. */
58 rank = GFC_DESCRIPTOR_RANK (array) - 1;
61 if (unlikely (dim < 0 || dim > rank))
63 runtime_error ("Dim argument incorrect in u_name intrinsic: "
64 "is %ld, should be between 1 and %ld",
65 (long int) dim + 1, (long int) rank + 1);
68 len = GFC_DESCRIPTOR_EXTENT(array,dim);
72 delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
74 for (n = 0; n < dim; n++)
76 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
77 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
82 for (n = dim; n < rank; n++)
84 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
85 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
91 if (retarray->base_addr == NULL)
93 size_t alloc_size, str;
95 for (n = 0; n < rank; n++)
100 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
102 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
106 retarray->offset = 0;
107 GFC_DTYPE_COPY_SETRANK(retarray,array,rank);
109 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
112 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
115 /* Make sure we have a zero-sized array. */
116 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
123 if (rank != GFC_DESCRIPTOR_RANK (retarray))
124 runtime_error ("rank of return array incorrect in"
125 " u_name intrinsic: is %ld, should be %ld",
126 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
129 if (unlikely (compile_options.bounds_check))
130 bounds_ifunction_return ((array_t *) retarray, extent,
131 "return value", "u_name");
134 for (n = 0; n < rank; n++)
137 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
142 base = array->base_addr;
143 dest = retarray->base_addr;
146 while (continue_loop)
148 const atype_name * restrict src;
152 define(START_ARRAY_BLOCK,
154 memset (dest, '$1`, sizeof (*dest) * string_len);
157 for (n = 0; n < len; n++, src += delta)
160 define(FINISH_ARRAY_FUNCTION,
163 memcpy (dest, retval, sizeof (*dest) * string_len);
166 /* Advance to the next element. */
171 while (count[n] == extent[n])
173 /* When we get to the end of a dimension, reset it and increment
174 the next dimension. */
176 /* We could precalculate these products, but this is a less
177 frequently used path so probably not worth it. */
178 base -= sstride[n] * extent[n];
179 dest -= dstride[n] * extent[n];
183 /* Break out of the loop. */
196 define(START_MASKED_ARRAY_FUNCTION,
198 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
199 gfc_charlen_type, atype * const restrict,
200 const index_type * const restrict,
201 gfc_array_l1 * const restrict, gfc_charlen_type);
202 export_proto(`m'name`'rtype_qual`_'atype_code);
205 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
206 gfc_charlen_type xlen, atype * const restrict array,
207 const index_type * const restrict pdim,
208 gfc_array_l1 * const restrict mask,
209 gfc_charlen_type string_len)
212 index_type count[GFC_MAX_DIMENSIONS];
213 index_type extent[GFC_MAX_DIMENSIONS];
214 index_type sstride[GFC_MAX_DIMENSIONS];
215 index_type dstride[GFC_MAX_DIMENSIONS];
216 index_type mstride[GFC_MAX_DIMENSIONS];
217 rtype_name * restrict dest;
218 const atype_name * restrict base;
219 const GFC_LOGICAL_1 * restrict mbase;
228 assert (xlen == string_len);
231 rank = GFC_DESCRIPTOR_RANK (array) - 1;
233 if (unlikely (dim < 0 || dim > rank))
235 runtime_error ("Dim argument incorrect in u_name intrinsic: "
236 "is %ld, should be between 1 and %ld",
237 (long int) dim + 1, (long int) rank + 1);
240 len = GFC_DESCRIPTOR_EXTENT(array,dim);
244 mbase = mask->base_addr;
246 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
248 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
249 #ifdef HAVE_GFC_LOGICAL_16
253 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
255 runtime_error ("Funny sized logical array");
257 delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
258 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
260 for (n = 0; n < dim; n++)
262 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
263 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
264 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
270 for (n = dim; n < rank; n++)
272 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
273 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
274 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
280 if (retarray->base_addr == NULL)
282 size_t alloc_size, str;
284 for (n = 0; n < rank; n++)
289 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
291 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
295 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
298 retarray->offset = 0;
299 GFC_DTYPE_COPY_SETRANK(retarray,array,rank);
303 /* Make sure we have a zero-sized array. */
304 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
308 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
313 if (rank != GFC_DESCRIPTOR_RANK (retarray))
314 runtime_error ("rank of return array incorrect in u_name intrinsic");
316 if (unlikely (compile_options.bounds_check))
318 bounds_ifunction_return ((array_t *) retarray, extent,
319 "return value", "u_name");
320 bounds_equal_extents ((array_t *) mask, (array_t *) array,
321 "MASK argument", "u_name");
325 for (n = 0; n < rank; n++)
328 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
333 dest = retarray->base_addr;
334 base = array->base_addr;
338 const atype_name * restrict src;
339 const GFC_LOGICAL_1 * restrict msrc;
345 define(START_MASKED_ARRAY_BLOCK,
346 ` for (n = 0; n < len; n++, src += delta, msrc += mdelta)
349 define(FINISH_MASKED_ARRAY_FUNCTION,
351 memcpy (dest, retval, sizeof (*dest) * string_len);
353 /* Advance to the next element. */
359 while (count[n] == extent[n])
361 /* When we get to the end of a dimension, reset it and increment
362 the next dimension. */
364 /* We could precalculate these products, but this is a less
365 frequently used path so probably not worth it. */
366 base -= sstride[n] * extent[n];
367 mbase -= mstride[n] * extent[n];
368 dest -= dstride[n] * extent[n];
372 /* Break out of the loop. */
386 define(SCALAR_ARRAY_FUNCTION,
388 void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
389 gfc_charlen_type, atype * const restrict,
390 const index_type * const restrict,
391 GFC_LOGICAL_4 *, gfc_charlen_type);
393 export_proto(`s'name`'rtype_qual`_'atype_code);
396 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
397 gfc_charlen_type xlen, atype * const restrict array,
398 const index_type * const restrict pdim,
399 GFC_LOGICAL_4 *mask, gfc_charlen_type string_len)
402 index_type count[GFC_MAX_DIMENSIONS];
403 index_type extent[GFC_MAX_DIMENSIONS];
404 index_type dstride[GFC_MAX_DIMENSIONS];
405 rtype_name * restrict dest;
413 name`'rtype_qual`_'atype_code (retarray, xlen, array, pdim, string_len);
416 /* Make dim zero based to avoid confusion. */
418 rank = GFC_DESCRIPTOR_RANK (array) - 1;
420 if (unlikely (dim < 0 || dim > rank))
422 runtime_error ("Dim argument incorrect in u_name intrinsic: "
423 "is %ld, should be between 1 and %ld",
424 (long int) dim + 1, (long int) rank + 1);
427 for (n = 0; n < dim; n++)
429 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
435 for (n = dim; n < rank; n++)
438 GFC_DESCRIPTOR_EXTENT(array,n + 1);
444 if (retarray->base_addr == NULL)
446 size_t alloc_size, str;
448 for (n = 0; n < rank; n++)
453 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
455 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
459 retarray->offset = 0;
460 GFC_DTYPE_COPY_SETRANK(retarray,array,rank);
462 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
467 /* Make sure we have a zero-sized array. */
468 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
472 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
476 if (rank != GFC_DESCRIPTOR_RANK (retarray))
477 runtime_error ("rank of return array incorrect in"
478 " u_name intrinsic: is %ld, should be %ld",
479 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
482 if (unlikely (compile_options.bounds_check))
484 for (n=0; n < rank; n++)
486 index_type ret_extent;
488 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
489 if (extent[n] != ret_extent)
490 runtime_error ("Incorrect extent in return value of"
491 " u_name intrinsic in dimension %ld:"
492 " is %ld, should be %ld", (long int) n + 1,
493 (long int) ret_extent, (long int) extent[n]);
498 for (n = 0; n < rank; n++)
501 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
504 dest = retarray->base_addr;
508 memset (dest, '$1`, sizeof (*dest) * string_len);
512 while (count[n] == extent[n])
514 /* When we get to the end of a dimension, reset it and increment
515 the next dimension. */
517 /* We could precalculate these products, but this is a less
518 frequently used path so probably not worth it. */
519 dest -= dstride[n] * extent[n];
531 define(ARRAY_FUNCTION,
532 `START_ARRAY_FUNCTION($1)
534 START_ARRAY_BLOCK($1)
536 FINISH_ARRAY_FUNCTION($4)')dnl
537 define(MASKED_ARRAY_FUNCTION,
538 `START_MASKED_ARRAY_FUNCTION
540 START_MASKED_ARRAY_BLOCK
542 FINISH_MASKED_ARRAY_FUNCTION')dnl