1 `/* Implementation of the EOSHIFT intrinsic
2 Copyright (C) 2002-2019 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran 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_'atype_name`)
34 eoshift3 (gfc_array_char * const restrict ret,
35 const gfc_array_char * const restrict array,
36 const 'atype` * const restrict h,
37 const gfc_array_char * const restrict bound,
38 const 'atype_name` * const restrict pwhich,
39 const char * filler, index_type filler_len)
41 /* r.* indicates the return array. */
42 index_type rstride[GFC_MAX_DIMENSIONS];
47 /* s.* indicates the source array. */
48 index_type sstride[GFC_MAX_DIMENSIONS];
53 /* h.* indicates the shift array. */
54 index_type hstride[GFC_MAX_DIMENSIONS];
56 const 'atype_name` *hptr;
57 /* b.* indicates the bound array. */
58 index_type bstride[GFC_MAX_DIMENSIONS];
62 index_type count[GFC_MAX_DIMENSIONS];
63 index_type extent[GFC_MAX_DIMENSIONS];
73 /* The compiler cannot figure out that these are set, initialize
74 them to avoid warnings. */
79 arraysize = size0 ((array_t *) array);
80 size = GFC_DESCRIPTOR_SIZE(array);
87 if (ret->base_addr == NULL)
89 ret->base_addr = xmallocarray (arraysize, size);
91 GFC_DTYPE_COPY(ret,array);
92 for (index_type i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
96 ub = GFC_DESCRIPTOR_EXTENT(array,i) - 1;
101 str = GFC_DESCRIPTOR_EXTENT(ret,i-1)
102 * GFC_DESCRIPTOR_STRIDE(ret,i-1);
104 GFC_DIMENSION_SET(ret->dim[i], 0, ub, str);
107 /* xmallocarray allocates a single byte for zero size. */
108 ret->base_addr = xmallocarray (arraysize, size);
111 else if (unlikely (compile_options.bounds_check))
113 bounds_equal_extents ((array_t *) ret, (array_t *) array,
114 "return value", "EOSHIFT");
117 if (unlikely (compile_options.bounds_check))
119 bounds_reduced_extents ((array_t *) h, (array_t *) array, which,
120 "SHIFT argument", "EOSHIFT");
129 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
133 roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
136 soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
139 len = GFC_DESCRIPTOR_EXTENT(array,dim);
144 extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
145 rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
146 sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
148 hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
150 bstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(bound,n);
162 if (bound && bstride[0] == 0)
165 dim = GFC_DESCRIPTOR_RANK (array);
166 rstride0 = rstride[0];
167 sstride0 = sstride[0];
168 hstride0 = hstride[0];
169 bstride0 = bstride[0];
170 rptr = ret->base_addr;
171 sptr = array->base_addr;
174 bptr = bound->base_addr;
180 /* Do the shift for this dimension. */
182 if (( sh >= 0 ? sh : -sh ) > len)
188 delta = (sh >= 0) ? sh: -sh;
192 src = &sptr[delta * soffset];
198 dest = &rptr[delta * roffset];
201 /* If the elements are contiguous, perform a single block move. */
202 if (soffset == size && roffset == size)
204 size_t chunk = size * (len - delta);
205 memcpy (dest, src, chunk);
210 for (n = 0; n < len - delta; n++)
212 memcpy (dest, src, size);
225 memcpy (dest, bptr, size);
234 memset (dest, filler[0], size);
236 for (i = 0; i < size; i += filler_len)
237 memcpy (&dest[i], filler, filler_len);
242 /* Advance to the next section. */
249 while (count[n] == extent[n])
251 /* When we get to the end of a dimension, reset it and increment
252 the next dimension. */
254 /* We could precalculate these products, but this is a less
255 frequently used path so probably not worth it. */
256 rptr -= rstride[n] * extent[n];
257 sptr -= sstride[n] * extent[n];
258 hptr -= hstride[n] * extent[n];
259 bptr -= bstride[n] * extent[n];
263 /* Break out of the loop. */
279 extern void eoshift3_'atype_kind` (gfc_array_char * const restrict,
280 const gfc_array_char * const restrict,
281 const 'atype` * const restrict,
282 const gfc_array_char * const restrict,
283 const 'atype_name` *);
284 export_proto(eoshift3_'atype_kind`);
287 eoshift3_'atype_kind` (gfc_array_char * const restrict ret,
288 const gfc_array_char * const restrict array,
289 const 'atype` * const restrict h,
290 const gfc_array_char * const restrict bound,
291 const 'atype_name` * const restrict pwhich)
293 eoshift3 (ret, array, h, bound, pwhich, "\0", 1);
297 extern void eoshift3_'atype_kind`_char (gfc_array_char * const restrict,
299 const gfc_array_char * const restrict,
300 const 'atype` * const restrict,
301 const gfc_array_char * const restrict,
302 const 'atype_name` * const restrict,
303 GFC_INTEGER_4, GFC_INTEGER_4);
304 export_proto(eoshift3_'atype_kind`_char);
307 eoshift3_'atype_kind`_char (gfc_array_char * const restrict ret,
308 GFC_INTEGER_4 ret_length __attribute__((unused)),
309 const gfc_array_char * const restrict array,
310 const 'atype` * const restrict h,
311 const gfc_array_char * const restrict bound,
312 const 'atype_name` * const restrict pwhich,
313 GFC_INTEGER_4 array_length __attribute__((unused)),
314 GFC_INTEGER_4 bound_length __attribute__((unused)))
316 eoshift3 (ret, array, h, bound, pwhich, " ", 1);
320 extern void eoshift3_'atype_kind`_char4 (gfc_array_char * const restrict,
322 const gfc_array_char * const restrict,
323 const 'atype` * const restrict,
324 const gfc_array_char * const restrict,
325 const 'atype_name` * const restrict,
326 GFC_INTEGER_4, GFC_INTEGER_4);
327 export_proto(eoshift3_'atype_kind`_char4);
330 eoshift3_'atype_kind`_char4 (gfc_array_char * const restrict ret,
331 GFC_INTEGER_4 ret_length __attribute__((unused)),
332 const gfc_array_char * const restrict array,
333 const 'atype` * const restrict h,
334 const gfc_array_char * const restrict bound,
335 const 'atype_name` * const restrict pwhich,
336 GFC_INTEGER_4 array_length __attribute__((unused)),
337 GFC_INTEGER_4 bound_length __attribute__((unused)))
339 static const gfc_char4_t space = (unsigned char) ''` ''`;
340 eoshift3 (ret, array, h, bound, pwhich,
341 (const char *) &space, sizeof (gfc_char4_t));