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 - 1];
29 index_type extent[GFC_MAX_DIMENSIONS - 1];
30 index_type sstride[GFC_MAX_DIMENSIONS - 1];
31 index_type dstride[GFC_MAX_DIMENSIONS - 1];
40 /* Make dim zero based to avoid confusion. */
42 rank = GFC_DESCRIPTOR_RANK (array) - 1;
43 assert (rank == GFC_DESCRIPTOR_RANK (retarray));
44 if (array->dim[0].stride == 0)
45 array->dim[0].stride = 1;
46 if (retarray->dim[0].stride == 0)
47 retarray->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
83 for (n = 0; n < rank; n++)
86 dstride[n] = retarray->dim[n].stride;
92 dest = retarray->data;
101 define(START_ARRAY_BLOCK,
106 for (n = 0; n < len; n++, src += delta)
109 define(FINISH_ARRAY_FUNCTION,
114 /* Advance to the next element. */
119 while (count[n] == extent[n])
121 /* When we get to the end of a dimension, reset it and increment
122 the next dimension. */
124 /* We could precalculate these products, but this is a less
125 frequently used path so proabably not worth it. */
126 base -= sstride[n] * extent[n];
127 dest -= dstride[n] * extent[n];
131 /* Break out of the look. */
144 define(START_MASKED_ARRAY_FUNCTION,
146 extern void `m'name`'rtype_qual`_'atype_code (rtype *, atype *, index_type *,
148 export_proto(`m'name`'rtype_qual`_'atype_code);
151 `m'name`'rtype_qual`_'atype_code (rtype * retarray, atype * array,
152 index_type *pdim, gfc_array_l4 * mask)
154 index_type count[GFC_MAX_DIMENSIONS - 1];
155 index_type extent[GFC_MAX_DIMENSIONS - 1];
156 index_type sstride[GFC_MAX_DIMENSIONS - 1];
157 index_type dstride[GFC_MAX_DIMENSIONS - 1];
158 index_type mstride[GFC_MAX_DIMENSIONS - 1];
161 GFC_LOGICAL_4 *mbase;
170 rank = GFC_DESCRIPTOR_RANK (array) - 1;
171 assert (rank == GFC_DESCRIPTOR_RANK (retarray));
172 if (array->dim[0].stride == 0)
173 array->dim[0].stride = 1;
174 if (retarray->dim[0].stride == 0)
175 retarray->dim[0].stride = 1;
177 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
180 delta = array->dim[dim].stride;
181 mdelta = mask->dim[dim].stride;
183 for (n = 0; n < dim; n++)
185 sstride[n] = array->dim[n].stride;
186 mstride[n] = mask->dim[n].stride;
187 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
189 for (n = dim; n < rank; n++)
191 sstride[n] = array->dim[n + 1].stride;
192 mstride[n] = mask->dim[n + 1].stride;
194 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
197 for (n = 0; n < rank; n++)
200 dstride[n] = retarray->dim[n].stride;
205 dest = retarray->data;
209 if (GFC_DESCRIPTOR_SIZE (mask) != 4)
211 /* This allows the same loop to be used for all logical types. */
212 assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
213 for (n = 0; n < rank; n++)
216 mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
228 define(START_MASKED_ARRAY_BLOCK,
233 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
236 define(FINISH_MASKED_ARRAY_FUNCTION,
241 /* Advance to the next element. */
247 while (count[n] == extent[n])
249 /* When we get to the end of a dimension, reset it and increment
250 the next dimension. */
252 /* We could precalculate these products, but this is a less
253 frequently used path so proabably not worth it. */
254 base -= sstride[n] * extent[n];
255 mbase -= mstride[n] * extent[n];
256 dest -= dstride[n] * extent[n];
260 /* Break out of the look. */
274 define(ARRAY_FUNCTION,
275 `START_ARRAY_FUNCTION
277 START_ARRAY_BLOCK($1)
279 FINISH_ARRAY_FUNCTION')dnl
280 define(MASKED_ARRAY_FUNCTION,
281 `START_MASKED_ARRAY_FUNCTION
283 START_MASKED_ARRAY_BLOCK($1)
285 FINISH_MASKED_ARRAY_FUNCTION')dnl