1 /* Generic implementation of the EOSHIFT intrinsic
2 Copyright (C) 2002-2018 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 Ligbfortran 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 eoshift2 (gfc_array_char
*ret
, const gfc_array_char
*array
,
32 index_type shift
, const gfc_array_char
*bound
, int which
,
33 const char *filler
, index_type filler_len
)
35 /* r.* indicates the return array. */
36 index_type rstride
[GFC_MAX_DIMENSIONS
];
41 /* s.* indicates the source array. */
42 index_type sstride
[GFC_MAX_DIMENSIONS
];
47 /* b.* indicates the bound array. */
48 index_type bstride
[GFC_MAX_DIMENSIONS
];
52 index_type count
[GFC_MAX_DIMENSIONS
];
53 index_type extent
[GFC_MAX_DIMENSIONS
];
60 /* The compiler cannot figure out that these are set, initialize
61 them to avoid warnings. */
66 size
= GFC_DESCRIPTOR_SIZE (array
);
68 arraysize
= size0 ((array_t
*) array
);
70 if (ret
->base_addr
== NULL
)
75 GFC_DTYPE_COPY(ret
,array
);
77 /* xmallocarray allocates a single byte for zero size. */
78 ret
->base_addr
= xmallocarray (arraysize
, size
);
80 for (i
= 0; i
< GFC_DESCRIPTOR_RANK (array
); i
++)
84 ub
= GFC_DESCRIPTOR_EXTENT(array
,i
) - 1;
89 str
= GFC_DESCRIPTOR_EXTENT(ret
,i
-1)
90 * GFC_DESCRIPTOR_STRIDE(ret
,i
-1);
92 GFC_DIMENSION_SET(ret
->dim
[i
], 0, ub
, str
);
95 else if (unlikely (compile_options
.bounds_check
))
97 bounds_equal_extents ((array_t
*) ret
, (array_t
*) array
,
98 "return value", "EOSHIFT");
112 for (dim
= 0; dim
< GFC_DESCRIPTOR_RANK (array
); dim
++)
116 roffset
= GFC_DESCRIPTOR_STRIDE_BYTES(ret
,dim
);
119 soffset
= GFC_DESCRIPTOR_STRIDE_BYTES(array
,dim
);
122 len
= GFC_DESCRIPTOR_EXTENT(array
,dim
);
127 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,dim
);
128 rstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(ret
,dim
);
129 sstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(array
,dim
);
131 bstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(bound
,n
);
141 if (bound
&& bstride
[0] == 0)
144 dim
= GFC_DESCRIPTOR_RANK (array
);
145 rstride0
= rstride
[0];
146 sstride0
= sstride
[0];
147 bstride0
= bstride
[0];
148 rptr
= ret
->base_addr
;
149 sptr
= array
->base_addr
;
151 if ((shift
>= 0 ? shift
: -shift
) > len
)
165 bptr
= bound
->base_addr
;
171 /* Do the shift for this dimension. */
174 src
= &sptr
[shift
* soffset
];
180 dest
= &rptr
[-shift
* roffset
];
183 /* If the elements are contiguous, perform a single block move. */
184 if (soffset
== size
&& roffset
== size
)
186 size_t chunk
= size
* len
;
187 memcpy (dest
, src
, chunk
);
192 for (n
= 0; n
< len
; n
++)
194 memcpy (dest
, src
, size
);
212 memcpy (dest
, bptr
, size
);
221 memset (dest
, filler
[0], size
);
223 for (i
= 0; i
< size
; i
+= filler_len
)
224 memcpy (&dest
[i
], filler
, filler_len
);
229 /* Advance to the next section. */
235 while (count
[n
] == extent
[n
])
237 /* When we get to the end of a dimension, reset it and increment
238 the next dimension. */
240 /* We could precalculate these products, but this is a less
241 frequently used path so probably not worth it. */
242 rptr
-= rstride
[n
] * extent
[n
];
243 sptr
-= sstride
[n
] * extent
[n
];
244 bptr
-= bstride
[n
] * extent
[n
];
248 /* Break out of the loop. */
264 #define DEFINE_EOSHIFT(N) \
265 extern void eoshift2_##N (gfc_array_char *, const gfc_array_char *, \
266 const GFC_INTEGER_##N *, const gfc_array_char *, \
267 const GFC_INTEGER_##N *); \
268 export_proto(eoshift2_##N); \
271 eoshift2_##N (gfc_array_char *ret, const gfc_array_char *array, \
272 const GFC_INTEGER_##N *pshift, const gfc_array_char *pbound, \
273 const GFC_INTEGER_##N *pdim) \
275 eoshift2 (ret, array, *pshift, pbound, pdim ? *pdim : 1, \
279 extern void eoshift2_##N##_char (gfc_array_char *, GFC_INTEGER_4, \
280 const gfc_array_char *, \
281 const GFC_INTEGER_##N *, \
282 const gfc_array_char *, \
283 const GFC_INTEGER_##N *, \
284 GFC_INTEGER_4, GFC_INTEGER_4); \
285 export_proto(eoshift2_##N##_char); \
288 eoshift2_##N##_char (gfc_array_char *ret, \
289 GFC_INTEGER_4 ret_length __attribute__((unused)), \
290 const gfc_array_char *array, \
291 const GFC_INTEGER_##N *pshift, \
292 const gfc_array_char *pbound, \
293 const GFC_INTEGER_##N *pdim, \
294 GFC_INTEGER_4 array_length __attribute__((unused)), \
295 GFC_INTEGER_4 bound_length __attribute__((unused))) \
297 eoshift2 (ret, array, *pshift, pbound, pdim ? *pdim : 1, \
301 extern void eoshift2_##N##_char4 (gfc_array_char *, GFC_INTEGER_4, \
302 const gfc_array_char *, \
303 const GFC_INTEGER_##N *, \
304 const gfc_array_char *, \
305 const GFC_INTEGER_##N *, \
306 GFC_INTEGER_4, GFC_INTEGER_4); \
307 export_proto(eoshift2_##N##_char4); \
310 eoshift2_##N##_char4 (gfc_array_char *ret, \
311 GFC_INTEGER_4 ret_length __attribute__((unused)), \
312 const gfc_array_char *array, \
313 const GFC_INTEGER_##N *pshift, \
314 const gfc_array_char *pbound, \
315 const GFC_INTEGER_##N *pdim, \
316 GFC_INTEGER_4 array_length __attribute__((unused)), \
317 GFC_INTEGER_4 bound_length __attribute__((unused))) \
319 static const gfc_char4_t space = (unsigned char) ' '; \
320 eoshift2 (ret, array, *pshift, pbound, pdim ? *pdim : 1, \
321 (const char *) &space, \
322 sizeof (gfc_char4_t)); \
329 #ifdef HAVE_GFC_INTEGER_16