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;
43 /* Make dim zero based to avoid confusion. */
45 rank = GFC_DESCRIPTOR_RANK (array) - 1;
47 /* TODO: It should be a front end job to correctly set the strides. */
49 if (array->dim[0].stride == 0)
50 array->dim[0].stride = 1;
52 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
53 delta = array->dim[dim].stride;
55 for (n = 0; n < dim; n++)
57 sstride[n] = array->dim[n].stride;
58 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
60 for (n = dim; n < rank; n++)
62 sstride[n] = array->dim[n + 1].stride;
64 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
67 if (retarray->data == NULL)
69 for (n = 0; n < rank; n++)
71 retarray->dim[n].lbound = 0;
72 retarray->dim[n].ubound = extent[n]-1;
74 retarray->dim[n].stride = 1;
76 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
80 = internal_malloc_size (sizeof (rtype_name)
81 * retarray->dim[rank-1].stride
84 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
88 if (retarray->dim[0].stride == 0)
89 retarray->dim[0].stride = 1;
91 if (rank != GFC_DESCRIPTOR_RANK (retarray))
92 runtime_error ("rank of return array incorrect");
95 for (n = 0; n < rank; n++)
98 dstride[n] = retarray->dim[n].stride;
104 dest = retarray->data;
108 const atype_name * restrict src;
113 define(START_ARRAY_BLOCK,
118 for (n = 0; n < len; n++, src += delta)
121 define(FINISH_ARRAY_FUNCTION,
126 /* Advance to the next element. */
131 while (count[n] == extent[n])
133 /* When we get to the end of a dimension, reset it and increment
134 the next dimension. */
136 /* We could precalculate these products, but this is a less
137 frequently used path so proabably not worth it. */
138 base -= sstride[n] * extent[n];
139 dest -= dstride[n] * extent[n];
143 /* Break out of the look. */
156 define(START_MASKED_ARRAY_FUNCTION,
158 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
159 atype * const restrict, const index_type * const restrict,
160 gfc_array_l4 * const restrict);
161 export_proto(`m'name`'rtype_qual`_'atype_code);
164 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
165 atype * const restrict array,
166 const index_type * const restrict pdim,
167 gfc_array_l4 * const restrict mask)
169 index_type count[GFC_MAX_DIMENSIONS];
170 index_type extent[GFC_MAX_DIMENSIONS];
171 index_type sstride[GFC_MAX_DIMENSIONS];
172 index_type dstride[GFC_MAX_DIMENSIONS];
173 index_type mstride[GFC_MAX_DIMENSIONS];
174 rtype_name * restrict dest;
175 const atype_name * restrict base;
176 const GFC_LOGICAL_4 * restrict mbase;
185 rank = GFC_DESCRIPTOR_RANK (array) - 1;
187 /* TODO: It should be a front end job to correctly set the strides. */
189 if (array->dim[0].stride == 0)
190 array->dim[0].stride = 1;
192 if (mask->dim[0].stride == 0)
193 mask->dim[0].stride = 1;
195 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
198 delta = array->dim[dim].stride;
199 mdelta = mask->dim[dim].stride;
201 for (n = 0; n < dim; n++)
203 sstride[n] = array->dim[n].stride;
204 mstride[n] = mask->dim[n].stride;
205 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
207 for (n = dim; n < rank; n++)
209 sstride[n] = array->dim[n + 1].stride;
210 mstride[n] = mask->dim[n + 1].stride;
212 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
215 if (retarray->data == NULL)
217 for (n = 0; n < rank; n++)
219 retarray->dim[n].lbound = 0;
220 retarray->dim[n].ubound = extent[n]-1;
222 retarray->dim[n].stride = 1;
224 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
228 = internal_malloc_size (sizeof (rtype_name)
229 * retarray->dim[rank-1].stride
231 retarray->offset = 0;
232 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
236 if (retarray->dim[0].stride == 0)
237 retarray->dim[0].stride = 1;
239 if (rank != GFC_DESCRIPTOR_RANK (retarray))
240 runtime_error ("rank of return array incorrect");
243 for (n = 0; n < rank; n++)
246 dstride[n] = retarray->dim[n].stride;
251 dest = retarray->data;
255 if (GFC_DESCRIPTOR_SIZE (mask) != 4)
257 /* This allows the same loop to be used for all logical types. */
258 assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
259 for (n = 0; n < rank; n++)
262 mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
267 const atype_name * restrict src;
268 const GFC_LOGICAL_4 * restrict msrc;
274 define(START_MASKED_ARRAY_BLOCK,
279 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
282 define(FINISH_MASKED_ARRAY_FUNCTION,
287 /* Advance to the next element. */
293 while (count[n] == extent[n])
295 /* When we get to the end of a dimension, reset it and increment
296 the next dimension. */
298 /* We could precalculate these products, but this is a less
299 frequently used path so proabably not worth it. */
300 base -= sstride[n] * extent[n];
301 mbase -= mstride[n] * extent[n];
302 dest -= dstride[n] * extent[n];
306 /* Break out of the look. */
320 define(SCALAR_ARRAY_FUNCTION,
322 extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
323 atype * const restrict, const index_type * const restrict,
325 export_proto(`s'name`'rtype_qual`_'atype_code);
328 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
329 atype * const restrict array,
330 const index_type * const restrict pdim,
331 GFC_LOGICAL_4 * mask)
340 name`'rtype_qual`_'atype_code (retarray, array, pdim);
343 rank = GFC_DESCRIPTOR_RANK (array);
345 runtime_error ("Rank of array needs to be > 0");
347 if (retarray->data == NULL)
349 retarray->dim[0].lbound = 0;
350 retarray->dim[0].ubound = rank-1;
351 retarray->dim[0].stride = 1;
352 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
353 retarray->offset = 0;
354 retarray->data = internal_malloc_size (sizeof (rtype_name) * rank);
358 if (GFC_DESCRIPTOR_RANK (retarray) != 1)
359 runtime_error ("rank of return array does not equal 1");
361 if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
362 runtime_error ("dimension of return array incorrect");
364 if (retarray->dim[0].stride == 0)
365 retarray->dim[0].stride = 1;
368 dstride = retarray->dim[0].stride;
369 dest = retarray->data;
371 for (n = 0; n < rank; n++)
372 dest[n * dstride] = $1 ;
374 define(ARRAY_FUNCTION,
375 `START_ARRAY_FUNCTION
377 START_ARRAY_BLOCK($1)
379 FINISH_ARRAY_FUNCTION')dnl
380 define(MASKED_ARRAY_FUNCTION,
381 `START_MASKED_ARRAY_FUNCTION
383 START_MASKED_ARRAY_BLOCK($1)
385 FINISH_MASKED_ARRAY_FUNCTION')dnl