reshape.m4 revision 1.1.1.3 1 1.1 mrg `/* Implementation of the RESHAPE intrinsic
2 1.1.1.3 mrg Copyright (C) 2002-2022 Free Software Foundation, Inc.
3 1.1 mrg Contributed by Paul Brook <paul (a] nowt.org>
4 1.1 mrg
5 1.1 mrg This file is part of the GNU Fortran runtime library (libgfortran).
6 1.1 mrg
7 1.1 mrg Libgfortran is free software; you can redistribute it and/or
8 1.1 mrg modify it under the terms of the GNU General Public
9 1.1 mrg License as published by the Free Software Foundation; either
10 1.1 mrg version 3 of the License, or (at your option) any later version.
11 1.1 mrg
12 1.1 mrg Libgfortran is distributed in the hope that it will be useful,
13 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 mrg GNU General Public License for more details.
16 1.1 mrg
17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
18 1.1 mrg permissions described in the GCC Runtime Library Exception, version
19 1.1 mrg 3.1, as published by the Free Software Foundation.
20 1.1 mrg
21 1.1 mrg You should have received a copy of the GNU General Public License and
22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 1.1 mrg <http://www.gnu.org/licenses/>. */
25 1.1 mrg
26 1.1 mrg #include "libgfortran.h"'
27 1.1 mrg
28 1.1 mrg include(iparm.m4)dnl
29 1.1 mrg
30 1.1 mrg `#if defined (HAVE_'rtype_name`)
31 1.1 mrg
32 1.1 mrg typedef GFC_FULL_ARRAY_DESCRIPTOR(1, 'index_type`) 'shape_type`;'
33 1.1 mrg
34 1.1 mrg dnl For integer routines, only the kind (ie size) is used to name the
35 1.1 mrg dnl function. The same function will be used for integer and logical
36 1.1 mrg dnl arrays of the same kind.
37 1.1 mrg
38 1.1 mrg `extern void reshape_'rtype_ccode` ('rtype` * const restrict,
39 1.1 mrg 'rtype` * const restrict,
40 1.1 mrg 'shape_type` * const restrict,
41 1.1 mrg 'rtype` * const restrict,
42 1.1 mrg 'shape_type` * const restrict);
43 1.1 mrg export_proto(reshape_'rtype_ccode`);
44 1.1 mrg
45 1.1 mrg void
46 1.1 mrg reshape_'rtype_ccode` ('rtype` * const restrict ret,
47 1.1 mrg 'rtype` * const restrict source,
48 1.1 mrg 'shape_type` * const restrict shape,
49 1.1 mrg 'rtype` * const restrict pad,
50 1.1 mrg 'shape_type` * const restrict order)
51 1.1 mrg {
52 1.1 mrg /* r.* indicates the return array. */
53 1.1 mrg index_type rcount[GFC_MAX_DIMENSIONS];
54 1.1 mrg index_type rextent[GFC_MAX_DIMENSIONS];
55 1.1 mrg index_type rstride[GFC_MAX_DIMENSIONS];
56 1.1 mrg index_type rstride0;
57 1.1 mrg index_type rdim;
58 1.1 mrg index_type rsize;
59 1.1 mrg index_type rs;
60 1.1 mrg index_type rex;
61 1.1 mrg 'rtype_name` *rptr;
62 1.1 mrg /* s.* indicates the source array. */
63 1.1 mrg index_type scount[GFC_MAX_DIMENSIONS];
64 1.1 mrg index_type sextent[GFC_MAX_DIMENSIONS];
65 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS];
66 1.1 mrg index_type sstride0;
67 1.1 mrg index_type sdim;
68 1.1 mrg index_type ssize;
69 1.1 mrg const 'rtype_name` *sptr;
70 1.1 mrg /* p.* indicates the pad array. */
71 1.1 mrg index_type pcount[GFC_MAX_DIMENSIONS];
72 1.1 mrg index_type pextent[GFC_MAX_DIMENSIONS];
73 1.1 mrg index_type pstride[GFC_MAX_DIMENSIONS];
74 1.1 mrg index_type pdim;
75 1.1 mrg index_type psize;
76 1.1 mrg const 'rtype_name` *pptr;
77 1.1 mrg
78 1.1 mrg const 'rtype_name` *src;
79 1.1 mrg int sempty, pempty, shape_empty;
80 1.1 mrg index_type shape_data[GFC_MAX_DIMENSIONS];
81 1.1 mrg
82 1.1 mrg rdim = GFC_DESCRIPTOR_EXTENT(shape,0);
83 1.1 mrg /* rdim is always > 0; this lets the compiler optimize more and
84 1.1 mrg avoids a potential warning. */
85 1.1 mrg GFC_ASSERT(rdim>0);
86 1.1 mrg
87 1.1 mrg if (rdim != GFC_DESCRIPTOR_RANK(ret))
88 1.1 mrg runtime_error("rank of return array incorrect in RESHAPE intrinsic");
89 1.1 mrg
90 1.1 mrg shape_empty = 0;
91 1.1 mrg
92 1.1 mrg for (index_type n = 0; n < rdim; n++)
93 1.1 mrg {
94 1.1 mrg shape_data[n] = shape->base_addr[n * GFC_DESCRIPTOR_STRIDE(shape,0)];
95 1.1 mrg if (shape_data[n] <= 0)
96 1.1 mrg {
97 1.1 mrg shape_data[n] = 0;
98 1.1 mrg shape_empty = 1;
99 1.1 mrg }
100 1.1 mrg }
101 1.1 mrg
102 1.1 mrg if (ret->base_addr == NULL)
103 1.1 mrg {
104 1.1 mrg index_type alloc_size;
105 1.1 mrg
106 1.1 mrg rs = 1;
107 1.1 mrg for (index_type n = 0; n < rdim; n++)
108 1.1 mrg {
109 1.1 mrg rex = shape_data[n];
110 1.1 mrg
111 1.1 mrg GFC_DIMENSION_SET(ret->dim[n], 0, rex - 1, rs);
112 1.1 mrg
113 1.1 mrg rs *= rex;
114 1.1 mrg }
115 1.1 mrg ret->offset = 0;
116 1.1 mrg
117 1.1 mrg if (unlikely (rs < 1))
118 1.1 mrg alloc_size = 0;
119 1.1 mrg else
120 1.1 mrg alloc_size = rs;
121 1.1 mrg
122 1.1 mrg ret->base_addr = xmallocarray (alloc_size, sizeof ('rtype_name`));
123 1.1 mrg ret->dtype.rank = rdim;
124 1.1 mrg }
125 1.1 mrg
126 1.1 mrg if (shape_empty)
127 1.1 mrg return;
128 1.1 mrg
129 1.1 mrg if (pad)
130 1.1 mrg {
131 1.1 mrg pdim = GFC_DESCRIPTOR_RANK (pad);
132 1.1 mrg psize = 1;
133 1.1 mrg pempty = 0;
134 1.1 mrg for (index_type n = 0; n < pdim; n++)
135 1.1 mrg {
136 1.1 mrg pcount[n] = 0;
137 1.1 mrg pstride[n] = GFC_DESCRIPTOR_STRIDE(pad,n);
138 1.1 mrg pextent[n] = GFC_DESCRIPTOR_EXTENT(pad,n);
139 1.1 mrg if (pextent[n] <= 0)
140 1.1 mrg {
141 1.1 mrg pempty = 1;
142 1.1 mrg pextent[n] = 0;
143 1.1 mrg }
144 1.1 mrg
145 1.1 mrg if (psize == pstride[n])
146 1.1 mrg psize *= pextent[n];
147 1.1 mrg else
148 1.1 mrg psize = 0;
149 1.1 mrg }
150 1.1 mrg pptr = pad->base_addr;
151 1.1 mrg }
152 1.1 mrg else
153 1.1 mrg {
154 1.1 mrg pdim = 0;
155 1.1 mrg psize = 1;
156 1.1 mrg pempty = 1;
157 1.1 mrg pptr = NULL;
158 1.1 mrg }
159 1.1 mrg
160 1.1 mrg if (unlikely (compile_options.bounds_check))
161 1.1 mrg {
162 1.1 mrg index_type ret_extent, source_extent;
163 1.1 mrg
164 1.1 mrg rs = 1;
165 1.1 mrg for (index_type n = 0; n < rdim; n++)
166 1.1 mrg {
167 1.1 mrg rs *= shape_data[n];
168 1.1 mrg ret_extent = GFC_DESCRIPTOR_EXTENT(ret,n);
169 1.1 mrg if (ret_extent != shape_data[n])
170 1.1 mrg runtime_error("Incorrect extent in return value of RESHAPE"
171 1.1 mrg " intrinsic in dimension %ld: is %ld,"
172 1.1 mrg " should be %ld", (long int) n+1,
173 1.1 mrg (long int) ret_extent, (long int) shape_data[n]);
174 1.1 mrg }
175 1.1 mrg
176 1.1 mrg source_extent = 1;
177 1.1 mrg sdim = GFC_DESCRIPTOR_RANK (source);
178 1.1 mrg for (index_type n = 0; n < sdim; n++)
179 1.1 mrg {
180 1.1 mrg index_type se;
181 1.1 mrg se = GFC_DESCRIPTOR_EXTENT(source,n);
182 1.1 mrg source_extent *= se > 0 ? se : 0;
183 1.1 mrg }
184 1.1 mrg
185 1.1 mrg if (rs > source_extent && (!pad || pempty))
186 1.1 mrg runtime_error("Incorrect size in SOURCE argument to RESHAPE"
187 1.1 mrg " intrinsic: is %ld, should be %ld",
188 1.1 mrg (long int) source_extent, (long int) rs);
189 1.1 mrg
190 1.1 mrg if (order)
191 1.1 mrg {
192 1.1 mrg int seen[GFC_MAX_DIMENSIONS];
193 1.1 mrg index_type v;
194 1.1 mrg
195 1.1 mrg for (index_type n = 0; n < rdim; n++)
196 1.1 mrg seen[n] = 0;
197 1.1 mrg
198 1.1 mrg for (index_type n = 0; n < rdim; n++)
199 1.1 mrg {
200 1.1 mrg v = order->base_addr[n * GFC_DESCRIPTOR_STRIDE(order,0)] - 1;
201 1.1 mrg
202 1.1 mrg if (v < 0 || v >= rdim)
203 1.1 mrg runtime_error("Value %ld out of range in ORDER argument"
204 1.1 mrg " to RESHAPE intrinsic", (long int) v + 1);
205 1.1 mrg
206 1.1 mrg if (seen[v] != 0)
207 1.1 mrg runtime_error("Duplicate value %ld in ORDER argument to"
208 1.1 mrg " RESHAPE intrinsic", (long int) v + 1);
209 1.1 mrg
210 1.1 mrg seen[v] = 1;
211 1.1 mrg }
212 1.1 mrg }
213 1.1 mrg }
214 1.1 mrg
215 1.1 mrg rsize = 1;
216 1.1 mrg for (index_type n = 0; n < rdim; n++)
217 1.1 mrg {
218 1.1 mrg index_type dim;
219 1.1 mrg if (order)
220 1.1 mrg dim = order->base_addr[n * GFC_DESCRIPTOR_STRIDE(order,0)] - 1;
221 1.1 mrg else
222 1.1 mrg dim = n;
223 1.1 mrg
224 1.1 mrg rcount[n] = 0;
225 1.1 mrg rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,dim);
226 1.1 mrg rextent[n] = GFC_DESCRIPTOR_EXTENT(ret,dim);
227 1.1 mrg if (rextent[n] < 0)
228 1.1 mrg rextent[n] = 0;
229 1.1 mrg
230 1.1 mrg if (rextent[n] != shape_data[dim])
231 1.1 mrg runtime_error ("shape and target do not conform");
232 1.1 mrg
233 1.1 mrg if (rsize == rstride[n])
234 1.1 mrg rsize *= rextent[n];
235 1.1 mrg else
236 1.1 mrg rsize = 0;
237 1.1 mrg if (rextent[n] <= 0)
238 1.1 mrg return;
239 1.1 mrg }
240 1.1 mrg
241 1.1 mrg sdim = GFC_DESCRIPTOR_RANK (source);
242 1.1 mrg
243 1.1 mrg /* sdim is always > 0; this lets the compiler optimize more and
244 1.1 mrg avoids a warning. */
245 1.1 mrg GFC_ASSERT(sdim>0);
246 1.1 mrg
247 1.1 mrg ssize = 1;
248 1.1 mrg sempty = 0;
249 1.1 mrg for (index_type n = 0; n < sdim; n++)
250 1.1 mrg {
251 1.1 mrg scount[n] = 0;
252 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(source,n);
253 1.1 mrg sextent[n] = GFC_DESCRIPTOR_EXTENT(source,n);
254 1.1 mrg if (sextent[n] <= 0)
255 1.1 mrg {
256 1.1 mrg sempty = 1;
257 1.1 mrg sextent[n] = 0;
258 1.1 mrg }
259 1.1 mrg
260 1.1 mrg if (ssize == sstride[n])
261 1.1 mrg ssize *= sextent[n];
262 1.1 mrg else
263 1.1 mrg ssize = 0;
264 1.1 mrg }
265 1.1 mrg
266 1.1 mrg if (rsize != 0 && ssize != 0 && psize != 0)
267 1.1 mrg {
268 1.1 mrg rsize *= sizeof ('rtype_name`);
269 1.1 mrg ssize *= sizeof ('rtype_name`);
270 1.1 mrg psize *= sizeof ('rtype_name`);
271 1.1 mrg reshape_packed ((char *)ret->base_addr, rsize, (char *)source->base_addr,
272 1.1 mrg ssize, pad ? (char *)pad->base_addr : NULL, psize);
273 1.1 mrg return;
274 1.1 mrg }
275 1.1 mrg rptr = ret->base_addr;
276 1.1 mrg src = sptr = source->base_addr;
277 1.1 mrg rstride0 = rstride[0];
278 1.1 mrg sstride0 = sstride[0];
279 1.1 mrg
280 1.1 mrg if (sempty && pempty)
281 1.1 mrg abort ();
282 1.1 mrg
283 1.1 mrg if (sempty)
284 1.1 mrg {
285 1.1 mrg /* Pretend we are using the pad array the first time around, too. */
286 1.1 mrg src = pptr;
287 1.1 mrg sptr = pptr;
288 1.1 mrg sdim = pdim;
289 1.1 mrg for (index_type dim = 0; dim < pdim; dim++)
290 1.1 mrg {
291 1.1 mrg scount[dim] = pcount[dim];
292 1.1 mrg sextent[dim] = pextent[dim];
293 1.1 mrg sstride[dim] = pstride[dim];
294 1.1 mrg sstride0 = pstride[0];
295 1.1 mrg }
296 1.1 mrg }
297 1.1 mrg
298 1.1 mrg while (rptr)
299 1.1 mrg {
300 1.1 mrg /* Select between the source and pad arrays. */
301 1.1 mrg *rptr = *src;
302 1.1 mrg /* Advance to the next element. */
303 1.1 mrg rptr += rstride0;
304 1.1 mrg src += sstride0;
305 1.1 mrg rcount[0]++;
306 1.1 mrg scount[0]++;
307 1.1 mrg
308 1.1 mrg /* Advance to the next destination element. */
309 1.1 mrg index_type n = 0;
310 1.1 mrg while (rcount[n] == rextent[n])
311 1.1 mrg {
312 1.1 mrg /* When we get to the end of a dimension, reset it and increment
313 1.1 mrg the next dimension. */
314 1.1 mrg rcount[n] = 0;
315 1.1 mrg /* We could precalculate these products, but this is a less
316 1.1 mrg frequently used path so probably not worth it. */
317 1.1 mrg rptr -= rstride[n] * rextent[n];
318 1.1 mrg n++;
319 1.1 mrg if (n == rdim)
320 1.1 mrg {
321 1.1 mrg /* Break out of the loop. */
322 1.1 mrg rptr = NULL;
323 1.1 mrg break;
324 1.1 mrg }
325 1.1 mrg else
326 1.1 mrg {
327 1.1 mrg rcount[n]++;
328 1.1 mrg rptr += rstride[n];
329 1.1 mrg }
330 1.1 mrg }
331 1.1 mrg /* Advance to the next source element. */
332 1.1 mrg n = 0;
333 1.1 mrg while (scount[n] == sextent[n])
334 1.1 mrg {
335 1.1 mrg /* When we get to the end of a dimension, reset it and increment
336 1.1 mrg the next dimension. */
337 1.1 mrg scount[n] = 0;
338 1.1 mrg /* We could precalculate these products, but this is a less
339 1.1 mrg frequently used path so probably not worth it. */
340 1.1 mrg src -= sstride[n] * sextent[n];
341 1.1 mrg n++;
342 1.1 mrg if (n == sdim)
343 1.1 mrg {
344 1.1 mrg if (sptr && pad)
345 1.1 mrg {
346 1.1 mrg /* Switch to the pad array. */
347 1.1 mrg sptr = NULL;
348 1.1 mrg sdim = pdim;
349 1.1 mrg for (index_type dim = 0; dim < pdim; dim++)
350 1.1 mrg {
351 1.1 mrg scount[dim] = pcount[dim];
352 1.1 mrg sextent[dim] = pextent[dim];
353 1.1 mrg sstride[dim] = pstride[dim];
354 1.1 mrg sstride0 = sstride[0];
355 1.1 mrg }
356 1.1 mrg }
357 1.1 mrg /* We now start again from the beginning of the pad array. */
358 1.1 mrg src = pptr;
359 1.1 mrg break;
360 1.1 mrg }
361 1.1 mrg else
362 1.1 mrg {
363 1.1 mrg scount[n]++;
364 1.1 mrg src += sstride[n];
365 1.1 mrg }
366 1.1 mrg }
367 1.1 mrg }
368 1.1 mrg }
369 1.1 mrg
370 1.1 mrg #endif'
371