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 GFC_DTYPE_COPY_SETRANK(retarray,array,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;
226 rank = GFC_DESCRIPTOR_RANK (array) - 1;
229 if (unlikely (dim < 0 || dim > rank))
231 runtime_error ("Dim argument incorrect in u_name intrinsic: "
232 "is %ld, should be between 1 and %ld",
233 (long int) dim + 1, (long int) rank + 1);
236 len = GFC_DESCRIPTOR_EXTENT(array,dim);
240 mbase = mask->base_addr;
242 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
244 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
245 #ifdef HAVE_GFC_LOGICAL_16
249 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
251 runtime_error ("Funny sized logical array");
253 delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
254 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
256 for (n = 0; n < dim; n++)
258 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
259 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
260 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
266 for (n = dim; n < rank; n++)
268 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
269 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
270 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
276 if (retarray->base_addr == NULL)
278 size_t alloc_size, str;
280 for (n = 0; n < rank; n++)
285 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
287 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
291 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
293 retarray->offset = 0;
294 GFC_DTYPE_COPY_SETRANK(retarray,array,rank);
298 /* Make sure we have a zero-sized array. */
299 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
303 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
308 if (rank != GFC_DESCRIPTOR_RANK (retarray))
309 runtime_error ("rank of return array incorrect in u_name intrinsic");
311 if (unlikely (compile_options.bounds_check))
313 bounds_ifunction_return ((array_t *) retarray, extent,
314 "return value", "u_name");
315 bounds_equal_extents ((array_t *) mask, (array_t *) array,
316 "MASK argument", "u_name");
320 for (n = 0; n < rank; n++)
323 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
328 dest = retarray->base_addr;
329 base = array->base_addr;
333 const atype_name * restrict src;
334 const GFC_LOGICAL_1 * restrict msrc;
340 define(START_MASKED_ARRAY_BLOCK,
341 ` for (n = 0; n < len; n++, src += delta, msrc += mdelta)
344 define(FINISH_MASKED_ARRAY_FUNCTION,
348 /* Advance to the next element. */
354 while (count[n] == extent[n])
356 /* When we get to the end of a dimension, reset it and increment
357 the next dimension. */
359 /* We could precalculate these products, but this is a less
360 frequently used path so probably not worth it. */
361 base -= sstride[n] * extent[n];
362 mbase -= mstride[n] * extent[n];
363 dest -= dstride[n] * extent[n];
367 /* Break out of the loop. */
381 define(SCALAR_ARRAY_FUNCTION,
383 extern void `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict,
384 'atype` * const restrict, const index_type * const restrict,
385 GFC_LOGICAL_4 *'back_arg`, gfc_charlen_type);
386 export_proto(s'name`'rtype_qual`_'atype_code`);
389 s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray,
390 'atype` * const restrict array,
391 const index_type * const restrict pdim,
392 GFC_LOGICAL_4 * mask 'back_arg`, gfc_charlen_type string_len)
394 index_type count[GFC_MAX_DIMENSIONS];
395 index_type extent[GFC_MAX_DIMENSIONS];
396 index_type dstride[GFC_MAX_DIMENSIONS];
397 'rtype_name * restrict dest;
406 name`'rtype_qual`_'atype_code (retarray, array, pdim, back, string_len);
408 name`'rtype_qual`_'atype_code (retarray, array, pdim, string_len);
412 /* Make dim zero based to avoid confusion. */
414 rank = GFC_DESCRIPTOR_RANK (array) - 1;
416 if (unlikely (dim < 0 || dim > rank))
418 runtime_error ("Dim argument incorrect in u_name intrinsic: "
419 "is %ld, should be between 1 and %ld",
420 (long int) dim + 1, (long int) rank + 1);
423 for (n = 0; n < dim; n++)
425 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
431 for (n = dim; n < rank; n++)
434 GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
440 if (retarray->base_addr == NULL)
442 size_t alloc_size, str;
444 for (n = 0; n < rank; n++)
449 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
451 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
455 retarray->offset = 0;
456 GFC_DTYPE_COPY_SETRANK(retarray,array,rank);
458 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
462 /* Make sure we have a zero-sized array. */
463 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
467 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
471 if (rank != GFC_DESCRIPTOR_RANK (retarray))
472 runtime_error ("rank of return array incorrect in"
473 " u_name intrinsic: is %ld, should be %ld",
474 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
477 if (unlikely (compile_options.bounds_check))
479 for (n=0; n < rank; n++)
481 index_type ret_extent;
483 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
484 if (extent[n] != ret_extent)
485 runtime_error ("Incorrect extent in return value of"
486 " u_name intrinsic in dimension %ld:"
487 " is %ld, should be %ld", (long int) n + 1,
488 (long int) ret_extent, (long int) extent[n]);
493 for (n = 0; n < rank; n++)
496 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
499 dest = retarray->base_addr;
507 while (count[n] == extent[n])
509 /* When we get to the end of a dimension, reset it and increment
510 the next dimension. */
512 /* We could precalculate these products, but this is a less
513 frequently used path so probably not worth it. */
514 dest -= dstride[n] * extent[n];
526 define(ARRAY_FUNCTION,
527 `START_ARRAY_FUNCTION
529 START_ARRAY_BLOCK($1)
531 FINISH_ARRAY_FUNCTION($4)')dnl
532 define(MASKED_ARRAY_FUNCTION,
533 `START_MASKED_ARRAY_FUNCTION
535 START_MASKED_ARRAY_BLOCK
537 FINISH_MASKED_ARRAY_FUNCTION')dnl