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 = sizeof (rtype_name) * GFC_DESCRIPTOR_STRIDE(retarray,rank-1)
91 retarray->base_addr = xmalloc (alloc_size);
94 /* Make sure we have a zero-sized array. */
95 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
102 if (rank != GFC_DESCRIPTOR_RANK (retarray))
103 runtime_error ("rank of return array incorrect in"
104 " u_name intrinsic: is %ld, should be %ld",
105 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
108 if (unlikely (compile_options.bounds_check))
109 bounds_ifunction_return ((array_t *) retarray, extent,
110 "return value", "u_name");
113 for (n = 0; n < rank; n++)
116 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
121 base = array->base_addr;
122 dest = retarray->base_addr;
125 while (continue_loop)
127 const atype_name * restrict src;
132 define(START_ARRAY_BLOCK,
137 for (n = 0; n < len; n++, src += delta)
140 define(FINISH_ARRAY_FUNCTION,
146 /* Advance to the next element. */
151 while (count[n] == extent[n])
153 /* When we get to the end of a dimension, reset it and increment
154 the next dimension. */
156 /* We could precalculate these products, but this is a less
157 frequently used path so probably not worth it. */
158 base -= sstride[n] * extent[n];
159 dest -= dstride[n] * extent[n];
163 /* Break out of the look. */
176 define(START_MASKED_ARRAY_FUNCTION,
178 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
179 atype * const restrict, const index_type * const restrict,
180 gfc_array_l1 * const restrict);
181 export_proto(`m'name`'rtype_qual`_'atype_code);
184 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
185 atype * const restrict array,
186 const index_type * const restrict pdim,
187 gfc_array_l1 * const restrict mask)
189 index_type count[GFC_MAX_DIMENSIONS];
190 index_type extent[GFC_MAX_DIMENSIONS];
191 index_type sstride[GFC_MAX_DIMENSIONS];
192 index_type dstride[GFC_MAX_DIMENSIONS];
193 index_type mstride[GFC_MAX_DIMENSIONS];
194 rtype_name * restrict dest;
195 const atype_name * restrict base;
196 const GFC_LOGICAL_1 * restrict mbase;
206 rank = GFC_DESCRIPTOR_RANK (array) - 1;
208 len = GFC_DESCRIPTOR_EXTENT(array,dim);
212 mbase = mask->base_addr;
214 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
216 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
217 #ifdef HAVE_GFC_LOGICAL_16
221 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
223 runtime_error ("Funny sized logical array");
225 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
226 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
228 for (n = 0; n < dim; n++)
230 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
231 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
232 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
238 for (n = dim; n < rank; n++)
240 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
241 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
242 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
248 if (retarray->base_addr == NULL)
250 size_t alloc_size, str;
252 for (n = 0; n < rank; n++)
257 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
259 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
263 alloc_size = sizeof (rtype_name) * GFC_DESCRIPTOR_STRIDE(retarray,rank-1)
266 retarray->offset = 0;
267 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
271 /* Make sure we have a zero-sized array. */
272 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
276 retarray->base_addr = xmalloc (alloc_size);
281 if (rank != GFC_DESCRIPTOR_RANK (retarray))
282 runtime_error ("rank of return array incorrect in u_name intrinsic");
284 if (unlikely (compile_options.bounds_check))
286 bounds_ifunction_return ((array_t *) retarray, extent,
287 "return value", "u_name");
288 bounds_equal_extents ((array_t *) mask, (array_t *) array,
289 "MASK argument", "u_name");
293 for (n = 0; n < rank; n++)
296 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
301 dest = retarray->base_addr;
302 base = array->base_addr;
306 const atype_name * restrict src;
307 const GFC_LOGICAL_1 * restrict msrc;
313 define(START_MASKED_ARRAY_BLOCK,
314 ` for (n = 0; n < len; n++, src += delta, msrc += mdelta)
317 define(FINISH_MASKED_ARRAY_FUNCTION,
321 /* Advance to the next element. */
327 while (count[n] == extent[n])
329 /* When we get to the end of a dimension, reset it and increment
330 the next dimension. */
332 /* We could precalculate these products, but this is a less
333 frequently used path so probably not worth it. */
334 base -= sstride[n] * extent[n];
335 mbase -= mstride[n] * extent[n];
336 dest -= dstride[n] * extent[n];
340 /* Break out of the look. */
354 define(SCALAR_ARRAY_FUNCTION,
356 extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
357 atype * const restrict, const index_type * const restrict,
359 export_proto(`s'name`'rtype_qual`_'atype_code);
362 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
363 atype * const restrict array,
364 const index_type * const restrict pdim,
365 GFC_LOGICAL_4 * mask)
367 index_type count[GFC_MAX_DIMENSIONS];
368 index_type extent[GFC_MAX_DIMENSIONS];
369 index_type dstride[GFC_MAX_DIMENSIONS];
370 rtype_name * restrict dest;
378 name`'rtype_qual`_'atype_code (retarray, array, pdim);
381 /* Make dim zero based to avoid confusion. */
383 rank = GFC_DESCRIPTOR_RANK (array) - 1;
385 for (n = 0; n < dim; n++)
387 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
393 for (n = dim; n < rank; n++)
396 GFC_DESCRIPTOR_EXTENT(array,n + 1);
402 if (retarray->base_addr == NULL)
404 size_t alloc_size, str;
406 for (n = 0; n < rank; n++)
411 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
413 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
417 retarray->offset = 0;
418 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
420 alloc_size = sizeof (rtype_name) * GFC_DESCRIPTOR_STRIDE(retarray,rank-1)
425 /* Make sure we have a zero-sized array. */
426 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
430 retarray->base_addr = xmalloc (alloc_size);
434 if (rank != GFC_DESCRIPTOR_RANK (retarray))
435 runtime_error ("rank of return array incorrect in"
436 " u_name intrinsic: is %ld, should be %ld",
437 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
440 if (unlikely (compile_options.bounds_check))
442 for (n=0; n < rank; n++)
444 index_type ret_extent;
446 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
447 if (extent[n] != ret_extent)
448 runtime_error ("Incorrect extent in return value of"
449 " u_name intrinsic in dimension %ld:"
450 " is %ld, should be %ld", (long int) n + 1,
451 (long int) ret_extent, (long int) extent[n]);
456 for (n = 0; n < rank; n++)
459 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
462 dest = retarray->base_addr;
470 while (count[n] == extent[n])
472 /* When we get to the end of a dimension, reset it and increment
473 the next dimension. */
475 /* We could precalculate these products, but this is a less
476 frequently used path so probably not worth it. */
477 dest -= dstride[n] * extent[n];
489 define(ARRAY_FUNCTION,
490 `START_ARRAY_FUNCTION
492 START_ARRAY_BLOCK($1)
494 FINISH_ARRAY_FUNCTION($4)')dnl
495 define(MASKED_ARRAY_FUNCTION,
496 `START_MASKED_ARRAY_FUNCTION
498 START_MASKED_ARRAY_BLOCK
500 FINISH_MASKED_ARRAY_FUNCTION')dnl