1 `/* Implementation of the CSHIFT intrinsic
2 Copyright (C) 2003-2015 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"
33 `#if defined (HAVE_'atype_name`)
36 cshift1 (gfc_array_char * const restrict ret,
37 const gfc_array_char * const restrict array,
38 const 'atype` * const restrict h,
39 const 'atype_name` * const restrict pwhich)
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;
58 index_type count[GFC_MAX_DIMENSIONS];
59 index_type extent[GFC_MAX_DIMENSIONS];
73 if (which < 0 || (which + 1) > GFC_DESCRIPTOR_RANK (array))
74 runtime_error ("Argument ''`DIM''` is out of range in call to ''`CSHIFT''`");
76 size = GFC_DESCRIPTOR_SIZE(array);
78 arraysize = size0 ((array_t *)array);
80 if (ret->base_addr == NULL)
84 ret->base_addr = xmallocarray (arraysize, size);
86 ret->dtype = array->dtype;
87 for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
91 ub = GFC_DESCRIPTOR_EXTENT(array,i) - 1;
96 str = GFC_DESCRIPTOR_EXTENT(ret,i-1) *
97 GFC_DESCRIPTOR_STRIDE(ret,i-1);
99 GFC_DIMENSION_SET(ret->dim[i], 0, ub, str);
102 else if (unlikely (compile_options.bounds_check))
104 bounds_equal_extents ((array_t *) ret, (array_t *) array,
105 "return value", "CSHIFT");
108 if (unlikely (compile_options.bounds_check))
110 bounds_reduced_extents ((array_t *) h, (array_t *) array, which,
111 "SHIFT argument", "CSHIFT");
121 /* Initialized for avoiding compiler warnings. */
126 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
130 roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
133 soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
136 len = GFC_DESCRIPTOR_EXTENT(array,dim);
141 extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
142 rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
143 sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
145 hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
156 dim = GFC_DESCRIPTOR_RANK (array);
157 rstride0 = rstride[0];
158 sstride0 = sstride[0];
159 hstride0 = hstride[0];
160 rptr = ret->base_addr;
161 sptr = array->base_addr;
166 /* Do the shift for this dimension. */
168 sh = (div (sh, len)).rem;
172 src = &sptr[sh * soffset];
175 for (n = 0; n < len; n++)
177 memcpy (dest, src, size);
179 if (n == len - sh - 1)
185 /* Advance to the next section. */
191 while (count[n] == extent[n])
193 /* When we get to the end of a dimension, reset it and increment
194 the next dimension. */
196 /* We could precalculate these products, but this is a less
197 frequently used path so probably not worth it. */
198 rptr -= rstride[n] * extent[n];
199 sptr -= sstride[n] * extent[n];
200 hptr -= hstride[n] * extent[n];
204 /* Break out of the loop. */
219 void cshift1_'atype_kind` (gfc_array_char * const restrict,
220 const gfc_array_char * const restrict,
221 const 'atype` * const restrict,
222 const 'atype_name` * const restrict);
223 export_proto(cshift1_'atype_kind`);
226 cshift1_'atype_kind` (gfc_array_char * const restrict ret,
227 const gfc_array_char * const restrict array,
228 const 'atype` * const restrict h,
229 const 'atype_name` * const restrict pwhich)
231 cshift1 (ret, array, h, pwhich);
235 void cshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
237 const gfc_array_char * const restrict array,
238 const 'atype` * const restrict h,
239 const 'atype_name` * const restrict pwhich,
241 export_proto(cshift1_'atype_kind`_char);
244 cshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
245 GFC_INTEGER_4 ret_length __attribute__((unused)),
246 const gfc_array_char * const restrict array,
247 const 'atype` * const restrict h,
248 const 'atype_name` * const restrict pwhich,
249 GFC_INTEGER_4 array_length __attribute__((unused)))
251 cshift1 (ret, array, h, pwhich);
255 void cshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
257 const gfc_array_char * const restrict array,
258 const 'atype` * const restrict h,
259 const 'atype_name` * const restrict pwhich,
261 export_proto(cshift1_'atype_kind`_char4);
264 cshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
265 GFC_INTEGER_4 ret_length __attribute__((unused)),
266 const gfc_array_char * const restrict array,
267 const 'atype` * const restrict h,
268 const 'atype_name` * const restrict pwhich,
269 GFC_INTEGER_4 array_length __attribute__((unused)))
271 cshift1 (ret, array, h, pwhich);