OSDN Git Service

6a68db0524355e7a174057c371ea4d63bfd07754
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / sum_r8.c
1 /* Implementation of the SUM intrinsic
2    Copyright 2002 Free Software Foundation, Inc.
3    Contributed by Paul Brook <paul@nowt.org>
4
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file.  (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
19 executable.)
20
21 Libgfortran is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public
27 License along with libgfortran; see the file COPYING.  If not,
28 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
29 Boston, MA 02110-1301, USA.  */
30
31 #include "config.h"
32 #include <stdlib.h>
33 #include <assert.h>
34 #include "libgfortran.h"
35
36
37 #if defined (HAVE_GFC_REAL_8) && defined (HAVE_GFC_REAL_8)
38
39
40 extern void sum_r8 (gfc_array_r8 * const restrict, 
41         gfc_array_r8 * const restrict, const index_type * const restrict);
42 export_proto(sum_r8);
43
44 void
45 sum_r8 (gfc_array_r8 * const restrict retarray, 
46         gfc_array_r8 * const restrict array, 
47         const index_type * const restrict pdim)
48 {
49   index_type count[GFC_MAX_DIMENSIONS];
50   index_type extent[GFC_MAX_DIMENSIONS];
51   index_type sstride[GFC_MAX_DIMENSIONS];
52   index_type dstride[GFC_MAX_DIMENSIONS];
53   const GFC_REAL_8 * restrict base;
54   GFC_REAL_8 * restrict dest;
55   index_type rank;
56   index_type n;
57   index_type len;
58   index_type delta;
59   index_type dim;
60
61   /* Make dim zero based to avoid confusion.  */
62   dim = (*pdim) - 1;
63   rank = GFC_DESCRIPTOR_RANK (array) - 1;
64
65   len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
66   delta = array->dim[dim].stride;
67
68   for (n = 0; n < dim; n++)
69     {
70       sstride[n] = array->dim[n].stride;
71       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
72     }
73   for (n = dim; n < rank; n++)
74     {
75       sstride[n] = array->dim[n + 1].stride;
76       extent[n] =
77         array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
78     }
79
80   if (retarray->data == NULL)
81     {
82       for (n = 0; n < rank; n++)
83         {
84           retarray->dim[n].lbound = 0;
85           retarray->dim[n].ubound = extent[n]-1;
86           if (n == 0)
87             retarray->dim[n].stride = 1;
88           else
89             retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
90         }
91
92       retarray->data
93          = internal_malloc_size (sizeof (GFC_REAL_8)
94                                  * retarray->dim[rank-1].stride
95                                  * extent[rank-1]);
96       retarray->offset = 0;
97       retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
98     }
99   else
100     {
101       if (rank != GFC_DESCRIPTOR_RANK (retarray))
102         runtime_error ("rank of return array incorrect");
103     }
104
105   for (n = 0; n < rank; n++)
106     {
107       count[n] = 0;
108       dstride[n] = retarray->dim[n].stride;
109       if (extent[n] <= 0)
110         len = 0;
111     }
112
113   base = array->data;
114   dest = retarray->data;
115
116   while (base)
117     {
118       const GFC_REAL_8 * restrict src;
119       GFC_REAL_8 result;
120       src = base;
121       {
122
123   result = 0;
124         if (len <= 0)
125           *dest = 0;
126         else
127           {
128             for (n = 0; n < len; n++, src += delta)
129               {
130
131   result += *src;
132           }
133             *dest = result;
134           }
135       }
136       /* Advance to the next element.  */
137       count[0]++;
138       base += sstride[0];
139       dest += dstride[0];
140       n = 0;
141       while (count[n] == extent[n])
142         {
143           /* When we get to the end of a dimension, reset it and increment
144              the next dimension.  */
145           count[n] = 0;
146           /* We could precalculate these products, but this is a less
147              frequently used path so proabably not worth it.  */
148           base -= sstride[n] * extent[n];
149           dest -= dstride[n] * extent[n];
150           n++;
151           if (n == rank)
152             {
153               /* Break out of the look.  */
154               base = NULL;
155               break;
156             }
157           else
158             {
159               count[n]++;
160               base += sstride[n];
161               dest += dstride[n];
162             }
163         }
164     }
165 }
166
167
168 extern void msum_r8 (gfc_array_r8 * const restrict, 
169         gfc_array_r8 * const restrict, const index_type * const restrict,
170         gfc_array_l4 * const restrict);
171 export_proto(msum_r8);
172
173 void
174 msum_r8 (gfc_array_r8 * const restrict retarray, 
175         gfc_array_r8 * const restrict array, 
176         const index_type * const restrict pdim, 
177         gfc_array_l4 * const restrict mask)
178 {
179   index_type count[GFC_MAX_DIMENSIONS];
180   index_type extent[GFC_MAX_DIMENSIONS];
181   index_type sstride[GFC_MAX_DIMENSIONS];
182   index_type dstride[GFC_MAX_DIMENSIONS];
183   index_type mstride[GFC_MAX_DIMENSIONS];
184   GFC_REAL_8 * restrict dest;
185   const GFC_REAL_8 * restrict base;
186   const GFC_LOGICAL_4 * restrict mbase;
187   int rank;
188   int dim;
189   index_type n;
190   index_type len;
191   index_type delta;
192   index_type mdelta;
193
194   dim = (*pdim) - 1;
195   rank = GFC_DESCRIPTOR_RANK (array) - 1;
196
197   len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
198   if (len <= 0)
199     return;
200   delta = array->dim[dim].stride;
201   mdelta = mask->dim[dim].stride;
202
203   for (n = 0; n < dim; n++)
204     {
205       sstride[n] = array->dim[n].stride;
206       mstride[n] = mask->dim[n].stride;
207       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
208     }
209   for (n = dim; n < rank; n++)
210     {
211       sstride[n] = array->dim[n + 1].stride;
212       mstride[n] = mask->dim[n + 1].stride;
213       extent[n] =
214         array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
215     }
216
217   if (retarray->data == NULL)
218     {
219       for (n = 0; n < rank; n++)
220         {
221           retarray->dim[n].lbound = 0;
222           retarray->dim[n].ubound = extent[n]-1;
223           if (n == 0)
224             retarray->dim[n].stride = 1;
225           else
226             retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
227         }
228
229       retarray->data
230          = internal_malloc_size (sizeof (GFC_REAL_8)
231                                  * retarray->dim[rank-1].stride
232                                  * extent[rank-1]);
233       retarray->offset = 0;
234       retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
235     }
236   else
237     {
238       if (rank != GFC_DESCRIPTOR_RANK (retarray))
239         runtime_error ("rank of return array incorrect");
240     }
241
242   for (n = 0; n < rank; n++)
243     {
244       count[n] = 0;
245       dstride[n] = retarray->dim[n].stride;
246       if (extent[n] <= 0)
247         return;
248     }
249
250   dest = retarray->data;
251   base = array->data;
252   mbase = mask->data;
253
254   if (GFC_DESCRIPTOR_SIZE (mask) != 4)
255     {
256       /* This allows the same loop to be used for all logical types.  */
257       assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
258       for (n = 0; n < rank; n++)
259         mstride[n] <<= 1;
260       mdelta <<= 1;
261       mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
262     }
263
264   while (base)
265     {
266       const GFC_REAL_8 * restrict src;
267       const GFC_LOGICAL_4 * restrict msrc;
268       GFC_REAL_8 result;
269       src = base;
270       msrc = mbase;
271       {
272
273   result = 0;
274         if (len <= 0)
275           *dest = 0;
276         else
277           {
278             for (n = 0; n < len; n++, src += delta, msrc += mdelta)
279               {
280
281   if (*msrc)
282     result += *src;
283               }
284             *dest = result;
285           }
286       }
287       /* Advance to the next element.  */
288       count[0]++;
289       base += sstride[0];
290       mbase += mstride[0];
291       dest += dstride[0];
292       n = 0;
293       while (count[n] == extent[n])
294         {
295           /* When we get to the end of a dimension, reset it and increment
296              the next dimension.  */
297           count[n] = 0;
298           /* We could precalculate these products, but this is a less
299              frequently used path so proabably not worth it.  */
300           base -= sstride[n] * extent[n];
301           mbase -= mstride[n] * extent[n];
302           dest -= dstride[n] * extent[n];
303           n++;
304           if (n == rank)
305             {
306               /* Break out of the look.  */
307               base = NULL;
308               break;
309             }
310           else
311             {
312               count[n]++;
313               base += sstride[n];
314               mbase += mstride[n];
315               dest += dstride[n];
316             }
317         }
318     }
319 }
320
321
322 extern void ssum_r8 (gfc_array_r8 * const restrict, 
323         gfc_array_r8 * const restrict, const index_type * const restrict,
324         GFC_LOGICAL_4 *);
325 export_proto(ssum_r8);
326
327 void
328 ssum_r8 (gfc_array_r8 * const restrict retarray, 
329         gfc_array_r8 * const restrict array, 
330         const index_type * const restrict pdim, 
331         GFC_LOGICAL_4 * mask)
332 {
333   index_type rank;
334   index_type n;
335   index_type dstride;
336   GFC_REAL_8 *dest;
337
338   if (*mask)
339     {
340       sum_r8 (retarray, array, pdim);
341       return;
342     }
343     rank = GFC_DESCRIPTOR_RANK (array);
344   if (rank <= 0)
345     runtime_error ("Rank of array needs to be > 0");
346
347   if (retarray->data == NULL)
348     {
349       retarray->dim[0].lbound = 0;
350       retarray->dim[0].ubound = rank-1;
351       retarray->dim[0].stride = 1;
352       retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
353       retarray->offset = 0;
354       retarray->data = internal_malloc_size (sizeof (GFC_REAL_8) * rank);
355     }
356   else
357     {
358       if (GFC_DESCRIPTOR_RANK (retarray) != 1)
359         runtime_error ("rank of return array does not equal 1");
360
361       if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
362         runtime_error ("dimension of return array incorrect");
363     }
364
365     dstride = retarray->dim[0].stride;
366     dest = retarray->data;
367
368     for (n = 0; n < rank; n++)
369       dest[n * dstride] = 0 ;
370 }
371
372 #endif