OSDN Git Service

gcc/fortran/
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / eoshift1_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 static void
38 eoshift1 (gfc_array_char *ret, const gfc_array_char *array, const gfc_array_i4 *h,
39           const char *pbound, const GFC_INTEGER_4 *pwhich, index_type size,
40           char filler)
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 *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_4 *hptr;
58
59   index_type count[GFC_MAX_DIMENSIONS];
60   index_type extent[GFC_MAX_DIMENSIONS];
61   index_type dim;
62   index_type len;
63   index_type n;
64   int which;
65   GFC_INTEGER_4 sh;
66   GFC_INTEGER_4 delta;
67
68   /* The compiler cannot figure out that these are set, initialize
69      them to avoid warnings.  */
70   len = 0;
71   soffset = 0;
72   roffset = 0;
73
74   if (pwhich)
75     which = *pwhich - 1;
76   else
77     which = 0;
78
79   extent[0] = 1;
80   count[0] = 0;
81
82   if (ret->data == NULL)
83     {
84       int i;
85
86       ret->data = internal_malloc_size (size * size0 ((array_t *)array));
87       ret->offset = 0;
88       ret->dtype = array->dtype;
89       for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
90         {
91           ret->dim[i].lbound = 0;
92           ret->dim[i].ubound = array->dim[i].ubound - array->dim[i].lbound;
93
94           if (i == 0)
95             ret->dim[i].stride = 1;
96           else
97             ret->dim[i].stride = (ret->dim[i-1].ubound + 1) * ret->dim[i-1].stride;
98         }
99     }
100
101   n = 0;
102   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
103     {
104       if (dim == which)
105         {
106           roffset = ret->dim[dim].stride * size;
107           if (roffset == 0)
108             roffset = size;
109           soffset = array->dim[dim].stride * size;
110           if (soffset == 0)
111             soffset = size;
112           len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
113         }
114       else
115         {
116           count[n] = 0;
117           extent[n] = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
118           rstride[n] = ret->dim[dim].stride * size;
119           sstride[n] = array->dim[dim].stride * size;
120
121           hstride[n] = h->dim[n].stride;
122           n++;
123         }
124     }
125   if (sstride[0] == 0)
126     sstride[0] = size;
127   if (rstride[0] == 0)
128     rstride[0] = size;
129   if (hstride[0] == 0)
130     hstride[0] = 1;
131
132   dim = GFC_DESCRIPTOR_RANK (array);
133   rstride0 = rstride[0];
134   sstride0 = sstride[0];
135   hstride0 = hstride[0];
136   rptr = ret->data;
137   sptr = array->data;
138   hptr = h->data;
139
140   while (rptr)
141     {
142       /* Do the shift for this dimension.  */
143       sh = *hptr;
144       if (( sh >= 0 ? sh : -sh ) > len)
145         {
146           delta = len;
147           sh = len;
148         }
149       else
150         delta = (sh >= 0) ? sh: -sh;
151
152       if (sh > 0)
153         {
154           src = &sptr[delta * soffset];
155           dest = rptr;
156         }
157       else
158         {
159           src = sptr;
160           dest = &rptr[delta * roffset];
161         }
162       for (n = 0; n < len - delta; n++)
163         {
164           memcpy (dest, src, size);
165           dest += roffset;
166           src += soffset;
167         }
168       if (sh < 0)
169         dest = rptr;
170       n = delta;
171
172       if (pbound)
173         while (n--)
174           {
175             memcpy (dest, pbound, size);
176             dest += roffset;
177           }
178       else
179         while (n--)
180           {
181             memset (dest, filler, size);
182             dest += roffset;
183           }
184
185       /* Advance to the next section.  */
186       rptr += rstride0;
187       sptr += sstride0;
188       hptr += hstride0;
189       count[0]++;
190       n = 0;
191       while (count[n] == extent[n])
192         {
193           /* When we get to the end of a dimension, reset it and increment
194              the next dimension.  */
195           count[n] = 0;
196           /* We could precalculate these products, but this is a less
197              frequently used path so proabably not worth it.  */
198           rptr -= rstride[n] * extent[n];
199           sptr -= sstride[n] * extent[n];
200           hptr -= hstride[n] * extent[n];
201           n++;
202           if (n >= dim - 1)
203             {
204               /* Break out of the loop.  */
205               rptr = NULL;
206               break;
207             }
208           else
209             {
210               count[n]++;
211               rptr += rstride[n];
212               sptr += sstride[n];
213               hptr += hstride[n];
214             }
215         }
216     }
217 }
218
219 void eoshift1_4 (gfc_array_char *, const gfc_array_char *,
220                             const gfc_array_i4 *, const char *, const GFC_INTEGER_4 *);
221 export_proto(eoshift1_4);
222
223 void
224 eoshift1_4 (gfc_array_char *ret, const gfc_array_char *array,
225                        const gfc_array_i4 *h, const char *pbound,
226                        const GFC_INTEGER_4 *pwhich)
227 {
228   eoshift1 (ret, array, h, pbound, pwhich, GFC_DESCRIPTOR_SIZE (array), 0);
229 }
230
231 void eoshift1_4_char (gfc_array_char *, GFC_INTEGER_4,
232                                    const gfc_array_char *, const gfc_array_i4 *,
233                                    const char *, const GFC_INTEGER_4 *,
234                                    GFC_INTEGER_4, GFC_INTEGER_4);
235 export_proto(eoshift1_4_char);
236
237 void
238 eoshift1_4_char (gfc_array_char *ret,
239                               GFC_INTEGER_4 ret_length __attribute__((unused)),
240                               const gfc_array_char *array, const gfc_array_i4 *h,
241                               const char *pbound, const GFC_INTEGER_4 *pwhich,
242                               GFC_INTEGER_4 array_length,
243                               GFC_INTEGER_4 bound_length
244                                 __attribute__((unused)))
245 {
246   eoshift1 (ret, array, h, pbound, pwhich, array_length, ' ');
247 }