OSDN Git Service

gcc/ChangeLog
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / eoshift3_8.c
1 /* Implementation of the EOSHIFT intrinsic
2    Copyright 2002, 2005, 2007, 2009 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 3 of the License, or (at your option) any later version.
11
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
20
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 <http://www.gnu.org/licenses/>.  */
25
26 #include "libgfortran.h"
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <string.h>
30
31
32 #if defined (HAVE_GFC_INTEGER_8)
33
34 static void
35 eoshift3 (gfc_array_char * const restrict ret, 
36         const gfc_array_char * const restrict array, 
37         const gfc_array_i8 * const restrict h,
38         const gfc_array_char * const restrict bound, 
39         const GFC_INTEGER_8 * const restrict pwhich,
40         const char * filler, index_type filler_len)
41 {
42   /* r.* indicates the return array.  */
43   index_type rstride[GFC_MAX_DIMENSIONS];
44   index_type rstride0;
45   index_type roffset;
46   char *rptr;
47   char * restrict dest;
48   /* s.* indicates the source array.  */
49   index_type sstride[GFC_MAX_DIMENSIONS];
50   index_type sstride0;
51   index_type soffset;
52   const char *sptr;
53   const char *src;
54   /* h.* indicates the shift array.  */
55   index_type hstride[GFC_MAX_DIMENSIONS];
56   index_type hstride0;
57   const GFC_INTEGER_8 *hptr;
58   /* b.* indicates the bound array.  */
59   index_type bstride[GFC_MAX_DIMENSIONS];
60   index_type bstride0;
61   const char *bptr;
62
63   index_type count[GFC_MAX_DIMENSIONS];
64   index_type extent[GFC_MAX_DIMENSIONS];
65   index_type dim;
66   index_type len;
67   index_type n;
68   index_type size;
69   index_type arraysize;
70   int which;
71   GFC_INTEGER_8 sh;
72   GFC_INTEGER_8 delta;
73
74   /* The compiler cannot figure out that these are set, initialize
75      them to avoid warnings.  */
76   len = 0;
77   soffset = 0;
78   roffset = 0;
79
80   arraysize = size0 ((array_t *) array);
81   size = GFC_DESCRIPTOR_SIZE(array);
82
83   if (pwhich)
84     which = *pwhich - 1;
85   else
86     which = 0;
87
88   if (ret->data == NULL)
89     {
90       int i;
91
92       ret->data = internal_malloc_size (size * arraysize);
93       ret->offset = 0;
94       ret->dtype = array->dtype;
95       for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
96         {
97           index_type ub, str;
98
99           ub = GFC_DESCRIPTOR_EXTENT(array,i) - 1;
100
101           if (i == 0)
102             str = 1;
103           else
104             str = GFC_DESCRIPTOR_EXTENT(ret,i-1)
105               * GFC_DESCRIPTOR_STRIDE(ret,i-1);
106
107           GFC_DIMENSION_SET(ret->dim[i], 0, ub, str);
108
109         }
110       if (arraysize > 0)
111         ret->data = internal_malloc_size (size * arraysize);
112       else
113         ret->data = internal_malloc_size (1);
114
115     }
116   else if (unlikely (compile_options.bounds_check))
117     {
118       bounds_equal_extents ((array_t *) ret, (array_t *) array,
119                                  "return value", "EOSHIFT");
120     }
121
122   if (unlikely (compile_options.bounds_check))
123     {
124       bounds_reduced_extents ((array_t *) h, (array_t *) array, which,
125                               "SHIFT argument", "EOSHIFT");
126     }
127
128   if (arraysize == 0)
129     return;
130
131   extent[0] = 1;
132   count[0] = 0;
133   n = 0;
134   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
135     {
136       if (dim == which)
137         {
138           roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
139           if (roffset == 0)
140             roffset = size;
141           soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
142           if (soffset == 0)
143             soffset = size;
144           len = GFC_DESCRIPTOR_EXTENT(array,dim);
145         }
146       else
147         {
148           count[n] = 0;
149           extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
150           rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
151           sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
152
153           hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
154           if (bound)
155             bstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(bound,n);
156           else
157             bstride[n] = 0;
158           n++;
159         }
160     }
161   if (sstride[0] == 0)
162     sstride[0] = size;
163   if (rstride[0] == 0)
164     rstride[0] = size;
165   if (hstride[0] == 0)
166     hstride[0] = 1;
167   if (bound && bstride[0] == 0)
168     bstride[0] = size;
169
170   dim = GFC_DESCRIPTOR_RANK (array);
171   rstride0 = rstride[0];
172   sstride0 = sstride[0];
173   hstride0 = hstride[0];
174   bstride0 = bstride[0];
175   rptr = ret->data;
176   sptr = array->data;
177   hptr = h->data;
178   if (bound)
179     bptr = bound->data;
180   else
181     bptr = NULL;
182
183   while (rptr)
184     {
185       /* Do the shift for this dimension.  */
186       sh = *hptr;
187       if (( sh >= 0 ? sh : -sh ) > len)
188         {
189           delta = len;
190           sh = len;
191         }
192       else
193         delta = (sh >= 0) ? sh: -sh;
194
195       if (sh > 0)
196         {
197           src = &sptr[delta * soffset];
198           dest = rptr;
199         }
200       else
201         {
202           src = sptr;
203           dest = &rptr[delta * roffset];
204         }
205       for (n = 0; n < len - delta; n++)
206         {
207           memcpy (dest, src, size);
208           dest += roffset;
209           src += soffset;
210         }
211       if (sh < 0)
212         dest = rptr;
213       n = delta;
214
215       if (bptr)
216         while (n--)
217           {
218             memcpy (dest, bptr, size);
219             dest += roffset;
220           }
221       else
222         while (n--)
223           {
224             index_type i;
225
226             if (filler_len == 1)
227               memset (dest, filler[0], size);
228             else
229               for (i = 0; i < size; i += filler_len)
230                 memcpy (&dest[i], filler, filler_len);
231
232             dest += roffset;
233           }
234
235       /* Advance to the next section.  */
236       rptr += rstride0;
237       sptr += sstride0;
238       hptr += hstride0;
239       bptr += bstride0;
240       count[0]++;
241       n = 0;
242       while (count[n] == extent[n])
243         {
244           /* When we get to the end of a dimension, reset it and increment
245              the next dimension.  */
246           count[n] = 0;
247           /* We could precalculate these products, but this is a less
248              frequently used path so probably not worth it.  */
249           rptr -= rstride[n] * extent[n];
250           sptr -= sstride[n] * extent[n];
251           hptr -= hstride[n] * extent[n];
252           bptr -= bstride[n] * extent[n];
253           n++;
254           if (n >= dim - 1)
255             {
256               /* Break out of the loop.  */
257               rptr = NULL;
258               break;
259             }
260           else
261             {
262               count[n]++;
263               rptr += rstride[n];
264               sptr += sstride[n];
265               hptr += hstride[n];
266               bptr += bstride[n];
267             }
268         }
269     }
270 }
271
272 extern void eoshift3_8 (gfc_array_char * const restrict, 
273         const gfc_array_char * const restrict,
274         const gfc_array_i8 * const restrict, 
275         const gfc_array_char * const restrict,
276         const GFC_INTEGER_8 *);
277 export_proto(eoshift3_8);
278
279 void
280 eoshift3_8 (gfc_array_char * const restrict ret, 
281         const gfc_array_char * const restrict array,
282         const gfc_array_i8 * const restrict h, 
283         const gfc_array_char * const restrict bound,
284         const GFC_INTEGER_8 * const restrict pwhich)
285 {
286   eoshift3 (ret, array, h, bound, pwhich, "\0", 1);
287 }
288
289
290 extern void eoshift3_8_char (gfc_array_char * const restrict, 
291         GFC_INTEGER_4,
292         const gfc_array_char * const restrict,
293         const gfc_array_i8 * const restrict,
294         const gfc_array_char * const restrict,
295         const GFC_INTEGER_8 * const restrict, 
296         GFC_INTEGER_4, GFC_INTEGER_4);
297 export_proto(eoshift3_8_char);
298
299 void
300 eoshift3_8_char (gfc_array_char * const restrict ret,
301         GFC_INTEGER_4 ret_length __attribute__((unused)),
302         const gfc_array_char * const restrict array, 
303         const gfc_array_i8 *  const restrict h,
304         const gfc_array_char * const restrict bound,
305         const GFC_INTEGER_8 * const restrict pwhich,
306         GFC_INTEGER_4 array_length __attribute__((unused)),
307         GFC_INTEGER_4 bound_length __attribute__((unused)))
308 {
309   eoshift3 (ret, array, h, bound, pwhich, " ", 1);
310 }
311
312
313 extern void eoshift3_8_char4 (gfc_array_char * const restrict, 
314         GFC_INTEGER_4,
315         const gfc_array_char * const restrict,
316         const gfc_array_i8 * const restrict,
317         const gfc_array_char * const restrict,
318         const GFC_INTEGER_8 * const restrict, 
319         GFC_INTEGER_4, GFC_INTEGER_4);
320 export_proto(eoshift3_8_char4);
321
322 void
323 eoshift3_8_char4 (gfc_array_char * const restrict ret,
324         GFC_INTEGER_4 ret_length __attribute__((unused)),
325         const gfc_array_char * const restrict array, 
326         const gfc_array_i8 *  const restrict h,
327         const gfc_array_char * const restrict bound,
328         const GFC_INTEGER_8 * const restrict pwhich,
329         GFC_INTEGER_4 array_length __attribute__((unused)),
330         GFC_INTEGER_4 bound_length __attribute__((unused)))
331 {
332   static const gfc_char4_t space = (unsigned char) ' ';
333   eoshift3 (ret, array, h, bound, pwhich,
334             (const char *) &space, sizeof (gfc_char4_t));
335 }
336
337 #endif