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