]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/intrinsics/reshape_generic.c
in_pack.m4 (internal_pack_'rtype_code`): Destination pointer is restrict.
[thirdparty/gcc.git] / libgfortran / intrinsics / reshape_generic.c
CommitLineData
6de9cd9a 1/* Generic implementation of the RESHAPE intrinsic
36ae8a61 2 Copyright 2002, 2006, 2007 Free Software Foundation, Inc.
6de9cd9a
DN
3 Contributed by Paul Brook <paul@nowt.org>
4
57dea9f6 5This file is part of the GNU Fortran 95 runtime library (libgfortran).
6de9cd9a 6
57dea9f6
TM
7Libgfortran is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public
6de9cd9a 9License as published by the Free Software Foundation; either
57dea9f6
TM
10version 2 of the License, or (at your option) any later version.
11
12In addition to the permissions in the GNU General Public License, the
13Free Software Foundation gives you unlimited permission to link the
14compiled version of this file into combinations with other programs,
15and to distribute those combinations without any restriction coming
16from the use of this file. (The General Public License restrictions
17do apply in other respects; for example, they cover modification of
18the file, and distribution when not linked into a combine
19executable.)
20
21Ligbfortran is distributed in the hope that it will be useful,
6de9cd9a
DN
22but WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57dea9f6 24GNU General Public License for more details.
6de9cd9a 25
57dea9f6
TM
26You should have received a copy of the GNU General Public
27License along with libgfortran; see the file COPYING. If not,
fe2ae685
KC
28write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
29Boston, MA 02110-1301, USA. */
6de9cd9a 30
36ae8a61 31#include "libgfortran.h"
6de9cd9a
DN
32#include <stdlib.h>
33#include <string.h>
34#include <assert.h>
6de9cd9a
DN
35
36typedef GFC_ARRAY_DESCRIPTOR(1, index_type) shape_type;
37typedef GFC_ARRAY_DESCRIPTOR(GFC_MAX_DIMENSIONS, char) parray;
38
7823229b
RS
39static void
40reshape_internal (parray *ret, parray *source, shape_type *shape,
41 parray *pad, shape_type *order, index_type size)
6de9cd9a
DN
42{
43 /* r.* indicates the return array. */
5f9bfaf2
TK
44 index_type rcount[GFC_MAX_DIMENSIONS];
45 index_type rextent[GFC_MAX_DIMENSIONS];
46 index_type rstride[GFC_MAX_DIMENSIONS];
6de9cd9a
DN
47 index_type rstride0;
48 index_type rdim;
49 index_type rsize;
da8f3dcc
TK
50 index_type rs;
51 index_type rex;
5863aacf 52 char * restrict rptr;
6de9cd9a 53 /* s.* indicates the source array. */
5f9bfaf2
TK
54 index_type scount[GFC_MAX_DIMENSIONS];
55 index_type sextent[GFC_MAX_DIMENSIONS];
56 index_type sstride[GFC_MAX_DIMENSIONS];
6de9cd9a
DN
57 index_type sstride0;
58 index_type sdim;
59 index_type ssize;
60 const char *sptr;
61 /* p.* indicates the pad array. */
5f9bfaf2
TK
62 index_type pcount[GFC_MAX_DIMENSIONS];
63 index_type pextent[GFC_MAX_DIMENSIONS];
64 index_type pstride[GFC_MAX_DIMENSIONS];
6de9cd9a
DN
65 index_type pdim;
66 index_type psize;
67 const char *pptr;
68
69 const char *src;
70 int n;
71 int dim;
8c154b65
TK
72 int sempty, pempty, shape_empty;
73 index_type shape_data[GFC_MAX_DIMENSIONS];
74
75 rdim = shape->dim[0].ubound - shape->dim[0].lbound + 1;
76 if (rdim != GFC_DESCRIPTOR_RANK(ret))
77 runtime_error("rank of return array incorrect in RESHAPE intrinsic");
78
79 shape_empty = 0;
80
81 for (n = 0; n < rdim; n++)
82 {
83 shape_data[n] = shape->data[n * shape->dim[0].stride];
84 if (shape_data[n] <= 0)
85 {
86 shape_data[n] = 0;
87 shape_empty = 1;
88 }
89 }
6de9cd9a 90
da8f3dcc
TK
91 if (ret->data == NULL)
92 {
da8f3dcc
TK
93 rdim = shape->dim[0].ubound - shape->dim[0].lbound + 1;
94 rs = 1;
47c07d96 95 for (n = 0; n < rdim; n++)
da8f3dcc
TK
96 {
97 ret->dim[n].lbound = 0;
8c154b65 98 rex = shape_data[n];
da8f3dcc
TK
99 ret->dim[n].ubound = rex - 1;
100 ret->dim[n].stride = rs;
101 rs *= rex;
102 }
efd4dc1a 103 ret->offset = 0;
da8f3dcc
TK
104 ret->data = internal_malloc_size ( rs * size );
105 ret->dtype = (source->dtype & ~GFC_DTYPE_RANK_MASK) | rdim;
106 }
8c154b65
TK
107
108 if (shape_empty)
109 return;
da8f3dcc 110
6de9cd9a
DN
111 rsize = 1;
112 for (n = 0; n < rdim; n++)
113 {
114 if (order)
115 dim = order->data[n * order->dim[0].stride] - 1;
116 else
117 dim = n;
118
119 rcount[n] = 0;
120 rstride[n] = ret->dim[dim].stride;
121 rextent[n] = ret->dim[dim].ubound + 1 - ret->dim[dim].lbound;
122
8c154b65 123 if (rextent[n] != shape_data[dim])
6de9cd9a
DN
124 runtime_error ("shape and target do not conform");
125
126 if (rsize == rstride[n])
127 rsize *= rextent[n];
128 else
129 rsize = 0;
da8f3dcc 130 if (rextent[n] <= 0)
6de9cd9a
DN
131 return;
132 }
133
134 sdim = GFC_DESCRIPTOR_RANK (source);
135 ssize = 1;
47c07d96 136 sempty = 0;
6de9cd9a
DN
137 for (n = 0; n < sdim; n++)
138 {
139 scount[n] = 0;
140 sstride[n] = source->dim[n].stride;
141 sextent[n] = source->dim[n].ubound + 1 - source->dim[n].lbound;
142 if (sextent[n] <= 0)
47c07d96
FXC
143 {
144 sempty = 1;
145 sextent[n] = 0;
146 }
6de9cd9a 147
da8f3dcc 148 if (ssize == sstride[n])
6de9cd9a
DN
149 ssize *= sextent[n];
150 else
151 ssize = 0;
152 }
153
154 if (pad)
155 {
6de9cd9a
DN
156 pdim = GFC_DESCRIPTOR_RANK (pad);
157 psize = 1;
47c07d96 158 pempty = 0;
6de9cd9a
DN
159 for (n = 0; n < pdim; n++)
160 {
161 pcount[n] = 0;
162 pstride[n] = pad->dim[n].stride;
163 pextent[n] = pad->dim[n].ubound + 1 - pad->dim[n].lbound;
164 if (pextent[n] <= 0)
47c07d96
FXC
165 {
166 pempty = 1;
167 pextent[n] = 0;
168 }
169
6de9cd9a
DN
170 if (psize == pstride[n])
171 psize *= pextent[n];
172 else
da8f3dcc 173 psize = 0;
6de9cd9a
DN
174 }
175 pptr = pad->data;
176 }
177 else
178 {
179 pdim = 0;
180 psize = 1;
47c07d96 181 pempty = 1;
6de9cd9a
DN
182 pptr = NULL;
183 }
184
185 if (rsize != 0 && ssize != 0 && psize != 0)
186 {
187 rsize *= size;
188 ssize *= size;
189 psize *= size;
190 reshape_packed (ret->data, rsize, source->data, ssize,
191 pad ? pad->data : NULL, psize);
192 return;
193 }
194 rptr = ret->data;
195 src = sptr = source->data;
196 rstride0 = rstride[0] * size;
197 sstride0 = sstride[0] * size;
198
47c07d96
FXC
199 if (sempty && pempty)
200 abort ();
201
202 if (sempty)
203 {
204 /* Switch immediately to the pad array. */
205 src = pptr;
206 sptr = NULL;
207 sdim = pdim;
208 for (dim = 0; dim < pdim; dim++)
209 {
210 scount[dim] = pcount[dim];
211 sextent[dim] = pextent[dim];
212 sstride[dim] = pstride[dim];
213 sstride0 = sstride[0] * size;
214 }
215 }
216
6de9cd9a
DN
217 while (rptr)
218 {
219 /* Select between the source and pad arrays. */
220 memcpy(rptr, src, size);
221 /* Advance to the next element. */
222 rptr += rstride0;
223 src += sstride0;
224 rcount[0]++;
225 scount[0]++;
47c07d96 226
6de9cd9a
DN
227 /* Advance to the next destination element. */
228 n = 0;
229 while (rcount[n] == rextent[n])
230 {
231 /* When we get to the end of a dimension, reset it and increment
232 the next dimension. */
233 rcount[n] = 0;
234 /* We could precalculate these products, but this is a less
8b6dba81 235 frequently used path so probably not worth it. */
6de9cd9a
DN
236 rptr -= rstride[n] * rextent[n] * size;
237 n++;
238 if (n == rdim)
239 {
240 /* Break out of the loop. */
241 rptr = NULL;
242 break;
243 }
244 else
245 {
246 rcount[n]++;
247 rptr += rstride[n] * size;
248 }
47c07d96
FXC
249 }
250
6de9cd9a
DN
251 /* Advance to the next source element. */
252 n = 0;
253 while (scount[n] == sextent[n])
254 {
255 /* When we get to the end of a dimension, reset it and increment
256 the next dimension. */
257 scount[n] = 0;
258 /* We could precalculate these products, but this is a less
8b6dba81 259 frequently used path so probably not worth it. */
6de9cd9a
DN
260 src -= sstride[n] * sextent[n] * size;
261 n++;
262 if (n == sdim)
263 {
264 if (sptr && pad)
265 {
266 /* Switch to the pad array. */
267 sptr = NULL;
268 sdim = pdim;
269 for (dim = 0; dim < pdim; dim++)
270 {
271 scount[dim] = pcount[dim];
272 sextent[dim] = pextent[dim];
273 sstride[dim] = pstride[dim];
274 sstride0 = sstride[0] * size;
275 }
276 }
277 /* We now start again from the beginning of the pad array. */
278 src = pptr;
279 break;
280 }
281 else
282 {
283 scount[n]++;
cc41ec4e 284 src += sstride[n] * size;
6de9cd9a
DN
285 }
286 }
287 }
288}
7823229b
RS
289
290extern void reshape (parray *, parray *, shape_type *, parray *, shape_type *);
291export_proto(reshape);
292
293void
294reshape (parray *ret, parray *source, shape_type *shape, parray *pad,
295 shape_type *order)
296{
297 reshape_internal (ret, source, shape, pad, order,
298 GFC_DESCRIPTOR_SIZE (source));
299}
300
3571925e
FXC
301
302extern void reshape_char (parray *, gfc_charlen_type, parray *, shape_type *,
303 parray *, shape_type *, gfc_charlen_type,
304 gfc_charlen_type);
7823229b
RS
305export_proto(reshape_char);
306
307void
3571925e 308reshape_char (parray *ret, gfc_charlen_type ret_length __attribute__((unused)),
7823229b 309 parray *source, shape_type *shape, parray *pad,
3571925e
FXC
310 shape_type *order, gfc_charlen_type source_length,
311 gfc_charlen_type pad_length __attribute__((unused)))
7823229b
RS
312{
313 reshape_internal (ret, source, shape, pad, order, source_length);
314}
3571925e
FXC
315
316
317extern void reshape_char4 (parray *, gfc_charlen_type, parray *, shape_type *,
318 parray *, shape_type *, gfc_charlen_type,
319 gfc_charlen_type);
320export_proto(reshape_char4);
321
322void
323reshape_char4 (parray *ret, gfc_charlen_type ret_length __attribute__((unused)),
324 parray *source, shape_type *shape, parray *pad,
325 shape_type *order, gfc_charlen_type source_length,
326 gfc_charlen_type pad_length __attribute__((unused)))
327{
328 reshape_internal (ret, source, shape, pad, order,
329 source_length * sizeof (gfc_char4_t));
330}