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,
22 extern void name`'rtype_qual`_'atype_code (rtype * const restrict,
23 atype * const restrict, const index_type * const restrict);
24 export_proto(name`'rtype_qual`_'atype_code);
27 name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
28 atype * const restrict array,
29 const index_type * const restrict pdim)
31 index_type count[GFC_MAX_DIMENSIONS];
32 index_type extent[GFC_MAX_DIMENSIONS];
33 index_type sstride[GFC_MAX_DIMENSIONS];
34 index_type dstride[GFC_MAX_DIMENSIONS];
35 const atype_name * restrict base;
36 rtype_name * restrict dest;
44 /* Make dim zero based to avoid confusion. */
46 rank = GFC_DESCRIPTOR_RANK (array) - 1;
48 len = GFC_DESCRIPTOR_EXTENT(array,dim);
51 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
53 for (n = 0; n < dim; n++)
55 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
56 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
61 for (n = dim; n < rank; n++)
63 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
64 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
70 if (retarray->base_addr == NULL)
72 size_t alloc_size, str;
74 for (n = 0; n < rank; n++)
79 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
81 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
86 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
88 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
90 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
93 /* Make sure we have a zero-sized array. */
94 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
101 if (rank != GFC_DESCRIPTOR_RANK (retarray))
102 runtime_error ("rank of return array incorrect in"
103 " u_name intrinsic: is %ld, should be %ld",
104 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
107 if (unlikely (compile_options.bounds_check))
108 bounds_ifunction_return ((array_t *) retarray, extent,
109 "return value", "u_name");
112 for (n = 0; n < rank; n++)
115 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
120 base = array->base_addr;
121 dest = retarray->base_addr;
124 while (continue_loop)
126 const atype_name * restrict src;
131 define(START_ARRAY_BLOCK,
136 for (n = 0; n < len; n++, src += delta)
139 define(FINISH_ARRAY_FUNCTION,
145 /* Advance to the next element. */
150 while (count[n] == extent[n])
152 /* When we get to the end of a dimension, reset it and increment
153 the next dimension. */
155 /* We could precalculate these products, but this is a less
156 frequently used path so probably not worth it. */
157 base -= sstride[n] * extent[n];
158 dest -= dstride[n] * extent[n];
162 /* Break out of the loop. */
175 define(START_MASKED_ARRAY_FUNCTION,
177 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
178 atype * const restrict, const index_type * const restrict,
179 gfc_array_l1 * const restrict);
180 export_proto(`m'name`'rtype_qual`_'atype_code);
183 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
184 atype * const restrict array,
185 const index_type * const restrict pdim,
186 gfc_array_l1 * const restrict mask)
188 index_type count[GFC_MAX_DIMENSIONS];
189 index_type extent[GFC_MAX_DIMENSIONS];
190 index_type sstride[GFC_MAX_DIMENSIONS];
191 index_type dstride[GFC_MAX_DIMENSIONS];
192 index_type mstride[GFC_MAX_DIMENSIONS];
193 rtype_name * restrict dest;
194 const atype_name * restrict base;
195 const GFC_LOGICAL_1 * restrict mbase;
205 rank = GFC_DESCRIPTOR_RANK (array) - 1;
207 len = GFC_DESCRIPTOR_EXTENT(array,dim);
211 mbase = mask->base_addr;
213 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
215 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
216 #ifdef HAVE_GFC_LOGICAL_16
220 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
222 runtime_error ("Funny sized logical array");
224 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
225 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
227 for (n = 0; n < dim; n++)
229 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
230 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
231 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
237 for (n = dim; n < rank; n++)
239 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
240 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
241 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
247 if (retarray->base_addr == NULL)
249 size_t alloc_size, str;
251 for (n = 0; n < rank; n++)
256 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
258 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
262 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
264 retarray->offset = 0;
265 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
269 /* Make sure we have a zero-sized array. */
270 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
274 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
279 if (rank != GFC_DESCRIPTOR_RANK (retarray))
280 runtime_error ("rank of return array incorrect in u_name intrinsic");
282 if (unlikely (compile_options.bounds_check))
284 bounds_ifunction_return ((array_t *) retarray, extent,
285 "return value", "u_name");
286 bounds_equal_extents ((array_t *) mask, (array_t *) array,
287 "MASK argument", "u_name");
291 for (n = 0; n < rank; n++)
294 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
299 dest = retarray->base_addr;
300 base = array->base_addr;
304 const atype_name * restrict src;
305 const GFC_LOGICAL_1 * restrict msrc;
311 define(START_MASKED_ARRAY_BLOCK,
312 ` for (n = 0; n < len; n++, src += delta, msrc += mdelta)
315 define(FINISH_MASKED_ARRAY_FUNCTION,
319 /* Advance to the next element. */
325 while (count[n] == extent[n])
327 /* When we get to the end of a dimension, reset it and increment
328 the next dimension. */
330 /* We could precalculate these products, but this is a less
331 frequently used path so probably not worth it. */
332 base -= sstride[n] * extent[n];
333 mbase -= mstride[n] * extent[n];
334 dest -= dstride[n] * extent[n];
338 /* Break out of the loop. */
352 define(SCALAR_ARRAY_FUNCTION,
354 extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
355 atype * const restrict, const index_type * const restrict,
357 export_proto(`s'name`'rtype_qual`_'atype_code);
360 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
361 atype * const restrict array,
362 const index_type * const restrict pdim,
363 GFC_LOGICAL_4 * mask)
365 index_type count[GFC_MAX_DIMENSIONS];
366 index_type extent[GFC_MAX_DIMENSIONS];
367 index_type dstride[GFC_MAX_DIMENSIONS];
368 rtype_name * restrict dest;
376 name`'rtype_qual`_'atype_code (retarray, array, pdim);
379 /* Make dim zero based to avoid confusion. */
381 rank = GFC_DESCRIPTOR_RANK (array) - 1;
383 for (n = 0; n < dim; n++)
385 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
391 for (n = dim; n < rank; n++)
394 GFC_DESCRIPTOR_EXTENT(array,n + 1);
400 if (retarray->base_addr == NULL)
402 size_t alloc_size, str;
404 for (n = 0; n < rank; n++)
409 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
411 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
415 retarray->offset = 0;
416 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
418 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
422 /* Make sure we have a zero-sized array. */
423 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
427 retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
431 if (rank != GFC_DESCRIPTOR_RANK (retarray))
432 runtime_error ("rank of return array incorrect in"
433 " u_name intrinsic: is %ld, should be %ld",
434 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
437 if (unlikely (compile_options.bounds_check))
439 for (n=0; n < rank; n++)
441 index_type ret_extent;
443 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
444 if (extent[n] != ret_extent)
445 runtime_error ("Incorrect extent in return value of"
446 " u_name intrinsic in dimension %ld:"
447 " is %ld, should be %ld", (long int) n + 1,
448 (long int) ret_extent, (long int) extent[n]);
453 for (n = 0; n < rank; n++)
456 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
459 dest = retarray->base_addr;
467 while (count[n] == extent[n])
469 /* When we get to the end of a dimension, reset it and increment
470 the next dimension. */
472 /* We could precalculate these products, but this is a less
473 frequently used path so probably not worth it. */
474 dest -= dstride[n] * extent[n];
486 define(ARRAY_FUNCTION,
487 `START_ARRAY_FUNCTION
489 START_ARRAY_BLOCK($1)
491 FINISH_ARRAY_FUNCTION($4)')dnl
492 define(MASKED_ARRAY_FUNCTION,
493 `START_MASKED_ARRAY_FUNCTION
495 START_MASKED_ARRAY_BLOCK
497 FINISH_MASKED_ARRAY_FUNCTION')dnl