OSDN Git Service

PR libfortran/19308
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / eoshift3_4.c
1 /* Implementation of the EOSHIFT intrinsic
2    Copyright 2002, 2005 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 <string.h>
35 #include "libgfortran.h"
36
37 #if defined (HAVE_GFC_INTEGER_4)
38
39 static void
40 eoshift3 (gfc_array_char *ret, const gfc_array_char *array, const gfc_array_i4 *h,
41           const gfc_array_char *bound, const GFC_INTEGER_4 *pwhich,
42           index_type size, char filler)
43 {
44   /* r.* indicates the return array.  */
45   index_type rstride[GFC_MAX_DIMENSIONS];
46   index_type rstride0;
47   index_type roffset;
48   char *rptr;
49   char *dest;
50   /* s.* indicates the source array.  */
51   index_type sstride[GFC_MAX_DIMENSIONS];
52   index_type sstride0;
53   index_type soffset;
54   const char *sptr;
55   const char *src;
56   /* h.* indicates the shift array.  */
57   index_type hstride[GFC_MAX_DIMENSIONS];
58   index_type hstride0;
59   const GFC_INTEGER_4 *hptr;
60   /* b.* indicates the bound array.  */
61   index_type bstride[GFC_MAX_DIMENSIONS];
62   index_type bstride0;
63   const char *bptr;
64
65   index_type count[GFC_MAX_DIMENSIONS];
66   index_type extent[GFC_MAX_DIMENSIONS];
67   index_type dim;
68   index_type len;
69   index_type n;
70   int which;
71   GFC_INTEGER_4 sh;
72   GFC_INTEGER_4 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   if (pwhich)
81     which = *pwhich - 1;
82   else
83     which = 0;
84
85   if (ret->data == NULL)
86     {
87       int i;
88
89       ret->data = internal_malloc_size (size * size0 ((array_t *)array));
90       ret->offset = 0;
91       ret->dtype = array->dtype;
92       for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
93         {
94           ret->dim[i].lbound = 0;
95           ret->dim[i].ubound = array->dim[i].ubound - array->dim[i].lbound;
96
97           if (i == 0)
98             ret->dim[i].stride = 1;
99           else
100             ret->dim[i].stride = (ret->dim[i-1].ubound + 1) * ret->dim[i-1].stride;
101         }
102     }
103
104
105   extent[0] = 1;
106   count[0] = 0;
107   n = 0;
108   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
109     {
110       if (dim == which)
111         {
112           roffset = ret->dim[dim].stride * size;
113           if (roffset == 0)
114             roffset = size;
115           soffset = array->dim[dim].stride * size;
116           if (soffset == 0)
117             soffset = size;
118           len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
119         }
120       else
121         {
122           count[n] = 0;
123           extent[n] = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
124           rstride[n] = ret->dim[dim].stride * size;
125           sstride[n] = array->dim[dim].stride * size;
126
127           hstride[n] = h->dim[n].stride;
128           if (bound)
129             bstride[n] = bound->dim[n].stride * size;
130           else
131             bstride[n] = 0;
132           n++;
133         }
134     }
135   if (sstride[0] == 0)
136     sstride[0] = size;
137   if (rstride[0] == 0)
138     rstride[0] = size;
139   if (hstride[0] == 0)
140     hstride[0] = 1;
141   if (bound && bstride[0] == 0)
142     bstride[0] = size;
143
144   dim = GFC_DESCRIPTOR_RANK (array);
145   rstride0 = rstride[0];
146   sstride0 = sstride[0];
147   hstride0 = hstride[0];
148   bstride0 = bstride[0];
149   rptr = ret->data;
150   sptr = array->data;
151   hptr = h->data;
152   if (bound)
153     bptr = bound->data;
154   else
155     bptr = NULL;
156
157   while (rptr)
158     {
159       /* Do the shift for this dimension.  */
160       sh = *hptr;
161       if (( sh >= 0 ? sh : -sh ) > len)
162         {
163           delta = len;
164           sh = len;
165         }
166       else
167         delta = (sh >= 0) ? sh: -sh;
168
169       if (sh > 0)
170         {
171           src = &sptr[delta * soffset];
172           dest = rptr;
173         }
174       else
175         {
176           src = sptr;
177           dest = &rptr[delta * roffset];
178         }
179       for (n = 0; n < len - delta; n++)
180         {
181           memcpy (dest, src, size);
182           dest += roffset;
183           src += soffset;
184         }
185       if (sh < 0)
186         dest = rptr;
187       n = delta;
188
189       if (bptr)
190         while (n--)
191           {
192             memcpy (dest, bptr, size);
193             dest += roffset;
194           }
195       else
196         while (n--)
197           {
198             memset (dest, filler, size);
199             dest += roffset;
200           }
201
202       /* Advance to the next section.  */
203       rptr += rstride0;
204       sptr += sstride0;
205       hptr += hstride0;
206       bptr += bstride0;
207       count[0]++;
208       n = 0;
209       while (count[n] == extent[n])
210         {
211           /* When we get to the end of a dimension, reset it and increment
212              the next dimension.  */
213           count[n] = 0;
214           /* We could precalculate these products, but this is a less
215              frequently used path so proabably not worth it.  */
216           rptr -= rstride[n] * extent[n];
217           sptr -= sstride[n] * extent[n];
218           hptr -= hstride[n] * extent[n];
219           bptr -= bstride[n] * extent[n];
220           n++;
221           if (n >= dim - 1)
222             {
223               /* Break out of the loop.  */
224               rptr = NULL;
225               break;
226             }
227           else
228             {
229               count[n]++;
230               rptr += rstride[n];
231               sptr += sstride[n];
232               hptr += hstride[n];
233               bptr += bstride[n];
234             }
235         }
236     }
237 }
238
239 extern void eoshift3_4 (gfc_array_char *, const gfc_array_char *,
240                                    const gfc_array_i4 *, const gfc_array_char *,
241                                    const GFC_INTEGER_4 *);
242 export_proto(eoshift3_4);
243
244 void
245 eoshift3_4 (gfc_array_char *ret, const gfc_array_char *array,
246                        const gfc_array_i4 *h, const gfc_array_char *bound,
247                        const GFC_INTEGER_4 *pwhich)
248 {
249   eoshift3 (ret, array, h, bound, pwhich, GFC_DESCRIPTOR_SIZE (array), 0);
250 }
251
252 extern void eoshift3_4_char (gfc_array_char *, GFC_INTEGER_4,
253                                           const gfc_array_char *,
254                                           const gfc_array_i4 *,
255                                           const gfc_array_char *,
256                                           const GFC_INTEGER_4 *, GFC_INTEGER_4,
257                                           GFC_INTEGER_4);
258 export_proto(eoshift3_4_char);
259
260 void
261 eoshift3_4_char (gfc_array_char *ret,
262                               GFC_INTEGER_4 ret_length __attribute__((unused)),
263                               const gfc_array_char *array, const gfc_array_i4 *h,
264                               const gfc_array_char *bound,
265                               const GFC_INTEGER_4 *pwhich,
266                               GFC_INTEGER_4 array_length,
267                               GFC_INTEGER_4 bound_length
268                                 __attribute__((unused)))
269 {
270   eoshift3 (ret, array, h, bound, pwhich, array_length, ' ');
271 }
272
273 #endif