2018-07-13 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgfortran / m4 / iforeach-s.m4
blob19bb23bd4ee640e2ec58e1ff3af338a376c9533a
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 Runtime Library (libgfortran)
4 dnl Distributed under the GNU GPL with exception.  See COPYING for details.
5 define(START_FOREACH_FUNCTION,
6 `static inline int
7 compare_fcn (const atype_name *a, const atype_name *b, gfc_charlen_type n)
9   if (sizeof ('atype_name`) == 1)
10     return memcmp (a, b, n);
11   else
12     return memcmp_char4 (a, b, n);
16 extern void name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
17         'atype` * const restrict array'back_arg`, gfc_charlen_type len);
18 export_proto('name`'rtype_qual`_'atype_code);
20 void
21 name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
22         'atype` * const restrict array'back_arg`, gfc_charlen_type len)
24   index_type count[GFC_MAX_DIMENSIONS];
25   index_type extent[GFC_MAX_DIMENSIONS];
26   index_type sstride[GFC_MAX_DIMENSIONS];
27   index_type dstride;
28   const 'atype_name *base;
29   rtype_name * restrict dest;
30   index_type rank;
31   index_type n;
33   rank = GFC_DESCRIPTOR_RANK (array);
34   if (rank <= 0)
35     runtime_error ("Rank of array needs to be > 0");
37   if (retarray->base_addr == NULL)
38     {
39       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
40       retarray->dtype.rank = 1;
41       retarray->offset = 0;
42       retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
43     }
44   else
45     {
46       if (unlikely (compile_options.bounds_check))
47         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
48                                 "u_name");
49     }
51   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
52   dest = retarray->base_addr;
53   for (n = 0; n < rank; n++)
54     {
55       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
56       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
57       count[n] = 0;
58       if (extent[n] <= 0)
59         {
60           /* Set the return value.  */
61           for (n = 0; n < rank; n++)
62             dest[n * dstride] = 0;
63           return;
64         }
65     }
67   base = array->base_addr;
69   /* Initialize the return value.  */
70   for (n = 0; n < rank; n++)
71     dest[n * dstride] = 1;
72   {
73 ')dnl
74 define(START_FOREACH_BLOCK,
75 `  while (base)
76     {
77       do
78         {
79           /* Implementation start.  */
80 ')dnl
81 define(FINISH_FOREACH_FUNCTION,
82 `         /* Implementation end.  */
83           /* Advance to the next element.  */
84           base += sstride[0];
85         }
86       while (++count[0] != extent[0]);
87       n = 0;
88       do
89         {
90           /* When we get to the end of a dimension, reset it and increment
91              the next dimension.  */
92           count[n] = 0;
93           /* We could precalculate these products, but this is a less
94              frequently used path so probably not worth it.  */
95           base -= sstride[n] * extent[n];
96           n++;
97           if (n >= rank)
98             {
99               /* Break out of the loop.  */
100               base = NULL;
101               break;
102             }
103           else
104             {
105               count[n]++;
106               base += sstride[n];
107             }
108         }
109       while (count[n] == extent[n]);
110     }
111   }
112 }')dnl
113 define(START_MASKED_FOREACH_FUNCTION,
115 extern void `m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict, 
116         'atype` * const restrict, gfc_array_l1 * const restrict 'back_arg`,
117         gfc_charlen_type len);
118 export_proto(m'name`'rtype_qual`_'atype_code`);
120 void
121 m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
122         'atype` * const restrict array,
123         gfc_array_l1 * const restrict mask'back_arg`,
124         gfc_charlen_type len)
126   index_type count[GFC_MAX_DIMENSIONS];
127   index_type extent[GFC_MAX_DIMENSIONS];
128   index_type sstride[GFC_MAX_DIMENSIONS];
129   index_type mstride[GFC_MAX_DIMENSIONS];
130   index_type dstride;
131   'rtype_name *dest;
132   const atype_name *base;
133   GFC_LOGICAL_1 *mbase;
134   int rank;
135   index_type n;
136   int mask_kind;
138   rank = GFC_DESCRIPTOR_RANK (array);
139   if (rank <= 0)
140     runtime_error ("Rank of array needs to be > 0");
142   if (retarray->base_addr == NULL)
143     {
144       GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
145       retarray->dtype.rank = 1;
146       retarray->offset = 0;
147       retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
148     }
149   else
150     {
151       if (unlikely (compile_options.bounds_check))
152         {
154           bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
155                                   "u_name");
156           bounds_equal_extents ((array_t *) mask, (array_t *) array,
157                                   "MASK argument", "u_name");
158         }
159     }
161   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
163   mbase = mask->base_addr;
165   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
166 #ifdef HAVE_GFC_LOGICAL_16
167       || mask_kind == 16
168 #endif
169       )
170     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
171   else
172     runtime_error ("Funny sized logical array");
174   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
175   dest = retarray->base_addr;
176   for (n = 0; n < rank; n++)
177     {
178       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
179       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
180       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
181       count[n] = 0;
182       if (extent[n] <= 0)
183         {
184           /* Set the return value.  */
185           for (n = 0; n < rank; n++)
186             dest[n * dstride] = 0;
187           return;
188         }
189     }
191   base = array->base_addr;
193   /* Initialize the return value.  */
194   for (n = 0; n < rank; n++)
195     dest[n * dstride] = 0;
196   {
197 ')dnl
198 define(START_MASKED_FOREACH_BLOCK, `START_FOREACH_BLOCK')dnl
199 define(FINISH_MASKED_FOREACH_FUNCTION,
200 `         /* Implementation end.  */
201           /* Advance to the next element.  */
202           base += sstride[0];
203           mbase += mstride[0];
204         }
205       while (++count[0] != extent[0]);
206       n = 0;
207       do
208         {
209           /* When we get to the end of a dimension, reset it and increment
210              the next dimension.  */
211           count[n] = 0;
212           /* We could precalculate these products, but this is a less
213              frequently used path so probably not worth it.  */
214           base -= sstride[n] * extent[n];
215           mbase -= mstride[n] * extent[n];
216           n++;
217           if (n >= rank)
218             {
219               /* Break out of the loop.  */
220               base = NULL;
221               break;
222             }
223           else
224             {
225               count[n]++;
226               base += sstride[n];
227               mbase += mstride[n];
228             }
229         }
230       while (count[n] == extent[n]);
231     }
232   }
233 }')dnl
234 define(FOREACH_FUNCTION,
235 `START_FOREACH_FUNCTION
237 START_FOREACH_BLOCK
239 FINISH_FOREACH_FUNCTION')dnl
240 define(MASKED_FOREACH_FUNCTION,
241 `START_MASKED_FOREACH_FUNCTION
243 START_MASKED_FOREACH_BLOCK
245 FINISH_MASKED_FOREACH_FUNCTION')dnl
246 define(SCALAR_FOREACH_FUNCTION,
248 extern void `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict, 
249         'atype` * const restrict, GFC_LOGICAL_4 *'back_arg`,
250         gfc_charlen_type len);
251 export_proto(s'name`'rtype_qual`_'atype_code);
253 void
254 `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 
255         'atype` * const restrict array,
256         GFC_LOGICAL_4 * mask'back_arg`,
257         gfc_charlen_type len)
259   index_type rank;
260   index_type dstride;
261   index_type n;
262   'rtype_name *dest;
264   if (*mask)
265     {
266 #ifdef HAVE_BACK_ARG    
267       name`'rtype_qual`_'atype_code (retarray, array, back, len);
268 #else
269       name`'rtype_qual`_'atype_code (retarray, array, len);
270 #endif
271       return;
272     }
274   rank = GFC_DESCRIPTOR_RANK (array);
276   if (rank <= 0)
277     runtime_error ("Rank of array needs to be > 0");
279   if (retarray->base_addr == NULL)
280     {
281       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
282       retarray->dtype.rank = 1;
283       retarray->offset = 0;
284       retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
285     }
286   else if (unlikely (compile_options.bounds_check))
287     {
288        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
289                                "u_name");
290     }
292   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
293   dest = retarray->base_addr;
294   for (n = 0; n<rank; n++)
295     dest[n * dstride] = $1 ;
296 }')dnl