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 'atype` * const restrict, const index_type * const restrict 'back_arg`,
36 export_proto('name`'rtype_qual`_'atype_code`);
39 'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray,
40 'atype` * const restrict array,
41 const index_type * const restrict pdim'back_arg`,
42 gfc_charlen_type string_len)
44 index_type count[GFC_MAX_DIMENSIONS];
45 index_type extent[GFC_MAX_DIMENSIONS];
46 index_type sstride[GFC_MAX_DIMENSIONS];
47 index_type dstride[GFC_MAX_DIMENSIONS];
48 const 'atype_name * restrict base;
49 rtype_name * restrict dest;
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);
71 delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
73 for (n = 0; n < dim; n++)
75 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
76 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
81 for (n = dim; n < rank; n++)
83 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
84 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
90 if (retarray->base_addr == NULL)
92 size_t alloc_size, str;
94 for (n = 0; n < rank; n++)
99 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
101 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
105 retarray->offset = 0;
106 retarray->dtype.rank = rank;
108 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
110 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
113 /* Make sure we have a zero-sized array. */
114 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
121 if (rank != GFC_DESCRIPTOR_RANK (retarray))
122 runtime_error ("rank of return array incorrect in"
123 " u_name intrinsic: is %ld, should be %ld",
124 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
127 if (unlikely (compile_options.bounds_check))
128 bounds_ifunction_return ((array_t *) retarray, extent,
129 "return value", "u_name");
132 for (n = 0; n < rank; n++)
135 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
140 base = array->base_addr;
141 dest = retarray->base_addr;
144 while (continue_loop)
146 const atype_name * restrict src;
151 define(START_ARRAY_BLOCK,
156 for (n = 0; n < len; n++, src += delta)
159 define(FINISH_ARRAY_FUNCTION,
165 /* Advance to the next element. */
170 while (count[n] == extent[n])
172 /* When we get to the end of a dimension, reset it and increment
173 the next dimension. */
175 /* We could precalculate these products, but this is a less
176 frequently used path so probably not worth it. */
177 base -= sstride[n] * extent[n];
178 dest -= dstride[n] * extent[n];
182 /* Break out of the loop. */
195 define(START_MASKED_ARRAY_FUNCTION,
197 extern void `m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict,
198 'atype` * const restrict, const index_type * const restrict,
199 gfc_array_l1 * const restrict'back_arg`, gfc_charlen_type);
200 export_proto(m'name`'rtype_qual`_'atype_code`);
203 m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray,
204 'atype` * const restrict array,
205 const index_type * const restrict pdim,
206 gfc_array_l1 * const restrict mask'back_arg`,
207 gfc_charlen_type string_len)
209 index_type count[GFC_MAX_DIMENSIONS];
210 index_type extent[GFC_MAX_DIMENSIONS];
211 index_type sstride[GFC_MAX_DIMENSIONS];
212 index_type dstride[GFC_MAX_DIMENSIONS];
213 index_type mstride[GFC_MAX_DIMENSIONS];
214 'rtype_name * restrict dest;
215 const atype_name * restrict base;
216 const GFC_LOGICAL_1 * restrict mbase;
228 name`'rtype_qual`_'atype_code (retarray, array, pdim, back, string_len);
230 name`'rtype_qual`_'atype_code (retarray, array, pdim, string_len);
236 rank = GFC_DESCRIPTOR_RANK (array) - 1;
239 if (unlikely (dim < 0 || dim > rank))
241 runtime_error ("Dim argument incorrect in u_name intrinsic: "
242 "is %ld, should be between 1 and %ld",
243 (long int) dim + 1, (long int) rank + 1);
246 len = GFC_DESCRIPTOR_EXTENT(array,dim);
250 mbase = mask->base_addr;
252 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
254 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
255 #ifdef HAVE_GFC_LOGICAL_16
259 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
261 runtime_error ("Funny sized logical array");
263 delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
264 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
266 for (n = 0; n < dim; n++)
268 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
269 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
270 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
276 for (n = dim; n < rank; n++)
278 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
279 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
280 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
286 if (retarray->base_addr == NULL)
288 size_t alloc_size, str;
290 for (n = 0; n < rank; n++)
295 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
297 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
301 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
303 retarray->offset = 0;
304 retarray->dtype.rank = rank;
308 /* Make sure we have a zero-sized array. */
309 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
313 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
318 if (rank != GFC_DESCRIPTOR_RANK (retarray))
319 runtime_error ("rank of return array incorrect in u_name intrinsic");
321 if (unlikely (compile_options.bounds_check))
323 bounds_ifunction_return ((array_t *) retarray, extent,
324 "return value", "u_name");
325 bounds_equal_extents ((array_t *) mask, (array_t *) array,
326 "MASK argument", "u_name");
330 for (n = 0; n < rank; n++)
333 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
338 dest = retarray->base_addr;
339 base = array->base_addr;
343 const atype_name * restrict src;
344 const GFC_LOGICAL_1 * restrict msrc;
350 define(START_MASKED_ARRAY_BLOCK,
351 ` for (n = 0; n < len; n++, src += delta, msrc += mdelta)
354 define(FINISH_MASKED_ARRAY_FUNCTION,
358 /* Advance to the next element. */
364 while (count[n] == extent[n])
366 /* When we get to the end of a dimension, reset it and increment
367 the next dimension. */
369 /* We could precalculate these products, but this is a less
370 frequently used path so probably not worth it. */
371 base -= sstride[n] * extent[n];
372 mbase -= mstride[n] * extent[n];
373 dest -= dstride[n] * extent[n];
377 /* Break out of the loop. */
391 define(SCALAR_ARRAY_FUNCTION,
393 extern void `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict,
394 'atype` * const restrict, const index_type * const restrict,
395 GFC_LOGICAL_4 *'back_arg`, gfc_charlen_type);
396 export_proto(s'name`'rtype_qual`_'atype_code`);
399 s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray,
400 'atype` * const restrict array,
401 const index_type * const restrict pdim,
402 GFC_LOGICAL_4 * mask 'back_arg`, gfc_charlen_type string_len)
404 index_type count[GFC_MAX_DIMENSIONS];
405 index_type extent[GFC_MAX_DIMENSIONS];
406 index_type dstride[GFC_MAX_DIMENSIONS];
407 'rtype_name * restrict dest;
413 if (mask == NULL || *mask)
416 name`'rtype_qual`_'atype_code (retarray, array, pdim, back, string_len);
418 name`'rtype_qual`_'atype_code (retarray, array, pdim, string_len);
422 /* Make dim zero based to avoid confusion. */
424 rank = GFC_DESCRIPTOR_RANK (array) - 1;
426 if (unlikely (dim < 0 || dim > rank))
428 runtime_error ("Dim argument incorrect in u_name intrinsic: "
429 "is %ld, should be between 1 and %ld",
430 (long int) dim + 1, (long int) rank + 1);
433 for (n = 0; n < dim; n++)
435 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
441 for (n = dim; n < rank; n++)
444 GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
450 if (retarray->base_addr == NULL)
452 size_t alloc_size, str;
454 for (n = 0; n < rank; n++)
459 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
461 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
465 retarray->offset = 0;
466 retarray->dtype.rank = rank;
468 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
472 /* Make sure we have a zero-sized array. */
473 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
477 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
481 if (rank != GFC_DESCRIPTOR_RANK (retarray))
482 runtime_error ("rank of return array incorrect in"
483 " u_name intrinsic: is %ld, should be %ld",
484 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
487 if (unlikely (compile_options.bounds_check))
489 for (n=0; n < rank; n++)
491 index_type ret_extent;
493 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
494 if (extent[n] != ret_extent)
495 runtime_error ("Incorrect extent in return value of"
496 " u_name intrinsic in dimension %ld:"
497 " is %ld, should be %ld", (long int) n + 1,
498 (long int) ret_extent, (long int) extent[n]);
503 for (n = 0; n < rank; n++)
506 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
509 dest = retarray->base_addr;
517 while (count[n] == extent[n])
519 /* When we get to the end of a dimension, reset it and increment
520 the next dimension. */
522 /* We could precalculate these products, but this is a less
523 frequently used path so probably not worth it. */
524 dest -= dstride[n] * extent[n];
536 define(ARRAY_FUNCTION,
537 `START_ARRAY_FUNCTION
539 START_ARRAY_BLOCK($1)
541 FINISH_ARRAY_FUNCTION($4)')dnl
542 define(MASKED_ARRAY_FUNCTION,
543 `START_MASKED_ARRAY_FUNCTION
545 START_MASKED_ARRAY_BLOCK
547 FINISH_MASKED_ARRAY_FUNCTION')dnl