]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/intrinsics/eoshift2.c
iresolve.c (gfc_resolve_all, [...]): Use PREFIX.
[thirdparty/gcc.git] / libgfortran / intrinsics / eoshift2.c
CommitLineData
883c9d4d 1/* Generic implementation of the EOSHIFT intrinsic
6de9cd9a
DN
2 Copyright 2002 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4
5This file is part of the GNU Fortran 95 runtime library (libgfor).
6
7Libgfor is free software; you can redistribute it and/or
8modify it under the terms of the GNU Lesser General Public
9License as published by the Free Software Foundation; either
10version 2.1 of the License, or (at your option) any later version.
11
12Ligbfor is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public
18License along with libgfor; see the file COPYING.LIB. If not,
19write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22#include "config.h"
23#include <stdlib.h>
24#include <assert.h>
25#include <string.h>
26#include "libgfortran.h"
27
28static const char zeros[16] =
29 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
30
31/* TODO: make this work for large shifts when
32 sizeof(int) < sizeof (index_type). */
33
34static void
7f68c75f
RH
35eoshift2 (gfc_array_char *ret, const gfc_array_char *array,
36 int shift, const gfc_array_char *bound, int which)
6de9cd9a
DN
37{
38 /* r.* indicates the return array. */
39 index_type rstride[GFC_MAX_DIMENSIONS - 1];
40 index_type rstride0;
41 index_type roffset;
42 char *rptr;
43 char *dest;
44 /* s.* indicates the source array. */
45 index_type sstride[GFC_MAX_DIMENSIONS - 1];
46 index_type sstride0;
47 index_type soffset;
48 const char *sptr;
49 const char *src;
50 /* b.* indicates the bound array. */
51 index_type bstride[GFC_MAX_DIMENSIONS - 1];
52 index_type bstride0;
53 const char *bptr;
54
55 index_type count[GFC_MAX_DIMENSIONS - 1];
56 index_type extent[GFC_MAX_DIMENSIONS - 1];
57 index_type dim;
58 index_type size;
59 index_type len;
60 index_type n;
61
62 size = GFC_DESCRIPTOR_SIZE (ret);
63
883c9d4d
VL
64 if (ret->data == NULL)
65 {
66 int i;
67
07d3cebe 68 ret->data = internal_malloc_size (size * size0 ((array_t *)array));
883c9d4d
VL
69 ret->base = 0;
70 ret->dtype = array->dtype;
71 for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
72 {
73 ret->dim[i].lbound = 0;
74 ret->dim[i].ubound = array->dim[i].ubound - array->dim[i].lbound;
75
76 if (i == 0)
77 ret->dim[i].stride = 1;
78 else
79 ret->dim[i].stride = (ret->dim[i-1].ubound + 1) * ret->dim[i-1].stride;
80 }
81 }
82
6de9cd9a
DN
83 which = which - 1;
84
85 extent[0] = 1;
86 count[0] = 0;
87 size = GFC_DESCRIPTOR_SIZE (array);
88 n = 0;
89 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
90 {
91 if (dim == which)
92 {
93 roffset = ret->dim[dim].stride * size;
94 if (roffset == 0)
95 roffset = size;
96 soffset = array->dim[dim].stride * size;
97 if (soffset == 0)
98 soffset = size;
99 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
100 }
101 else
102 {
103 count[n] = 0;
104 extent[n] = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
105 rstride[n] = ret->dim[dim].stride * size;
106 sstride[n] = array->dim[dim].stride * size;
107 if (bound)
108 bstride[n] = bound->dim[n].stride * size;
109 else
110 bstride[n] = 0;
111 n++;
112 }
113 }
114 if (sstride[0] == 0)
115 sstride[0] = size;
116 if (rstride[0] == 0)
117 rstride[0] = size;
118 if (bound && bstride[0] == 0)
119 bstride[0] = size;
120
121 dim = GFC_DESCRIPTOR_RANK (array);
122 rstride0 = rstride[0];
123 sstride0 = sstride[0];
124 bstride0 = bstride[0];
125 rptr = ret->data;
126 sptr = array->data;
127 if (bound)
128 bptr = bound->data;
129 else
130 bptr = zeros;
131
132 if (shift > 0)
133 len = len - shift;
134 else
135 len = len + shift;
136
137 while (rptr)
138 {
139 /* Do the shift for this dimension. */
140 if (shift > 0)
141 {
142 src = &sptr[shift * soffset];
143 dest = rptr;
144 }
145 else
146 {
147 src = sptr;
148 dest = &rptr[-shift * roffset];
149 }
150 for (n = 0; n < len; n++)
151 {
152 memcpy (dest, src, size);
153 dest += roffset;
154 src += soffset;
155 }
156 if (shift >= 0)
157 {
158 n = shift;
159 }
160 else
161 {
162 dest = rptr;
163 n = -shift;
164 }
165
166 while (n--)
167 {
168 memcpy (dest, bptr, size);
169 dest += roffset;
170 }
171
172 /* Advance to the next section. */
173 rptr += rstride0;
174 sptr += sstride0;
175 bptr += bstride0;
176 count[0]++;
177 n = 0;
178 while (count[n] == extent[n])
179 {
180 /* When we get to the end of a dimension, reset it and increment
181 the next dimension. */
182 count[n] = 0;
183 /* We could precalculate these products, but this is a less
184 frequently used path so proabably not worth it. */
185 rptr -= rstride[n] * extent[n];
186 sptr -= sstride[n] * extent[n];
187 bptr -= bstride[n] * extent[n];
188 n++;
189 if (n >= dim - 1)
190 {
191 /* Break out of the loop. */
192 rptr = NULL;
193 break;
194 }
195 else
196 {
197 count[n]++;
198 rptr += rstride[n];
199 sptr += sstride[n];
200 bptr += bstride[n];
201 }
202 }
203 }
204}
205
7f68c75f
RH
206extern void eoshift2_4 (gfc_array_char *, const gfc_array_char *,
207 const GFC_INTEGER_4 *, const gfc_array_char *,
208 const GFC_INTEGER_4 *);
209export_proto(eoshift2_4);
6de9cd9a
DN
210
211void
7f68c75f
RH
212eoshift2_4 (gfc_array_char *ret, const gfc_array_char *array,
213 const GFC_INTEGER_4 *pshift, const gfc_array_char *bound,
214 const GFC_INTEGER_4 *pdim)
6de9cd9a 215{
7f68c75f 216 eoshift2 (ret, array, *pshift, bound, pdim ? *pdim : 1);
6de9cd9a
DN
217}
218
7f68c75f
RH
219extern void eoshift2_8 (gfc_array_char *, const gfc_array_char *,
220 const GFC_INTEGER_8 *, const gfc_array_char *,
221 const GFC_INTEGER_8 *);
222export_proto(eoshift2_8);
6de9cd9a
DN
223
224void
7f68c75f
RH
225eoshift2_8 (gfc_array_char *ret, const gfc_array_char *array,
226 const GFC_INTEGER_8 *pshift, const gfc_array_char *bound,
227 const GFC_INTEGER_8 *pdim)
6de9cd9a 228{
7f68c75f 229 eoshift2 (ret, array, *pshift, bound, pdim ? *pdim : 1);
6de9cd9a 230}