1 `/* Implementation of the CSHIFT intrinsic
2 Copyright (C) 2003-2017 Free Software Foundation, Inc.
3 Contributed by Feng Wang <wf_cs@yahoo.com>
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 `#if defined (HAVE_'atype_name`)
34 cshift1 (gfc_array_char * const restrict ret,
35 const gfc_array_char * const restrict array,
36 const 'atype` * const restrict h,
37 const 'atype_name` * const restrict pwhich)
39 /* r.* indicates the return array. */
40 index_type rstride[GFC_MAX_DIMENSIONS];
45 /* s.* indicates the source array. */
46 index_type sstride[GFC_MAX_DIMENSIONS];
51 /* h.* indicates the shift array. */
52 index_type hstride[GFC_MAX_DIMENSIONS];
54 const 'atype_name` *hptr;
56 index_type count[GFC_MAX_DIMENSIONS];
57 index_type extent[GFC_MAX_DIMENSIONS];
72 if (which < 0 || (which + 1) > GFC_DESCRIPTOR_RANK (array))
73 runtime_error ("Argument ''`DIM''` is out of range in call to ''`CSHIFT''`");
75 size = GFC_DESCRIPTOR_SIZE(array);
77 arraysize = size0 ((array_t *)array);
79 if (ret->base_addr == NULL)
83 ret->base_addr = xmallocarray (arraysize, size);
85 ret->dtype = array->dtype;
86 for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
90 ub = GFC_DESCRIPTOR_EXTENT(array,i) - 1;
95 str = GFC_DESCRIPTOR_EXTENT(ret,i-1) *
96 GFC_DESCRIPTOR_STRIDE(ret,i-1);
98 GFC_DIMENSION_SET(ret->dim[i], 0, ub, str);
101 else if (unlikely (compile_options.bounds_check))
103 bounds_equal_extents ((array_t *) ret, (array_t *) array,
104 "return value", "CSHIFT");
107 if (unlikely (compile_options.bounds_check))
109 bounds_reduced_extents ((array_t *) h, (array_t *) array, which,
110 "SHIFT argument", "CSHIFT");
116 /* See if we should dispatch to a helper function. */
118 type_size = GFC_DTYPE_TYPE_SIZE (array);
122 case GFC_DTYPE_LOGICAL_1:
123 case GFC_DTYPE_INTEGER_1:
124 case GFC_DTYPE_DERIVED_1:
125 cshift1_'atype_kind`_i1 ((gfc_array_i1 *)ret, (gfc_array_i1 *) array,
129 case GFC_DTYPE_LOGICAL_2:
130 case GFC_DTYPE_INTEGER_2:
131 cshift1_'atype_kind`_i2 ((gfc_array_i2 *)ret, (gfc_array_i2 *) array,
135 case GFC_DTYPE_LOGICAL_4:
136 case GFC_DTYPE_INTEGER_4:
137 cshift1_'atype_kind`_i4 ((gfc_array_i4 *)ret, (gfc_array_i4 *) array,
141 case GFC_DTYPE_LOGICAL_8:
142 case GFC_DTYPE_INTEGER_8:
143 cshift1_'atype_kind`_i8 ((gfc_array_i8 *)ret, (gfc_array_i8 *) array,
147 #if defined (HAVE_INTEGER_16)
148 case GFC_DTYPE_LOGICAL_16:
149 case GFC_DTYPE_INTEGER_16:
150 cshift1_'atype_kind`_i16 ((gfc_array_i16 *)ret, (gfc_array_i16 *) array,
155 case GFC_DTYPE_REAL_4:
156 cshift1_'atype_kind`_r4 ((gfc_array_r4 *)ret, (gfc_array_r4 *) array,
160 case GFC_DTYPE_REAL_8:
161 cshift1_'atype_kind`_r8 ((gfc_array_r8 *)ret, (gfc_array_r8 *) array,
165 #if defined (HAVE_REAL_10)
166 case GFC_DTYPE_REAL_10:
167 cshift1_'atype_kind`_r10 ((gfc_array_r10 *)ret, (gfc_array_r10 *) array,
172 #if defined (HAVE_REAL_16)
173 case GFC_DTYPE_REAL_16:
174 cshift1_'atype_kind`_r16 ((gfc_array_r16 *)ret, (gfc_array_r16 *) array,
179 case GFC_DTYPE_COMPLEX_4:
180 cshift1_'atype_kind`_c4 ((gfc_array_c4 *)ret, (gfc_array_c4 *) array,
184 case GFC_DTYPE_COMPLEX_8:
185 cshift1_'atype_kind`_c8 ((gfc_array_c8 *)ret, (gfc_array_c8 *) array,
189 #if defined (HAVE_COMPLEX_10)
190 case GFC_DTYPE_COMPLEX_10:
191 cshift1_'atype_kind`_c10 ((gfc_array_c10 *)ret, (gfc_array_c10 *) array,
196 #if defined (HAVE_COMPLEX_16)
197 case GFC_DTYPE_COMPLEX_16:
198 cshift1_'atype_kind`_c16 ((gfc_array_c16 *)ret, (gfc_array_c16 *) array,
212 /* Initialized for avoiding compiler warnings. */
217 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
221 roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
224 soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
227 len = GFC_DESCRIPTOR_EXTENT(array,dim);
232 extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
233 rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
234 sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
236 hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
247 dim = GFC_DESCRIPTOR_RANK (array);
248 rstride0 = rstride[0];
249 sstride0 = sstride[0];
250 hstride0 = hstride[0];
251 rptr = ret->base_addr;
252 sptr = array->base_addr;
257 /* Do the shift for this dimension. */
259 /* Normal case should be -len < sh < len; try to
260 avoid the expensive remainder operation if possible. */
263 if (unlikely (sh >= len || sh < 0))
270 src = &sptr[sh * soffset];
272 if (soffset == size && roffset == size)
274 size_t len1 = sh * size;
275 size_t len2 = (len - sh) * size;
276 memcpy (rptr, sptr + len1, len2);
277 memcpy (rptr + len2, sptr, len1);
281 for (n = 0; n < len - sh; n++)
283 memcpy (dest, src, size);
287 for (src = sptr, n = 0; n < sh; n++)
289 memcpy (dest, src, size);
295 /* Advance to the next section. */
301 while (count[n] == extent[n])
303 /* When we get to the end of a dimension, reset it and increment
304 the next dimension. */
306 /* We could precalculate these products, but this is a less
307 frequently used path so probably not worth it. */
308 rptr -= rstride[n] * extent[n];
309 sptr -= sstride[n] * extent[n];
310 hptr -= hstride[n] * extent[n];
314 /* Break out of the loop. */
329 void cshift1_'atype_kind` (gfc_array_char * const restrict,
330 const gfc_array_char * const restrict,
331 const 'atype` * const restrict,
332 const 'atype_name` * const restrict);
333 export_proto(cshift1_'atype_kind`);
336 cshift1_'atype_kind` (gfc_array_char * const restrict ret,
337 const gfc_array_char * const restrict array,
338 const 'atype` * const restrict h,
339 const 'atype_name` * const restrict pwhich)
341 cshift1 (ret, array, h, pwhich);
345 void cshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
347 const gfc_array_char * const restrict array,
348 const 'atype` * const restrict h,
349 const 'atype_name` * const restrict pwhich,
351 export_proto(cshift1_'atype_kind`_char);
354 cshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
355 GFC_INTEGER_4 ret_length __attribute__((unused)),
356 const gfc_array_char * const restrict array,
357 const 'atype` * const restrict h,
358 const 'atype_name` * const restrict pwhich,
359 GFC_INTEGER_4 array_length __attribute__((unused)))
361 cshift1 (ret, array, h, pwhich);
365 void cshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
367 const gfc_array_char * const restrict array,
368 const 'atype` * const restrict h,
369 const 'atype_name` * const restrict pwhich,
371 export_proto(cshift1_'atype_kind`_char4);
374 cshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
375 GFC_INTEGER_4 ret_length __attribute__((unused)),
376 const gfc_array_char * const restrict array,
377 const 'atype` * const restrict h,
378 const 'atype_name` * const restrict pwhich,
379 GFC_INTEGER_4 array_length __attribute__((unused)))
381 cshift1 (ret, array, h, pwhich);