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));
118 if (rank != GFC_DESCRIPTOR_RANK (retarray))
119 runtime_error ("rank of return array incorrect in"
120 " u_name intrinsic: is %ld, should be %ld",
121 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
124 if (unlikely (compile_options.bounds_check))
125 bounds_ifunction_return ((array_t *) retarray, extent,
126 "return value", "u_name");
129 for (n = 0; n < rank; n++)
132 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
137 base = array->base_addr;
138 dest = retarray->base_addr;
141 while (continue_loop)
143 const atype_name * restrict src;
147 define(START_ARRAY_BLOCK,
149 memset (dest, '$1`, sizeof (*dest) * string_len);
152 for (n = 0; n < len; n++, src += delta)
155 define(FINISH_ARRAY_FUNCTION,
158 memcpy (dest, retval, sizeof (*dest) * string_len);
161 /* Advance to the next element. */
166 while (count[n] == extent[n])
168 /* When we get to the end of a dimension, reset it and increment
169 the next dimension. */
171 /* We could precalculate these products, but this is a less
172 frequently used path so probably not worth it. */
173 base -= sstride[n] * extent[n];
174 dest -= dstride[n] * extent[n];
178 /* Break out of the loop. */
191 define(START_MASKED_ARRAY_FUNCTION,
193 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
194 gfc_charlen_type, atype * const restrict,
195 const index_type * const restrict,
196 gfc_array_l1 * const restrict, gfc_charlen_type);
197 export_proto(`m'name`'rtype_qual`_'atype_code);
200 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
201 gfc_charlen_type xlen, atype * const restrict array,
202 const index_type * const restrict pdim,
203 gfc_array_l1 * const restrict mask,
204 gfc_charlen_type string_len)
207 index_type count[GFC_MAX_DIMENSIONS];
208 index_type extent[GFC_MAX_DIMENSIONS];
209 index_type sstride[GFC_MAX_DIMENSIONS];
210 index_type dstride[GFC_MAX_DIMENSIONS];
211 index_type mstride[GFC_MAX_DIMENSIONS];
212 rtype_name * restrict dest;
213 const atype_name * restrict base;
214 const GFC_LOGICAL_1 * restrict mbase;
225 name`'rtype_qual`_'atype_code (retarray, xlen, array, pdim, string_len);
229 assert (xlen == string_len);
232 rank = GFC_DESCRIPTOR_RANK (array) - 1;
234 if (unlikely (dim < 0 || dim > rank))
236 runtime_error ("Dim argument incorrect in u_name intrinsic: "
237 "is %ld, should be between 1 and %ld",
238 (long int) dim + 1, (long int) rank + 1);
241 len = GFC_DESCRIPTOR_EXTENT(array,dim);
245 mbase = mask->base_addr;
247 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
249 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
250 #ifdef HAVE_GFC_LOGICAL_16
254 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
256 runtime_error ("Funny sized logical array");
258 delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
259 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
261 for (n = 0; n < dim; n++)
263 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
264 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
265 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
271 for (n = dim; n < rank; n++)
273 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
274 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
275 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
281 if (retarray->base_addr == NULL)
283 size_t alloc_size, str;
285 for (n = 0; n < rank; n++)
290 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
292 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
296 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
299 retarray->offset = 0;
300 retarray->dtype.rank = rank;
302 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) * string_len;
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,
346 memcpy (dest, retval, sizeof (*dest) * string_len);
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 void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
384 gfc_charlen_type, atype * const restrict,
385 const index_type * const restrict,
386 GFC_LOGICAL_4 *, gfc_charlen_type);
388 export_proto(`s'name`'rtype_qual`_'atype_code);
391 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
392 gfc_charlen_type xlen, atype * const restrict array,
393 const index_type * const restrict pdim,
394 GFC_LOGICAL_4 *mask, gfc_charlen_type string_len)
397 index_type count[GFC_MAX_DIMENSIONS];
398 index_type extent[GFC_MAX_DIMENSIONS];
399 index_type dstride[GFC_MAX_DIMENSIONS];
400 rtype_name * restrict dest;
406 if (mask == NULL || *mask)
408 name`'rtype_qual`_'atype_code (retarray, xlen, array, pdim, string_len);
411 /* Make dim zero based to avoid confusion. */
413 rank = GFC_DESCRIPTOR_RANK (array) - 1;
415 if (unlikely (dim < 0 || dim > rank))
417 runtime_error ("Dim argument incorrect in u_name intrinsic: "
418 "is %ld, should be between 1 and %ld",
419 (long int) dim + 1, (long int) rank + 1);
422 for (n = 0; n < dim; n++)
424 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
430 for (n = dim; n < rank; n++)
433 GFC_DESCRIPTOR_EXTENT(array,n + 1);
439 if (retarray->base_addr == NULL)
441 size_t alloc_size, str;
443 for (n = 0; n < rank; n++)
448 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
450 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
454 retarray->offset = 0;
455 retarray->dtype.rank = rank;
457 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
460 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
466 if (rank != GFC_DESCRIPTOR_RANK (retarray))
467 runtime_error ("rank of return array incorrect in"
468 " u_name intrinsic: is %ld, should be %ld",
469 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
472 if (unlikely (compile_options.bounds_check))
474 for (n=0; n < rank; n++)
476 index_type ret_extent;
478 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
479 if (extent[n] != ret_extent)
480 runtime_error ("Incorrect extent in return value of"
481 " u_name intrinsic in dimension %ld:"
482 " is %ld, should be %ld", (long int) n + 1,
483 (long int) ret_extent, (long int) extent[n]);
488 for (n = 0; n < rank; n++)
491 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
494 dest = retarray->base_addr;
498 memset (dest, '$1`, sizeof (*dest) * string_len);
502 while (count[n] == extent[n])
504 /* When we get to the end of a dimension, reset it and increment
505 the next dimension. */
507 /* We could precalculate these products, but this is a less
508 frequently used path so probably not worth it. */
509 dest -= dstride[n] * extent[n];
521 define(ARRAY_FUNCTION,
522 `START_ARRAY_FUNCTION($1)
524 START_ARRAY_BLOCK($1)
526 FINISH_ARRAY_FUNCTION($4)')dnl
527 define(MASKED_ARRAY_FUNCTION,
528 `START_MASKED_ARRAY_FUNCTION
530 START_MASKED_ARRAY_BLOCK
532 FINISH_MASKED_ARRAY_FUNCTION')dnl