]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/m4/cshift1.m4
Update copyright years.
[thirdparty/gcc.git] / libgfortran / m4 / cshift1.m4
CommitLineData
6de9cd9a 1`/* Implementation of the CSHIFT intrinsic
a945c346 2 Copyright (C) 2003-2024 Free Software Foundation, Inc.
6de9cd9a
DN
3 Contributed by Feng Wang <wf_cs@yahoo.com>
4
21d1335b 5This file is part of the GNU Fortran runtime library (libgfortran).
6de9cd9a
DN
6
7Libgfortran is free software; you can redistribute it and/or
57dea9f6 8modify it under the terms of the GNU General Public
6de9cd9a 9License as published by the Free Software Foundation; either
748086b7 10version 3 of the License, or (at your option) any later version.
57dea9f6
TM
11
12Ligbfortran is distributed in the hope that it will be useful,
6de9cd9a
DN
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57dea9f6 15GNU General Public License for more details.
6de9cd9a 16
748086b7
JJ
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
6de9cd9a 25
36ae8a61 26#include "libgfortran.h"
36ae8a61
FXC
27#include <string.h>'
28
c9e66eda 29include(iparm.m4)dnl
6de9cd9a 30
adea5e16 31`#if defined (HAVE_'atype_name`)
644cb69f 32
7823229b 33static void
64acfd99
JB
34cshift1 (gfc_array_char * const restrict ret,
35 const gfc_array_char * const restrict array,
adea5e16 36 const 'atype` * const restrict h,
dfb55fdc 37 const 'atype_name` * const restrict pwhich)
6de9cd9a
DN
38{
39 /* r.* indicates the return array. */
e33e218b 40 index_type rstride[GFC_MAX_DIMENSIONS];
6de9cd9a
DN
41 index_type rstride0;
42 index_type roffset;
43 char *rptr;
44 char *dest;
45 /* s.* indicates the source array. */
e33e218b 46 index_type sstride[GFC_MAX_DIMENSIONS];
6de9cd9a
DN
47 index_type sstride0;
48 index_type soffset;
49 const char *sptr;
50 const char *src;
7d7b8bfe 51 /* h.* indicates the shift array. */
e33e218b 52 index_type hstride[GFC_MAX_DIMENSIONS];
6de9cd9a 53 index_type hstride0;
adea5e16 54 const 'atype_name` *hptr;
6de9cd9a 55
e33e218b
TK
56 index_type count[GFC_MAX_DIMENSIONS];
57 index_type extent[GFC_MAX_DIMENSIONS];
6de9cd9a 58 index_type dim;
6de9cd9a
DN
59 index_type len;
60 index_type n;
61 int which;
adea5e16 62 'atype_name` sh;
c44109aa 63 index_type arraysize;
dfb55fdc 64 index_type size;
e56e3fda
TK
65 index_type type_size;
66
6de9cd9a
DN
67 if (pwhich)
68 which = *pwhich - 1;
69 else
70 which = 0;
e56e3fda 71
6de9cd9a 72 if (which < 0 || (which + 1) > GFC_DESCRIPTOR_RANK (array))
adea5e16 73 runtime_error ("Argument ''`DIM''` is out of range in call to ''`CSHIFT''`");
6de9cd9a 74
dfb55fdc
TK
75 size = GFC_DESCRIPTOR_SIZE(array);
76
c44109aa
TK
77 arraysize = size0 ((array_t *)array);
78
21d1335b 79 if (ret->base_addr == NULL)
0e6d033b 80 {
92e6f3a4 81 ret->base_addr = xmallocarray (arraysize, size);
efd4dc1a 82 ret->offset = 0;
fa3c4d47 83 GFC_DTYPE_COPY(ret,array);
7a157266 84 for (index_type i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
0e6d033b 85 {
dfb55fdc
TK
86 index_type ub, str;
87
88 ub = GFC_DESCRIPTOR_EXTENT(array,i) - 1;
0e6d033b
TK
89
90 if (i == 0)
dfb55fdc 91 str = 1;
0e6d033b 92 else
dfb55fdc
TK
93 str = GFC_DESCRIPTOR_EXTENT(ret,i-1) *
94 GFC_DESCRIPTOR_STRIDE(ret,i-1);
95
96 GFC_DIMENSION_SET(ret->dim[i], 0, ub, str);
0e6d033b
TK
97 }
98 }
16bff921
TK
99 else if (unlikely (compile_options.bounds_check))
100 {
101 bounds_equal_extents ((array_t *) ret, (array_t *) array,
102 "return value", "CSHIFT");
103 }
104
105 if (unlikely (compile_options.bounds_check))
106 {
107 bounds_reduced_extents ((array_t *) h, (array_t *) array, which,
108 "SHIFT argument", "CSHIFT");
109 }
0e6d033b 110
c44109aa
TK
111 if (arraysize == 0)
112 return;
113
e56e3fda
TK
114 /* See if we should dispatch to a helper function. */
115
116 type_size = GFC_DTYPE_TYPE_SIZE (array);
117
118 switch (type_size)
119 {
120 case GFC_DTYPE_LOGICAL_1:
121 case GFC_DTYPE_INTEGER_1:
e56e3fda
TK
122 cshift1_'atype_kind`_i1 ((gfc_array_i1 *)ret, (gfc_array_i1 *) array,
123 h, pwhich);
124 return;
125
126 case GFC_DTYPE_LOGICAL_2:
127 case GFC_DTYPE_INTEGER_2:
128 cshift1_'atype_kind`_i2 ((gfc_array_i2 *)ret, (gfc_array_i2 *) array,
129 h, pwhich);
130 return;
131
132 case GFC_DTYPE_LOGICAL_4:
133 case GFC_DTYPE_INTEGER_4:
134 cshift1_'atype_kind`_i4 ((gfc_array_i4 *)ret, (gfc_array_i4 *) array,
135 h, pwhich);
136 return;
137
138 case GFC_DTYPE_LOGICAL_8:
139 case GFC_DTYPE_INTEGER_8:
140 cshift1_'atype_kind`_i8 ((gfc_array_i8 *)ret, (gfc_array_i8 *) array,
141 h, pwhich);
142 return;
143
144#if defined (HAVE_INTEGER_16)
145 case GFC_DTYPE_LOGICAL_16:
146 case GFC_DTYPE_INTEGER_16:
147 cshift1_'atype_kind`_i16 ((gfc_array_i16 *)ret, (gfc_array_i16 *) array,
148 h, pwhich);
149 return;
150#endif
151
152 case GFC_DTYPE_REAL_4:
153 cshift1_'atype_kind`_r4 ((gfc_array_r4 *)ret, (gfc_array_r4 *) array,
154 h, pwhich);
155 return;
156
157 case GFC_DTYPE_REAL_8:
158 cshift1_'atype_kind`_r8 ((gfc_array_r8 *)ret, (gfc_array_r8 *) array,
159 h, pwhich);
160 return;
161
162#if defined (HAVE_REAL_10)
163 case GFC_DTYPE_REAL_10:
164 cshift1_'atype_kind`_r10 ((gfc_array_r10 *)ret, (gfc_array_r10 *) array,
165 h, pwhich);
166 return;
167#endif
168
169#if defined (HAVE_REAL_16)
170 case GFC_DTYPE_REAL_16:
171 cshift1_'atype_kind`_r16 ((gfc_array_r16 *)ret, (gfc_array_r16 *) array,
172 h, pwhich);
173 return;
174#endif
175
176 case GFC_DTYPE_COMPLEX_4:
177 cshift1_'atype_kind`_c4 ((gfc_array_c4 *)ret, (gfc_array_c4 *) array,
178 h, pwhich);
179 return;
180
181 case GFC_DTYPE_COMPLEX_8:
182 cshift1_'atype_kind`_c8 ((gfc_array_c8 *)ret, (gfc_array_c8 *) array,
183 h, pwhich);
184 return;
185
186#if defined (HAVE_COMPLEX_10)
187 case GFC_DTYPE_COMPLEX_10:
188 cshift1_'atype_kind`_c10 ((gfc_array_c10 *)ret, (gfc_array_c10 *) array,
189 h, pwhich);
190 return;
191#endif
192
193#if defined (HAVE_COMPLEX_16)
194 case GFC_DTYPE_COMPLEX_16:
195 cshift1_'atype_kind`_c16 ((gfc_array_c16 *)ret, (gfc_array_c16 *) array,
196 h, pwhich);
197 return;
198#endif
199
200 default:
201 break;
202
203 }
204
6de9cd9a
DN
205 extent[0] = 1;
206 count[0] = 0;
6de9cd9a
DN
207 n = 0;
208
7d7b8bfe 209 /* Initialized for avoiding compiler warnings. */
6de9cd9a
DN
210 roffset = size;
211 soffset = size;
212 len = 0;
213
214 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
215 {
216 if (dim == which)
217 {
dfb55fdc 218 roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
6de9cd9a
DN
219 if (roffset == 0)
220 roffset = size;
dfb55fdc 221 soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
6de9cd9a
DN
222 if (soffset == 0)
223 soffset = size;
dfb55fdc 224 len = GFC_DESCRIPTOR_EXTENT(array,dim);
6de9cd9a
DN
225 }
226 else
227 {
228 count[n] = 0;
dfb55fdc
TK
229 extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
230 rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
231 sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
6de9cd9a 232
dfb55fdc 233 hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
6de9cd9a
DN
234 n++;
235 }
236 }
237 if (sstride[0] == 0)
238 sstride[0] = size;
239 if (rstride[0] == 0)
240 rstride[0] = size;
241 if (hstride[0] == 0)
242 hstride[0] = 1;
243
244 dim = GFC_DESCRIPTOR_RANK (array);
245 rstride0 = rstride[0];
246 sstride0 = sstride[0];
247 hstride0 = hstride[0];
21d1335b
TB
248 rptr = ret->base_addr;
249 sptr = array->base_addr;
250 hptr = h->base_addr;
6de9cd9a
DN
251
252 while (rptr)
253 {
7d7b8bfe 254 /* Do the shift for this dimension. */
6de9cd9a 255 sh = *hptr;
e56e3fda
TK
256 /* Normal case should be -len < sh < len; try to
257 avoid the expensive remainder operation if possible. */
6de9cd9a
DN
258 if (sh < 0)
259 sh += len;
e56e3fda
TK
260 if (unlikely (sh >= len || sh < 0))
261 {
262 sh = sh % len;
263 if (sh < 0)
264 sh += len;
265 }
6de9cd9a
DN
266
267 src = &sptr[sh * soffset];
268 dest = rptr;
e56e3fda
TK
269 if (soffset == size && roffset == size)
270 {
271 size_t len1 = sh * size;
272 size_t len2 = (len - sh) * size;
273 memcpy (rptr, sptr + len1, len2);
274 memcpy (rptr + len2, sptr, len1);
275 }
276 else
6de9cd9a 277 {
e56e3fda
TK
278 for (n = 0; n < len - sh; n++)
279 {
280 memcpy (dest, src, size);
281 dest += roffset;
282 src += soffset;
283 }
284 for (src = sptr, n = 0; n < sh; n++)
285 {
286 memcpy (dest, src, size);
287 dest += roffset;
288 src += soffset;
289 }
290 }
6de9cd9a
DN
291
292 /* Advance to the next section. */
293 rptr += rstride0;
294 sptr += sstride0;
295 hptr += hstride0;
296 count[0]++;
297 n = 0;
298 while (count[n] == extent[n])
299 {
300 /* When we get to the end of a dimension, reset it and increment
301 the next dimension. */
302 count[n] = 0;
303 /* We could precalculate these products, but this is a less
8b6dba81 304 frequently used path so probably not worth it. */
6de9cd9a
DN
305 rptr -= rstride[n] * extent[n];
306 sptr -= sstride[n] * extent[n];
307 hptr -= hstride[n] * extent[n];
308 n++;
309 if (n >= dim - 1)
310 {
311 /* Break out of the loop. */
312 rptr = NULL;
313 break;
314 }
315 else
316 {
317 count[n]++;
318 rptr += rstride[n];
319 sptr += sstride[n];
320 hptr += hstride[n];
321 }
322 }
323 }
324}
7823229b 325
adea5e16 326void cshift1_'atype_kind` (gfc_array_char * const restrict,
64acfd99 327 const gfc_array_char * const restrict,
adea5e16
TK
328 const 'atype` * const restrict,
329 const 'atype_name` * const restrict);
330export_proto(cshift1_'atype_kind`);
7823229b
RS
331
332void
adea5e16 333cshift1_'atype_kind` (gfc_array_char * const restrict ret,
64acfd99 334 const gfc_array_char * const restrict array,
adea5e16
TK
335 const 'atype` * const restrict h,
336 const 'atype_name` * const restrict pwhich)
7823229b 337{
dfb55fdc 338 cshift1 (ret, array, h, pwhich);
7823229b
RS
339}
340
691da334 341
adea5e16 342void cshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
64acfd99
JB
343 GFC_INTEGER_4,
344 const gfc_array_char * const restrict array,
adea5e16
TK
345 const 'atype` * const restrict h,
346 const 'atype_name` * const restrict pwhich,
64acfd99 347 GFC_INTEGER_4);
adea5e16 348export_proto(cshift1_'atype_kind`_char);
7823229b
RS
349
350void
adea5e16 351cshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
64acfd99
JB
352 GFC_INTEGER_4 ret_length __attribute__((unused)),
353 const gfc_array_char * const restrict array,
adea5e16
TK
354 const 'atype` * const restrict h,
355 const 'atype_name` * const restrict pwhich,
dfb55fdc 356 GFC_INTEGER_4 array_length __attribute__((unused)))
7823229b 357{
dfb55fdc 358 cshift1 (ret, array, h, pwhich);
7823229b 359}
644cb69f 360
691da334
FXC
361
362void cshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
363 GFC_INTEGER_4,
364 const gfc_array_char * const restrict array,
365 const 'atype` * const restrict h,
366 const 'atype_name` * const restrict pwhich,
367 GFC_INTEGER_4);
368export_proto(cshift1_'atype_kind`_char4);
369
370void
371cshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
372 GFC_INTEGER_4 ret_length __attribute__((unused)),
373 const gfc_array_char * const restrict array,
374 const 'atype` * const restrict h,
375 const 'atype_name` * const restrict pwhich,
dfb55fdc 376 GFC_INTEGER_4 array_length __attribute__((unused)))
691da334 377{
dfb55fdc 378 cshift1 (ret, array, h, pwhich);
691da334
FXC
379}
380
adea5e16 381#endif'