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 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
48 delta = array->dim[dim].stride;
50 for (n = 0; n < dim; n++)
52 sstride[n] = array->dim[n].stride;
53 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
55 for (n = dim; n < rank; n++)
57 sstride[n] = array->dim[n + 1].stride;
59 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
62 if (retarray->data == NULL)
64 for (n = 0; n < rank; n++)
66 retarray->dim[n].lbound = 0;
67 retarray->dim[n].ubound = extent[n]-1;
69 retarray->dim[n].stride = 1;
71 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
75 = internal_malloc_size (sizeof (rtype_name)
76 * retarray->dim[rank-1].stride
79 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
83 if (rank != GFC_DESCRIPTOR_RANK (retarray))
84 runtime_error ("rank of return array incorrect");
87 for (n = 0; n < rank; n++)
90 dstride[n] = retarray->dim[n].stride;
96 dest = retarray->data;
100 const atype_name * restrict src;
105 define(START_ARRAY_BLOCK,
110 for (n = 0; n < len; n++, src += delta)
113 define(FINISH_ARRAY_FUNCTION,
118 /* Advance to the next element. */
123 while (count[n] == extent[n])
125 /* When we get to the end of a dimension, reset it and increment
126 the next dimension. */
128 /* We could precalculate these products, but this is a less
129 frequently used path so proabably not worth it. */
130 base -= sstride[n] * extent[n];
131 dest -= dstride[n] * extent[n];
135 /* Break out of the look. */
148 define(START_MASKED_ARRAY_FUNCTION,
150 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
151 atype * const restrict, const index_type * const restrict,
152 gfc_array_l4 * const restrict);
153 export_proto(`m'name`'rtype_qual`_'atype_code);
156 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
157 atype * const restrict array,
158 const index_type * const restrict pdim,
159 gfc_array_l4 * const restrict mask)
161 index_type count[GFC_MAX_DIMENSIONS];
162 index_type extent[GFC_MAX_DIMENSIONS];
163 index_type sstride[GFC_MAX_DIMENSIONS];
164 index_type dstride[GFC_MAX_DIMENSIONS];
165 index_type mstride[GFC_MAX_DIMENSIONS];
166 rtype_name * restrict dest;
167 const atype_name * restrict base;
168 const GFC_LOGICAL_4 * restrict mbase;
177 rank = GFC_DESCRIPTOR_RANK (array) - 1;
179 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
182 delta = array->dim[dim].stride;
183 mdelta = mask->dim[dim].stride;
185 for (n = 0; n < dim; n++)
187 sstride[n] = array->dim[n].stride;
188 mstride[n] = mask->dim[n].stride;
189 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
191 for (n = dim; n < rank; n++)
193 sstride[n] = array->dim[n + 1].stride;
194 mstride[n] = mask->dim[n + 1].stride;
196 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
199 if (retarray->data == NULL)
201 for (n = 0; n < rank; n++)
203 retarray->dim[n].lbound = 0;
204 retarray->dim[n].ubound = extent[n]-1;
206 retarray->dim[n].stride = 1;
208 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
212 = internal_malloc_size (sizeof (rtype_name)
213 * retarray->dim[rank-1].stride
215 retarray->offset = 0;
216 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
220 if (rank != GFC_DESCRIPTOR_RANK (retarray))
221 runtime_error ("rank of return array incorrect");
224 for (n = 0; n < rank; n++)
227 dstride[n] = retarray->dim[n].stride;
232 dest = retarray->data;
236 if (GFC_DESCRIPTOR_SIZE (mask) != 4)
238 /* This allows the same loop to be used for all logical types. */
239 assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
240 for (n = 0; n < rank; n++)
243 mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
248 const atype_name * restrict src;
249 const GFC_LOGICAL_4 * restrict msrc;
255 define(START_MASKED_ARRAY_BLOCK,
260 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
263 define(FINISH_MASKED_ARRAY_FUNCTION,
268 /* Advance to the next element. */
274 while (count[n] == extent[n])
276 /* When we get to the end of a dimension, reset it and increment
277 the next dimension. */
279 /* We could precalculate these products, but this is a less
280 frequently used path so proabably not worth it. */
281 base -= sstride[n] * extent[n];
282 mbase -= mstride[n] * extent[n];
283 dest -= dstride[n] * extent[n];
287 /* Break out of the look. */
301 define(SCALAR_ARRAY_FUNCTION,
303 extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
304 atype * const restrict, const index_type * const restrict,
306 export_proto(`s'name`'rtype_qual`_'atype_code);
309 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
310 atype * const restrict array,
311 const index_type * const restrict pdim,
312 GFC_LOGICAL_4 * mask)
321 name`'rtype_qual`_'atype_code (retarray, array, pdim);
324 rank = GFC_DESCRIPTOR_RANK (array);
326 runtime_error ("Rank of array needs to be > 0");
328 if (retarray->data == NULL)
330 retarray->dim[0].lbound = 0;
331 retarray->dim[0].ubound = rank-1;
332 retarray->dim[0].stride = 1;
333 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
334 retarray->offset = 0;
335 retarray->data = internal_malloc_size (sizeof (rtype_name) * rank);
339 if (GFC_DESCRIPTOR_RANK (retarray) != 1)
340 runtime_error ("rank of return array does not equal 1");
342 if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
343 runtime_error ("dimension of return array incorrect");
346 dstride = retarray->dim[0].stride;
347 dest = retarray->data;
349 for (n = 0; n < rank; n++)
350 dest[n * dstride] = $1 ;
352 define(ARRAY_FUNCTION,
353 `START_ARRAY_FUNCTION
355 START_ARRAY_BLOCK($1)
357 FINISH_ARRAY_FUNCTION')dnl
358 define(MASKED_ARRAY_FUNCTION,
359 `START_MASKED_ARRAY_FUNCTION
361 START_MASKED_ARRAY_BLOCK($1)
363 FINISH_MASKED_ARRAY_FUNCTION')dnl