OSDN Git Service

2006-10-16 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / libgfortran / m4 / iforeach.m4
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.
5 define(START_FOREACH_FUNCTION,
6 `
7 extern void name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
8         atype * const restrict array);
9 export_proto(name`'rtype_qual`_'atype_code);
10
11 void
12 name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
13         atype * const restrict array)
14 {
15   index_type count[GFC_MAX_DIMENSIONS];
16   index_type extent[GFC_MAX_DIMENSIONS];
17   index_type sstride[GFC_MAX_DIMENSIONS];
18   index_type dstride;
19   const atype_name *base;
20   rtype_name *dest;
21   index_type rank;
22   index_type n;
23
24   rank = GFC_DESCRIPTOR_RANK (array);
25   if (rank <= 0)
26     runtime_error ("Rank of array needs to be > 0");
27
28   if (retarray->data == NULL)
29     {
30       retarray->dim[0].lbound = 0;
31       retarray->dim[0].ubound = rank-1;
32       retarray->dim[0].stride = 1;
33       retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
34       retarray->offset = 0;
35       retarray->data = internal_malloc_size (sizeof (rtype_name) * rank);
36     }
37   else
38     {
39       if (GFC_DESCRIPTOR_RANK (retarray) != 1)
40         runtime_error ("rank of return array does not equal 1");
41
42       if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
43         runtime_error ("dimension of return array incorrect");
44     }
45
46   dstride = retarray->dim[0].stride;
47   dest = retarray->data;
48   for (n = 0; n < rank; n++)
49     {
50       sstride[n] = array->dim[n].stride;
51       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
52       count[n] = 0;
53       if (extent[n] <= 0)
54         {
55           /* Set the return value.  */
56           for (n = 0; n < rank; n++)
57             dest[n * dstride] = 0;
58           return;
59         }
60     }
61
62   base = array->data;
63
64   /* Initialize the return value.  */
65   for (n = 0; n < rank; n++)
66     dest[n * dstride] = 0;
67   {
68 ')dnl
69 define(START_FOREACH_BLOCK,
70 `  while (base)
71     {
72       {
73         /* Implementation start.  */
74 ')dnl
75 define(FINISH_FOREACH_FUNCTION,
76 `        /* Implementation end.  */
77       }
78       /* Advance to the next element.  */
79       count[0]++;
80       base += sstride[0];
81       n = 0;
82       while (count[n] == extent[n])
83         {
84           /* When we get to the end of a dimension, reset it and increment
85              the next dimension.  */
86           count[n] = 0;
87           /* We could precalculate these products, but this is a less
88              frequently used path so probably not worth it.  */
89           base -= sstride[n] * extent[n];
90           n++;
91           if (n == rank)
92             {
93               /* Break out of the loop.  */
94               base = NULL;
95               break;
96             }
97           else
98             {
99               count[n]++;
100               base += sstride[n];
101             }
102         }
103     }
104   }
105 }')dnl
106 define(START_MASKED_FOREACH_FUNCTION,
107 `
108 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict, 
109         atype * const restrict, gfc_array_l4 * const restrict);
110 export_proto(`m'name`'rtype_qual`_'atype_code);
111
112 void
113 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
114         atype * const restrict array,
115         gfc_array_l4 * const restrict mask)
116 {
117   index_type count[GFC_MAX_DIMENSIONS];
118   index_type extent[GFC_MAX_DIMENSIONS];
119   index_type sstride[GFC_MAX_DIMENSIONS];
120   index_type mstride[GFC_MAX_DIMENSIONS];
121   index_type dstride;
122   rtype_name *dest;
123   const atype_name *base;
124   GFC_LOGICAL_4 *mbase;
125   int rank;
126   index_type n;
127
128   rank = GFC_DESCRIPTOR_RANK (array);
129   if (rank <= 0)
130     runtime_error ("Rank of array needs to be > 0");
131
132   if (retarray->data == NULL)
133     {
134       retarray->dim[0].lbound = 0;
135       retarray->dim[0].ubound = rank-1;
136       retarray->dim[0].stride = 1;
137       retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
138       retarray->offset = 0;
139       retarray->data = internal_malloc_size (sizeof (rtype_name) * rank);
140     }
141   else
142     {
143       if (GFC_DESCRIPTOR_RANK (retarray) != 1)
144         runtime_error ("rank of return array does not equal 1");
145
146       if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
147         runtime_error ("dimension of return array incorrect");
148     }
149
150   dstride = retarray->dim[0].stride;
151   dest = retarray->data;
152   for (n = 0; n < rank; n++)
153     {
154       sstride[n] = array->dim[n].stride;
155       mstride[n] = mask->dim[n].stride;
156       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
157       count[n] = 0;
158       if (extent[n] <= 0)
159         {
160           /* Set the return value.  */
161           for (n = 0; n < rank; n++)
162             dest[n * dstride] = 0;
163           return;
164         }
165     }
166
167   base = array->data;
168   mbase = mask->data;
169
170   if (GFC_DESCRIPTOR_SIZE (mask) != 4)
171     {
172       /* This allows the same loop to be used for all logical types.  */
173       assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
174       for (n = 0; n < rank; n++)
175         mstride[n] <<= 1;
176       mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
177     }
178
179
180   /* Initialize the return value.  */
181   for (n = 0; n < rank; n++)
182     dest[n * dstride] = 0;
183   {
184 ')dnl
185 define(START_MASKED_FOREACH_BLOCK, `START_FOREACH_BLOCK')dnl
186 define(FINISH_MASKED_FOREACH_FUNCTION,
187 `        /* Implementation end.  */
188       }
189       /* Advance to the next element.  */
190       count[0]++;
191       base += sstride[0];
192       mbase += mstride[0];
193       n = 0;
194       while (count[n] == extent[n])
195         {
196           /* When we get to the end of a dimension, reset it and increment
197              the next dimension.  */
198           count[n] = 0;
199           /* We could precalculate these products, but this is a less
200              frequently used path so probably not worth it.  */
201           base -= sstride[n] * extent[n];
202           mbase -= mstride[n] * extent[n];
203           n++;
204           if (n == rank)
205             {
206               /* Break out of the loop.  */
207               base = NULL;
208               break;
209             }
210           else
211             {
212               count[n]++;
213               base += sstride[n];
214               mbase += mstride[n];
215             }
216         }
217     }
218   }
219 }')dnl
220 define(FOREACH_FUNCTION,
221 `START_FOREACH_FUNCTION
222 $1
223 START_FOREACH_BLOCK
224 $2
225 FINISH_FOREACH_FUNCTION')dnl
226 define(MASKED_FOREACH_FUNCTION,
227 `START_MASKED_FOREACH_FUNCTION
228 $1
229 START_MASKED_FOREACH_BLOCK
230 $2
231 FINISH_MASKED_FOREACH_FUNCTION')dnl
232 define(SCALAR_FOREACH_FUNCTION,
233 `
234 extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict, 
235         atype * const restrict, GFC_LOGICAL_4 *);
236 export_proto(`s'name`'rtype_qual`_'atype_code);
237
238 void
239 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
240         atype * const restrict array,
241         GFC_LOGICAL_4 * mask)
242 {
243   index_type rank;
244   index_type dstride;
245   index_type n;
246   rtype_name *dest;
247
248   if (*mask)
249     {
250       name`'rtype_qual`_'atype_code (retarray, array);
251       return;
252     }
253
254   rank = GFC_DESCRIPTOR_RANK (array);
255
256   if (rank <= 0)
257     runtime_error ("Rank of array needs to be > 0");
258
259   if (retarray->data == NULL)
260     {
261       retarray->dim[0].lbound = 0;
262       retarray->dim[0].ubound = rank-1;
263       retarray->dim[0].stride = 1;
264       retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
265       retarray->offset = 0;
266       retarray->data = internal_malloc_size (sizeof (rtype_name) * rank);
267     }
268   else
269     {
270       if (GFC_DESCRIPTOR_RANK (retarray) != 1)
271         runtime_error ("rank of return array does not equal 1");
272
273       if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
274         runtime_error ("dimension of return array incorrect");
275     }
276
277   dstride = retarray->dim[0].stride;
278   dest = retarray->data;
279   for (n = 0; n<rank; n++)
280     dest[n * dstride] = $1 ;
281 }')dnl