OSDN Git Service

2008-06-13 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / count_4_l.c
1 /* Implementation of the COUNT intrinsic
2    Copyright 2002, 2007 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 "libgfortran.h"
32 #include <stdlib.h>
33 #include <assert.h>
34
35
36 #if defined (HAVE_GFC_INTEGER_4)
37
38
39 extern void count_4_l (gfc_array_i4 * const restrict, 
40         gfc_array_l1 * const restrict, const index_type * const restrict);
41 export_proto(count_4_l);
42
43 void
44 count_4_l (gfc_array_i4 * const restrict retarray, 
45         gfc_array_l1 * const restrict array, 
46         const index_type * const restrict pdim)
47 {
48   index_type count[GFC_MAX_DIMENSIONS];
49   index_type extent[GFC_MAX_DIMENSIONS];
50   index_type sstride[GFC_MAX_DIMENSIONS];
51   index_type dstride[GFC_MAX_DIMENSIONS];
52   const GFC_LOGICAL_1 * restrict base;
53   GFC_INTEGER_4 * restrict dest;
54   index_type rank;
55   index_type n;
56   index_type len;
57   index_type delta;
58   index_type dim;
59   int src_kind;
60   int continue_loop;
61
62   /* Make dim zero based to avoid confusion.  */
63   dim = (*pdim) - 1;
64   rank = GFC_DESCRIPTOR_RANK (array) - 1;
65
66   src_kind = GFC_DESCRIPTOR_SIZE (array);
67
68   len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
69   if (len < 0)
70     len = 0;
71
72   delta = array->dim[dim].stride * src_kind;
73
74   for (n = 0; n < dim; n++)
75     {
76       sstride[n] = array->dim[n].stride * src_kind;
77       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
78
79       if (extent[n] < 0)
80         extent[n] = 0;
81     }
82   for (n = dim; n < rank; n++)
83     {
84       sstride[n] = array->dim[n + 1].stride * src_kind;
85       extent[n] =
86         array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
87
88       if (extent[n] < 0)
89         extent[n] = 0;
90     }
91
92   if (retarray->data == NULL)
93     {
94       size_t alloc_size;
95
96       for (n = 0; n < rank; n++)
97         {
98           retarray->dim[n].lbound = 0;
99           retarray->dim[n].ubound = extent[n]-1;
100           if (n == 0)
101             retarray->dim[n].stride = 1;
102           else
103             retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
104         }
105
106       retarray->offset = 0;
107       retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
108
109       alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
110                    * extent[rank-1];
111
112       if (alloc_size == 0)
113         {
114           /* Make sure we have a zero-sized array.  */
115           retarray->dim[0].lbound = 0;
116           retarray->dim[0].ubound = -1;
117           return;
118         }
119       else
120         retarray->data = internal_malloc_size (alloc_size);
121     }
122   else
123     {
124       if (rank != GFC_DESCRIPTOR_RANK (retarray))
125         runtime_error ("rank of return array incorrect in"
126                        " COUNT intrinsic: is %ld, should be %ld",
127                        (long int) GFC_DESCRIPTOR_RANK (retarray),
128                        (long int) rank);
129
130       if (compile_options.bounds_check)
131         {
132           for (n=0; n < rank; n++)
133             {
134               index_type ret_extent;
135
136               ret_extent = retarray->dim[n].ubound + 1
137                 - retarray->dim[n].lbound;
138               if (extent[n] != ret_extent)
139                 runtime_error ("Incorrect extent in return value of"
140                                " COUNT intrinsic in dimension %d:"
141                                " is %ld, should be %ld", (int) n + 1,
142                                (long int) ret_extent, (long int) extent[n]);
143             }
144         }
145     }
146
147   for (n = 0; n < rank; n++)
148     {
149       count[n] = 0;
150       dstride[n] = retarray->dim[n].stride;
151       if (extent[n] <= 0)
152         len = 0;
153     }
154
155   base = array->data;
156
157   if (src_kind == 1 || src_kind == 2 || src_kind == 4 || src_kind == 8
158 #ifdef HAVE_GFC_LOGICAL_16
159       || src_kind == 16
160 #endif
161     )
162     {
163       if (base)
164         base = GFOR_POINTER_TO_L1 (base, src_kind);
165     }
166   else
167     internal_error (NULL, "Funny sized logical array in COUNT intrinsic");
168
169   dest = retarray->data;
170
171   continue_loop = 1;
172   while (continue_loop)
173     {
174       const GFC_LOGICAL_1 * restrict src;
175       GFC_INTEGER_4 result;
176       src = base;
177       {
178
179   result = 0;
180         if (len <= 0)
181           *dest = 0;
182         else
183           {
184             for (n = 0; n < len; n++, src += delta)
185               {
186
187   if (*src)
188     result++;
189           }
190             *dest = result;
191           }
192       }
193       /* Advance to the next element.  */
194       count[0]++;
195       base += sstride[0];
196       dest += dstride[0];
197       n = 0;
198       while (count[n] == extent[n])
199         {
200           /* When we get to the end of a dimension, reset it and increment
201              the next dimension.  */
202           count[n] = 0;
203           /* We could precalculate these products, but this is a less
204              frequently used path so probably not worth it.  */
205           base -= sstride[n] * extent[n];
206           dest -= dstride[n] * extent[n];
207           n++;
208           if (n == rank)
209             {
210               /* Break out of the look.  */
211               continue_loop = 0;
212               break;
213             }
214           else
215             {
216               count[n]++;
217               base += sstride[n];
218               dest += dstride[n];
219             }
220         }
221     }
222 }
223
224 #endif