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 retarray->dtype.rank = 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;
230 name`'rtype_qual`_'atype_code (retarray, xlen, array, pdim, string_len);
234 assert (xlen == string_len);
237 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]
304 retarray->offset = 0;
305 retarray->dtype.rank = rank;
309 /* Make sure we have a zero-sized array. */
310 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
314 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
319 if (rank != GFC_DESCRIPTOR_RANK (retarray))
320 runtime_error ("rank of return array incorrect in u_name intrinsic");
322 if (unlikely (compile_options.bounds_check))
324 bounds_ifunction_return ((array_t *) retarray, extent,
325 "return value", "u_name");
326 bounds_equal_extents ((array_t *) mask, (array_t *) array,
327 "MASK argument", "u_name");
331 for (n = 0; n < rank; n++)
334 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
339 dest = retarray->base_addr;
340 base = array->base_addr;
344 const atype_name * restrict src;
345 const GFC_LOGICAL_1 * restrict msrc;
351 define(START_MASKED_ARRAY_BLOCK,
352 ` for (n = 0; n < len; n++, src += delta, msrc += mdelta)
355 define(FINISH_MASKED_ARRAY_FUNCTION,
357 memcpy (dest, retval, sizeof (*dest) * string_len);
359 /* Advance to the next element. */
365 while (count[n] == extent[n])
367 /* When we get to the end of a dimension, reset it and increment
368 the next dimension. */
370 /* We could precalculate these products, but this is a less
371 frequently used path so probably not worth it. */
372 base -= sstride[n] * extent[n];
373 mbase -= mstride[n] * extent[n];
374 dest -= dstride[n] * extent[n];
378 /* Break out of the loop. */
392 define(SCALAR_ARRAY_FUNCTION,
394 void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
395 gfc_charlen_type, atype * const restrict,
396 const index_type * const restrict,
397 GFC_LOGICAL_4 *, gfc_charlen_type);
399 export_proto(`s'name`'rtype_qual`_'atype_code);
402 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
403 gfc_charlen_type xlen, atype * const restrict array,
404 const index_type * const restrict pdim,
405 GFC_LOGICAL_4 *mask, gfc_charlen_type string_len)
408 index_type count[GFC_MAX_DIMENSIONS];
409 index_type extent[GFC_MAX_DIMENSIONS];
410 index_type dstride[GFC_MAX_DIMENSIONS];
411 rtype_name * restrict dest;
417 if (mask == NULL || *mask)
419 name`'rtype_qual`_'atype_code (retarray, xlen, 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);
441 for (n = dim; n < rank; n++)
444 GFC_DESCRIPTOR_EXTENT(array,n + 1);
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]
473 /* Make sure we have a zero-sized array. */
474 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
478 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
482 if (rank != GFC_DESCRIPTOR_RANK (retarray))
483 runtime_error ("rank of return array incorrect in"
484 " u_name intrinsic: is %ld, should be %ld",
485 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
488 if (unlikely (compile_options.bounds_check))
490 for (n=0; n < rank; n++)
492 index_type ret_extent;
494 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
495 if (extent[n] != ret_extent)
496 runtime_error ("Incorrect extent in return value of"
497 " u_name intrinsic in dimension %ld:"
498 " is %ld, should be %ld", (long int) n + 1,
499 (long int) ret_extent, (long int) extent[n]);
504 for (n = 0; n < rank; n++)
507 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
510 dest = retarray->base_addr;
514 memset (dest, '$1`, sizeof (*dest) * string_len);
518 while (count[n] == extent[n])
520 /* When we get to the end of a dimension, reset it and increment
521 the next dimension. */
523 /* We could precalculate these products, but this is a less
524 frequently used path so probably not worth it. */
525 dest -= dstride[n] * extent[n];
537 define(ARRAY_FUNCTION,
538 `START_ARRAY_FUNCTION($1)
540 START_ARRAY_BLOCK($1)
542 FINISH_ARRAY_FUNCTION($4)')dnl
543 define(MASKED_ARRAY_FUNCTION,
544 `START_MASKED_ARRAY_FUNCTION
546 START_MASKED_ARRAY_BLOCK
548 FINISH_MASKED_ARRAY_FUNCTION')dnl