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 LGPL. 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 `__'name`'rtype_qual`_'atype_code (rtype * retarray, atype *array, index_type *pdim)
24 index_type count[GFC_MAX_DIMENSIONS - 1];
25 index_type extent[GFC_MAX_DIMENSIONS - 1];
26 index_type sstride[GFC_MAX_DIMENSIONS - 1];
27 index_type dstride[GFC_MAX_DIMENSIONS - 1];
36 /* Make dim zero based to avoid confusion. */
38 rank = GFC_DESCRIPTOR_RANK (array) - 1;
39 assert (rank == GFC_DESCRIPTOR_RANK (retarray));
40 if (array->dim[0].stride == 0)
41 array->dim[0].stride = 1;
42 if (retarray->dim[0].stride == 0)
43 retarray->dim[0].stride = 1;
45 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
46 delta = array->dim[dim].stride;
48 for (n = 0; n < dim; n++)
50 sstride[n] = array->dim[n].stride;
51 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
53 for (n = dim; n < rank; n++)
55 sstride[n] = array->dim[n + 1].stride;
57 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
60 if (retarray->data == NULL)
62 for (n = 0; n < rank; n++)
64 retarray->dim[n].lbound = 0;
65 retarray->dim[n].ubound = extent[n]-1;
67 retarray->dim[n].stride = 1;
69 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
73 = internal_malloc_size (sizeof (rtype_name)
74 * retarray->dim[rank-1].stride
79 for (n = 0; n < rank; n++)
82 dstride[n] = retarray->dim[n].stride;
88 dest = retarray->data;
97 define(START_ARRAY_BLOCK,
102 for (n = 0; n < len; n++, src += delta)
105 define(FINISH_ARRAY_FUNCTION,
110 /* Advance to the next element. */
115 while (count[n] == extent[n])
117 /* When we get to the end of a dimension, reset it and increment
118 the next dimension. */
120 /* We could precalculate these products, but this is a less
121 frequently used path so proabably not worth it. */
122 base -= sstride[n] * extent[n];
123 dest -= dstride[n] * extent[n];
127 /* Break out of the look. */
140 define(START_MASKED_ARRAY_FUNCTION,
142 `__m'name`'rtype_qual`_'atype_code (rtype * retarray, atype * array, index_type *pdim, gfc_array_l4 * mask)
144 index_type count[GFC_MAX_DIMENSIONS - 1];
145 index_type extent[GFC_MAX_DIMENSIONS - 1];
146 index_type sstride[GFC_MAX_DIMENSIONS - 1];
147 index_type dstride[GFC_MAX_DIMENSIONS - 1];
148 index_type mstride[GFC_MAX_DIMENSIONS - 1];
151 GFC_LOGICAL_4 *mbase;
160 rank = GFC_DESCRIPTOR_RANK (array) - 1;
161 assert (rank == GFC_DESCRIPTOR_RANK (retarray));
162 if (array->dim[0].stride == 0)
163 array->dim[0].stride = 1;
164 if (retarray->dim[0].stride == 0)
165 retarray->dim[0].stride = 1;
167 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
170 delta = array->dim[dim].stride;
171 mdelta = mask->dim[dim].stride;
173 for (n = 0; n < dim; n++)
175 sstride[n] = array->dim[n].stride;
176 mstride[n] = mask->dim[n].stride;
177 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
179 for (n = dim; n < rank; n++)
181 sstride[n] = array->dim[n + 1].stride;
182 mstride[n] = mask->dim[n + 1].stride;
184 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
187 for (n = 0; n < rank; n++)
190 dstride[n] = retarray->dim[n].stride;
195 dest = retarray->data;
199 if (GFC_DESCRIPTOR_SIZE (mask) != 4)
201 /* This allows the same loop to be used for all logical types. */
202 assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
203 for (n = 0; n < rank; n++)
206 mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
218 define(START_MASKED_ARRAY_BLOCK,
223 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
226 define(FINISH_MASKED_ARRAY_FUNCTION,
231 /* Advance to the next element. */
237 while (count[n] == extent[n])
239 /* When we get to the end of a dimension, reset it and increment
240 the next dimension. */
242 /* We could precalculate these products, but this is a less
243 frequently used path so proabably not worth it. */
244 base -= sstride[n] * extent[n];
245 mbase -= mstride[n] * extent[n];
246 dest -= dstride[n] * extent[n];
250 /* Break out of the look. */
264 define(ARRAY_FUNCTION,
265 `START_ARRAY_FUNCTION
267 START_ARRAY_BLOCK($1)
269 FINISH_ARRAY_FUNCTION')dnl
270 define(MASKED_ARRAY_FUNCTION,
271 `START_MASKED_ARRAY_FUNCTION
273 START_MASKED_ARRAY_BLOCK($1)
275 FINISH_MASKED_ARRAY_FUNCTION')dnl