OSDN Git Service

2008-09-06 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / all_l1.c
1 /* Implementation of the ALL 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_LOGICAL_1)
37
38
39 extern void all_l1 (gfc_array_l1 * const restrict, 
40         gfc_array_l1 * const restrict, const index_type * const restrict);
41 export_proto(all_l1);
42
43 void
44 all_l1 (gfc_array_l1 * 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_LOGICAL_1 * 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_LOGICAL_1) * 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                        " ALL intrinsic: is %ld, should be %ld",
127                        (long int) GFC_DESCRIPTOR_RANK (retarray),
128                        (long int) rank);
129
130       if (unlikely (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                                " ALL 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 ALL 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_LOGICAL_1 result;
176       src = base;
177       {
178
179   /* Return true only if all the elements are set.  */
180   result = 1;
181         if (len <= 0)
182           *dest = 1;
183         else
184           {
185             for (n = 0; n < len; n++, src += delta)
186               {
187
188   if (! *src)
189     {
190       result = 0;
191       break;
192     }
193           }
194             *dest = result;
195           }
196       }
197       /* Advance to the next element.  */
198       count[0]++;
199       base += sstride[0];
200       dest += dstride[0];
201       n = 0;
202       while (count[n] == extent[n])
203         {
204           /* When we get to the end of a dimension, reset it and increment
205              the next dimension.  */
206           count[n] = 0;
207           /* We could precalculate these products, but this is a less
208              frequently used path so probably not worth it.  */
209           base -= sstride[n] * extent[n];
210           dest -= dstride[n] * extent[n];
211           n++;
212           if (n == rank)
213             {
214               /* Break out of the look.  */
215               continue_loop = 0;
216               break;
217             }
218           else
219             {
220               count[n]++;
221               base += sstride[n];
222               dest += dstride[n];
223             }
224         }
225     }
226 }
227
228 #endif