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 95 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->data == 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)
93 /* Make sure we have a zero-sized array. */
94 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
99 retarray->data = internal_malloc_size (alloc_size);
103 if (rank != GFC_DESCRIPTOR_RANK (retarray))
104 runtime_error ("rank of return array incorrect in"
105 " u_name intrinsic: is %ld, should be %ld",
106 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
109 if (unlikely (compile_options.bounds_check))
110 bounds_ifunction_return ((array_t *) retarray, extent,
111 "return value", "u_name");
114 for (n = 0; n < rank; n++)
117 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
123 dest = retarray->data;
126 while (continue_loop)
128 const atype_name * restrict src;
133 define(START_ARRAY_BLOCK,
138 for (n = 0; n < len; n++, src += delta)
141 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);
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->data == 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->data = internal_malloc_size (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->data;
306 const atype_name * restrict src;
307 const GFC_LOGICAL_1 * restrict msrc;
313 define(START_MASKED_ARRAY_BLOCK,
318 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
321 define(FINISH_MASKED_ARRAY_FUNCTION,
326 /* Advance to the next element. */
332 while (count[n] == extent[n])
334 /* When we get to the end of a dimension, reset it and increment
335 the next dimension. */
337 /* We could precalculate these products, but this is a less
338 frequently used path so probably not worth it. */
339 base -= sstride[n] * extent[n];
340 mbase -= mstride[n] * extent[n];
341 dest -= dstride[n] * extent[n];
345 /* Break out of the look. */
359 define(SCALAR_ARRAY_FUNCTION,
361 extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
362 atype * const restrict, const index_type * const restrict,
364 export_proto(`s'name`'rtype_qual`_'atype_code);
367 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
368 atype * const restrict array,
369 const index_type * const restrict pdim,
370 GFC_LOGICAL_4 * mask)
372 index_type count[GFC_MAX_DIMENSIONS];
373 index_type extent[GFC_MAX_DIMENSIONS];
374 index_type dstride[GFC_MAX_DIMENSIONS];
375 rtype_name * restrict dest;
383 name`'rtype_qual`_'atype_code (retarray, array, pdim);
386 /* Make dim zero based to avoid confusion. */
388 rank = GFC_DESCRIPTOR_RANK (array) - 1;
390 for (n = 0; n < dim; n++)
392 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
398 for (n = dim; n < rank; n++)
401 GFC_DESCRIPTOR_EXTENT(array,n + 1);
407 if (retarray->data == NULL)
409 size_t alloc_size, str;
411 for (n = 0; n < rank; n++)
416 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
418 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
422 retarray->offset = 0;
423 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
425 alloc_size = sizeof (rtype_name) * GFC_DESCRIPTOR_STRIDE(retarray,rank-1)
430 /* Make sure we have a zero-sized array. */
431 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
435 retarray->data = internal_malloc_size (alloc_size);
439 if (rank != GFC_DESCRIPTOR_RANK (retarray))
440 runtime_error ("rank of return array incorrect in"
441 " u_name intrinsic: is %ld, should be %ld",
442 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
445 if (unlikely (compile_options.bounds_check))
447 for (n=0; n < rank; n++)
449 index_type ret_extent;
451 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
452 if (extent[n] != ret_extent)
453 runtime_error ("Incorrect extent in return value of"
454 " u_name intrinsic in dimension %ld:"
455 " is %ld, should be %ld", (long int) n + 1,
456 (long int) ret_extent, (long int) extent[n]);
461 for (n = 0; n < rank; n++)
464 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
467 dest = retarray->data;
475 while (count[n] == extent[n])
477 /* When we get to the end of a dimension, reset it and increment
478 the next dimension. */
480 /* We could precalculate these products, but this is a less
481 frequently used path so probably not worth it. */
482 dest -= dstride[n] * extent[n];
494 define(ARRAY_FUNCTION,
495 `START_ARRAY_FUNCTION
497 START_ARRAY_BLOCK($1)
499 FINISH_ARRAY_FUNCTION')dnl
500 define(MASKED_ARRAY_FUNCTION,
501 `START_MASKED_ARRAY_FUNCTION
503 START_MASKED_ARRAY_BLOCK($1)
505 FINISH_MASKED_ARRAY_FUNCTION')dnl