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 *, atype *, index_type *);
23 export_proto(name`'rtype_qual`_'atype_code);
26 name`'rtype_qual`_'atype_code (rtype *retarray, atype *array, index_type *pdim)
28 index_type count[GFC_MAX_DIMENSIONS];
29 index_type extent[GFC_MAX_DIMENSIONS];
30 index_type sstride[GFC_MAX_DIMENSIONS];
31 index_type dstride[GFC_MAX_DIMENSIONS];
40 /* Make dim zero based to avoid confusion. */
42 rank = GFC_DESCRIPTOR_RANK (array) - 1;
44 /* TODO: It should be a front end job to correctly set the strides. */
46 if (array->dim[0].stride == 0)
47 array->dim[0].stride = 1;
49 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
50 delta = array->dim[dim].stride;
52 for (n = 0; n < dim; n++)
54 sstride[n] = array->dim[n].stride;
55 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
57 for (n = dim; n < rank; n++)
59 sstride[n] = array->dim[n + 1].stride;
61 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
64 if (retarray->data == NULL)
66 for (n = 0; n < rank; n++)
68 retarray->dim[n].lbound = 0;
69 retarray->dim[n].ubound = extent[n]-1;
71 retarray->dim[n].stride = 1;
73 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
77 = internal_malloc_size (sizeof (rtype_name)
78 * retarray->dim[rank-1].stride
81 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
85 if (retarray->dim[0].stride == 0)
86 retarray->dim[0].stride = 1;
88 if (rank != GFC_DESCRIPTOR_RANK (retarray))
89 runtime_error ("rank of return array incorrect");
92 for (n = 0; n < rank; n++)
95 dstride[n] = retarray->dim[n].stride;
101 dest = retarray->data;
110 define(START_ARRAY_BLOCK,
115 for (n = 0; n < len; n++, src += delta)
118 define(FINISH_ARRAY_FUNCTION,
123 /* Advance to the next element. */
128 while (count[n] == extent[n])
130 /* When we get to the end of a dimension, reset it and increment
131 the next dimension. */
133 /* We could precalculate these products, but this is a less
134 frequently used path so proabably not worth it. */
135 base -= sstride[n] * extent[n];
136 dest -= dstride[n] * extent[n];
140 /* Break out of the look. */
153 define(START_MASKED_ARRAY_FUNCTION,
155 extern void `m'name`'rtype_qual`_'atype_code (rtype *, atype *, index_type *,
157 export_proto(`m'name`'rtype_qual`_'atype_code);
160 `m'name`'rtype_qual`_'atype_code (rtype * retarray, atype * array,
161 index_type *pdim, gfc_array_l4 * mask)
163 index_type count[GFC_MAX_DIMENSIONS];
164 index_type extent[GFC_MAX_DIMENSIONS];
165 index_type sstride[GFC_MAX_DIMENSIONS];
166 index_type dstride[GFC_MAX_DIMENSIONS];
167 index_type mstride[GFC_MAX_DIMENSIONS];
170 GFC_LOGICAL_4 *mbase;
179 rank = GFC_DESCRIPTOR_RANK (array) - 1;
181 /* TODO: It should be a front end job to correctly set the strides. */
183 if (array->dim[0].stride == 0)
184 array->dim[0].stride = 1;
186 if (mask->dim[0].stride == 0)
187 mask->dim[0].stride = 1;
189 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
192 delta = array->dim[dim].stride;
193 mdelta = mask->dim[dim].stride;
195 for (n = 0; n < dim; n++)
197 sstride[n] = array->dim[n].stride;
198 mstride[n] = mask->dim[n].stride;
199 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
201 for (n = dim; n < rank; n++)
203 sstride[n] = array->dim[n + 1].stride;
204 mstride[n] = mask->dim[n + 1].stride;
206 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
209 if (retarray->data == NULL)
211 for (n = 0; n < rank; n++)
213 retarray->dim[n].lbound = 0;
214 retarray->dim[n].ubound = extent[n]-1;
216 retarray->dim[n].stride = 1;
218 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
222 = internal_malloc_size (sizeof (rtype_name)
223 * retarray->dim[rank-1].stride
225 retarray->offset = 0;
226 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
230 if (retarray->dim[0].stride == 0)
231 retarray->dim[0].stride = 1;
233 if (rank != GFC_DESCRIPTOR_RANK (retarray))
234 runtime_error ("rank of return array incorrect");
237 for (n = 0; n < rank; n++)
240 dstride[n] = retarray->dim[n].stride;
245 dest = retarray->data;
249 if (GFC_DESCRIPTOR_SIZE (mask) != 4)
251 /* This allows the same loop to be used for all logical types. */
252 assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
253 for (n = 0; n < rank; n++)
256 mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
268 define(START_MASKED_ARRAY_BLOCK,
273 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
276 define(FINISH_MASKED_ARRAY_FUNCTION,
281 /* Advance to the next element. */
287 while (count[n] == extent[n])
289 /* When we get to the end of a dimension, reset it and increment
290 the next dimension. */
292 /* We could precalculate these products, but this is a less
293 frequently used path so proabably not worth it. */
294 base -= sstride[n] * extent[n];
295 mbase -= mstride[n] * extent[n];
296 dest -= dstride[n] * extent[n];
300 /* Break out of the look. */
314 define(ARRAY_FUNCTION,
315 `START_ARRAY_FUNCTION
317 START_ARRAY_BLOCK($1)
319 FINISH_ARRAY_FUNCTION')dnl
320 define(MASKED_ARRAY_FUNCTION,
321 `START_MASKED_ARRAY_FUNCTION
323 START_MASKED_ARRAY_BLOCK($1)
325 FINISH_MASKED_ARRAY_FUNCTION')dnl