1 /* Implementation of the RESHAPE intrinsic
2 Copyright 2002, 2006, 2007, 2009 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
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 3 of the License, or (at your option) any later version.
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgfortran.h"
31 #if defined (HAVE_GFC_INTEGER_4)
33 typedef GFC_ARRAY_DESCRIPTOR(1, index_type
) shape_type
;
36 extern void reshape_4 (gfc_array_i4
* const restrict
,
37 gfc_array_i4
* const restrict
,
38 shape_type
* const restrict
,
39 gfc_array_i4
* const restrict
,
40 shape_type
* const restrict
);
41 export_proto(reshape_4
);
44 reshape_4 (gfc_array_i4
* const restrict ret
,
45 gfc_array_i4
* const restrict source
,
46 shape_type
* const restrict shape
,
47 gfc_array_i4
* const restrict pad
,
48 shape_type
* const restrict order
)
50 /* r.* indicates the return array. */
51 index_type rcount
[GFC_MAX_DIMENSIONS
];
52 index_type rextent
[GFC_MAX_DIMENSIONS
];
53 index_type rstride
[GFC_MAX_DIMENSIONS
];
60 /* s.* indicates the source array. */
61 index_type scount
[GFC_MAX_DIMENSIONS
];
62 index_type sextent
[GFC_MAX_DIMENSIONS
];
63 index_type sstride
[GFC_MAX_DIMENSIONS
];
67 const GFC_INTEGER_4
*sptr
;
68 /* p.* indicates the pad array. */
69 index_type pcount
[GFC_MAX_DIMENSIONS
];
70 index_type pextent
[GFC_MAX_DIMENSIONS
];
71 index_type pstride
[GFC_MAX_DIMENSIONS
];
74 const GFC_INTEGER_4
*pptr
;
76 const GFC_INTEGER_4
*src
;
79 int sempty
, pempty
, shape_empty
;
80 index_type shape_data
[GFC_MAX_DIMENSIONS
];
82 rdim
= GFC_DESCRIPTOR_EXTENT(shape
,0);
83 if (rdim
!= GFC_DESCRIPTOR_RANK(ret
))
84 runtime_error("rank of return array incorrect in RESHAPE intrinsic");
88 for (n
= 0; n
< rdim
; n
++)
90 shape_data
[n
] = shape
->data
[n
* GFC_DESCRIPTOR_STRIDE(shape
,0)];
91 if (shape_data
[n
] <= 0)
98 if (ret
->data
== NULL
)
101 for (n
= 0; n
< rdim
; n
++)
105 GFC_DIMENSION_SET(ret
->dim
[n
], 0, rex
- 1, rs
);
110 ret
->data
= internal_malloc_size ( rs
* sizeof (GFC_INTEGER_4
));
111 ret
->dtype
= (source
->dtype
& ~GFC_DTYPE_RANK_MASK
) | rdim
;
119 pdim
= GFC_DESCRIPTOR_RANK (pad
);
122 for (n
= 0; n
< pdim
; n
++)
125 pstride
[n
] = GFC_DESCRIPTOR_STRIDE(pad
,n
);
126 pextent
[n
] = GFC_DESCRIPTOR_EXTENT(pad
,n
);
133 if (psize
== pstride
[n
])
148 if (unlikely (compile_options
.bounds_check
))
150 index_type ret_extent
, source_extent
;
153 for (n
= 0; n
< rdim
; n
++)
156 ret_extent
= GFC_DESCRIPTOR_EXTENT(ret
,n
);
157 if (ret_extent
!= shape_data
[n
])
158 runtime_error("Incorrect extent in return value of RESHAPE"
159 " intrinsic in dimension %ld: is %ld,"
160 " should be %ld", (long int) n
+1,
161 (long int) ret_extent
, (long int) shape_data
[n
]);
165 sdim
= GFC_DESCRIPTOR_RANK (source
);
166 for (n
= 0; n
< sdim
; n
++)
169 se
= GFC_DESCRIPTOR_EXTENT(source
,n
);
170 source_extent
*= se
> 0 ? se
: 0;
173 if (rs
> source_extent
&& (!pad
|| pempty
))
174 runtime_error("Incorrect size in SOURCE argument to RESHAPE"
175 " intrinsic: is %ld, should be %ld",
176 (long int) source_extent
, (long int) rs
);
180 int seen
[GFC_MAX_DIMENSIONS
];
183 for (n
= 0; n
< rdim
; n
++)
186 for (n
= 0; n
< rdim
; n
++)
188 v
= order
->data
[n
* GFC_DESCRIPTOR_STRIDE(order
,0)] - 1;
190 if (v
< 0 || v
>= rdim
)
191 runtime_error("Value %ld out of range in ORDER argument"
192 " to RESHAPE intrinsic", (long int) v
+ 1);
195 runtime_error("Duplicate value %ld in ORDER argument to"
196 " RESHAPE intrinsic", (long int) v
+ 1);
204 for (n
= 0; n
< rdim
; n
++)
207 dim
= order
->data
[n
* GFC_DESCRIPTOR_STRIDE(order
,0)] - 1;
212 rstride
[n
] = GFC_DESCRIPTOR_STRIDE(ret
,dim
);
213 rextent
[n
] = GFC_DESCRIPTOR_EXTENT(ret
,dim
);
217 if (rextent
[n
] != shape_data
[dim
])
218 runtime_error ("shape and target do not conform");
220 if (rsize
== rstride
[n
])
228 sdim
= GFC_DESCRIPTOR_RANK (source
);
231 for (n
= 0; n
< sdim
; n
++)
234 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(source
,n
);
235 sextent
[n
] = GFC_DESCRIPTOR_EXTENT(source
,n
);
242 if (ssize
== sstride
[n
])
248 if (rsize
!= 0 && ssize
!= 0 && psize
!= 0)
250 rsize
*= sizeof (GFC_INTEGER_4
);
251 ssize
*= sizeof (GFC_INTEGER_4
);
252 psize
*= sizeof (GFC_INTEGER_4
);
253 reshape_packed ((char *)ret
->data
, rsize
, (char *)source
->data
,
254 ssize
, pad
? (char *)pad
->data
: NULL
, psize
);
258 src
= sptr
= source
->data
;
259 rstride0
= rstride
[0];
260 sstride0
= sstride
[0];
262 if (sempty
&& pempty
)
267 /* Pretend we are using the pad array the first time around, too. */
271 for (dim
= 0; dim
< pdim
; dim
++)
273 scount
[dim
] = pcount
[dim
];
274 sextent
[dim
] = pextent
[dim
];
275 sstride
[dim
] = pstride
[dim
];
276 sstride0
= pstride
[0];
282 /* Select between the source and pad arrays. */
284 /* Advance to the next element. */
290 /* Advance to the next destination element. */
292 while (rcount
[n
] == rextent
[n
])
294 /* When we get to the end of a dimension, reset it and increment
295 the next dimension. */
297 /* We could precalculate these products, but this is a less
298 frequently used path so probably not worth it. */
299 rptr
-= rstride
[n
] * rextent
[n
];
303 /* Break out of the loop. */
313 /* Advance to the next source element. */
315 while (scount
[n
] == sextent
[n
])
317 /* When we get to the end of a dimension, reset it and increment
318 the next dimension. */
320 /* We could precalculate these products, but this is a less
321 frequently used path so probably not worth it. */
322 src
-= sstride
[n
] * sextent
[n
];
328 /* Switch to the pad array. */
331 for (dim
= 0; dim
< pdim
; dim
++)
333 scount
[dim
] = pcount
[dim
];
334 sextent
[dim
] = pextent
[dim
];
335 sstride
[dim
] = pstride
[dim
];
336 sstride0
= sstride
[0];
339 /* We now start again from the beginning of the pad array. */