]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/m4/eoshift3.m4
2019-06-13 Richard Biener <rguenther@suse.de>
[thirdparty/gcc.git] / libgfortran / m4 / eoshift3.m4
CommitLineData
4ee9c684 1`/* Implementation of the EOSHIFT intrinsic
fbd26352 2 Copyright (C) 2002-2019 Free Software Foundation, Inc.
4ee9c684 3 Contributed by Paul Brook <paul@nowt.org>
4
553877d9 5This file is part of the GNU Fortran runtime library (libgfortran).
4ee9c684 6
b417ea8c 7Libgfortran is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public
4ee9c684 9License as published by the Free Software Foundation; either
6bc9506f 10version 3 of the License, or (at your option) any later version.
b417ea8c 11
12Libgfortran is distributed in the hope that it will be useful,
4ee9c684 13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
b417ea8c 15GNU General Public License for more details.
4ee9c684 16
6bc9506f 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/>. */
4ee9c684 25
41f2d5e8 26#include "libgfortran.h"
41f2d5e8 27#include <string.h>'
28
cdafa1f6 29include(iparm.m4)dnl
4ee9c684 30
0a6b5f6b 31`#if defined (HAVE_'atype_name`)
920e54ef 32
1a9a4a12 33static void
b4cafd67 34eoshift3 (gfc_array_char * const restrict ret,
35 const gfc_array_char * const restrict array,
0a6b5f6b 36 const 'atype` * const restrict h,
b4cafd67 37 const gfc_array_char * const restrict bound,
0a6b5f6b 38 const 'atype_name` * const restrict pwhich,
827aef63 39 const char * filler, index_type filler_len)
4ee9c684 40{
41 /* r.* indicates the return array. */
9130521e 42 index_type rstride[GFC_MAX_DIMENSIONS];
4ee9c684 43 index_type rstride0;
44 index_type roffset;
45 char *rptr;
9d259edf 46 char * restrict dest;
4ee9c684 47 /* s.* indicates the source array. */
9130521e 48 index_type sstride[GFC_MAX_DIMENSIONS];
4ee9c684 49 index_type sstride0;
50 index_type soffset;
51 const char *sptr;
52 const char *src;
0a6b5f6b 53 /* h.* indicates the shift array. */
9130521e 54 index_type hstride[GFC_MAX_DIMENSIONS];
4ee9c684 55 index_type hstride0;
0a6b5f6b 56 const 'atype_name` *hptr;
4ee9c684 57 /* b.* indicates the bound array. */
9130521e 58 index_type bstride[GFC_MAX_DIMENSIONS];
4ee9c684 59 index_type bstride0;
60 const char *bptr;
61
9130521e 62 index_type count[GFC_MAX_DIMENSIONS];
63 index_type extent[GFC_MAX_DIMENSIONS];
4ee9c684 64 index_type dim;
4ee9c684 65 index_type len;
66 index_type n;
827aef63 67 index_type size;
5d04d450 68 index_type arraysize;
4ee9c684 69 int which;
0a6b5f6b 70 'atype_name` sh;
71 'atype_name` delta;
4ee9c684 72
7b49b59f 73 /* The compiler cannot figure out that these are set, initialize
74 them to avoid warnings. */
75 len = 0;
76 soffset = 0;
77 roffset = 0;
78
5d04d450 79 arraysize = size0 ((array_t *) array);
827aef63 80 size = GFC_DESCRIPTOR_SIZE(array);
81
4ee9c684 82 if (pwhich)
83 which = *pwhich - 1;
84 else
85 which = 0;
86
553877d9 87 if (ret->base_addr == NULL)
71a8a4b3 88 {
af1e9051 89 ret->base_addr = xmallocarray (arraysize, size);
93830de1 90 ret->offset = 0;
da8dff89 91 GFC_DTYPE_COPY(ret,array);
df52c9a4 92 for (index_type i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
71a8a4b3 93 {
827aef63 94 index_type ub, str;
95
96 ub = GFC_DESCRIPTOR_EXTENT(array,i) - 1;
71a8a4b3 97
98 if (i == 0)
827aef63 99 str = 1;
71a8a4b3 100 else
827aef63 101 str = GFC_DESCRIPTOR_EXTENT(ret,i-1)
102 * GFC_DESCRIPTOR_STRIDE(ret,i-1);
103
104 GFC_DIMENSION_SET(ret->dim[i], 0, ub, str);
105
71a8a4b3 106 }
af1e9051 107 /* xmallocarray allocates a single byte for zero size. */
108 ret->base_addr = xmallocarray (arraysize, size);
5d04d450 109
71a8a4b3 110 }
5d04d450 111 else if (unlikely (compile_options.bounds_check))
112 {
113 bounds_equal_extents ((array_t *) ret, (array_t *) array,
114 "return value", "EOSHIFT");
115 }
116
117 if (unlikely (compile_options.bounds_check))
74a175c1 118 {
5d04d450 119 bounds_reduced_extents ((array_t *) h, (array_t *) array, which,
120 "SHIFT argument", "EOSHIFT");
74a175c1 121 }
71a8a4b3 122
5d04d450 123 if (arraysize == 0)
124 return;
4ee9c684 125
126 extent[0] = 1;
127 count[0] = 0;
4ee9c684 128 n = 0;
129 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
130 {
131 if (dim == which)
132 {
827aef63 133 roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
4ee9c684 134 if (roffset == 0)
135 roffset = size;
827aef63 136 soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
4ee9c684 137 if (soffset == 0)
138 soffset = size;
827aef63 139 len = GFC_DESCRIPTOR_EXTENT(array,dim);
4ee9c684 140 }
141 else
142 {
143 count[n] = 0;
827aef63 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);
4ee9c684 147
827aef63 148 hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
4ee9c684 149 if (bound)
827aef63 150 bstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(bound,n);
4ee9c684 151 else
152 bstride[n] = 0;
153 n++;
154 }
155 }
156 if (sstride[0] == 0)
157 sstride[0] = size;
158 if (rstride[0] == 0)
159 rstride[0] = size;
160 if (hstride[0] == 0)
161 hstride[0] = 1;
162 if (bound && bstride[0] == 0)
163 bstride[0] = size;
164
165 dim = GFC_DESCRIPTOR_RANK (array);
166 rstride0 = rstride[0];
167 sstride0 = sstride[0];
168 hstride0 = hstride[0];
169 bstride0 = bstride[0];
553877d9 170 rptr = ret->base_addr;
171 sptr = array->base_addr;
172 hptr = h->base_addr;
4ee9c684 173 if (bound)
553877d9 174 bptr = bound->base_addr;
4ee9c684 175 else
1a9a4a12 176 bptr = NULL;
4ee9c684 177
178 while (rptr)
179 {
0a6b5f6b 180 /* Do the shift for this dimension. */
4ee9c684 181 sh = *hptr;
4eef4aad 182 if (( sh >= 0 ? sh : -sh ) > len)
183 {
184 delta = len;
185 sh = len;
186 }
187 else
188 delta = (sh >= 0) ? sh: -sh;
189
4ee9c684 190 if (sh > 0)
191 {
192 src = &sptr[delta * soffset];
193 dest = rptr;
194 }
195 else
196 {
197 src = sptr;
198 dest = &rptr[delta * roffset];
199 }
829231a6 200
201 /* If the elements are contiguous, perform a single block move. */
202 if (soffset == size && roffset == size)
203 {
204 size_t chunk = size * (len - delta);
205 memcpy (dest, src, chunk);
206 dest += chunk;
207 }
208 else
209 {
210 for (n = 0; n < len - delta; n++)
211 {
212 memcpy (dest, src, size);
213 dest += roffset;
214 src += soffset;
215 }
216 }
217
4ee9c684 218 if (sh < 0)
219 dest = rptr;
220 n = delta;
221
1a9a4a12 222 if (bptr)
223 while (n--)
224 {
225 memcpy (dest, bptr, size);
226 dest += roffset;
227 }
228 else
229 while (n--)
230 {
329f13ad 231 index_type i;
232
233 if (filler_len == 1)
234 memset (dest, filler[0], size);
235 else
236 for (i = 0; i < size; i += filler_len)
237 memcpy (&dest[i], filler, filler_len);
238
1a9a4a12 239 dest += roffset;
240 }
4ee9c684 241
242 /* Advance to the next section. */
243 rptr += rstride0;
244 sptr += sstride0;
245 hptr += hstride0;
246 bptr += bstride0;
247 count[0]++;
248 n = 0;
249 while (count[n] == extent[n])
250 {
251 /* When we get to the end of a dimension, reset it and increment
252 the next dimension. */
253 count[n] = 0;
254 /* We could precalculate these products, but this is a less
a2ffc2c4 255 frequently used path so probably not worth it. */
4ee9c684 256 rptr -= rstride[n] * extent[n];
257 sptr -= sstride[n] * extent[n];
258 hptr -= hstride[n] * extent[n];
259 bptr -= bstride[n] * extent[n];
260 n++;
261 if (n >= dim - 1)
262 {
263 /* Break out of the loop. */
264 rptr = NULL;
265 break;
266 }
267 else
268 {
269 count[n]++;
270 rptr += rstride[n];
271 sptr += sstride[n];
272 hptr += hstride[n];
273 bptr += bstride[n];
274 }
275 }
276 }
277}
1a9a4a12 278
0a6b5f6b 279extern void eoshift3_'atype_kind` (gfc_array_char * const restrict,
b4cafd67 280 const gfc_array_char * const restrict,
0a6b5f6b 281 const 'atype` * const restrict,
b4cafd67 282 const gfc_array_char * const restrict,
0a6b5f6b 283 const 'atype_name` *);
284export_proto(eoshift3_'atype_kind`);
1a9a4a12 285
286void
0a6b5f6b 287eoshift3_'atype_kind` (gfc_array_char * const restrict ret,
b4cafd67 288 const gfc_array_char * const restrict array,
0a6b5f6b 289 const 'atype` * const restrict h,
b4cafd67 290 const gfc_array_char * const restrict bound,
0a6b5f6b 291 const 'atype_name` * const restrict pwhich)
1a9a4a12 292{
827aef63 293 eoshift3 (ret, array, h, bound, pwhich, "\0", 1);
1a9a4a12 294}
295
329f13ad 296
0a6b5f6b 297extern void eoshift3_'atype_kind`_char (gfc_array_char * const restrict,
b4cafd67 298 GFC_INTEGER_4,
299 const gfc_array_char * const restrict,
0a6b5f6b 300 const 'atype` * const restrict,
b4cafd67 301 const gfc_array_char * const restrict,
0a6b5f6b 302 const 'atype_name` * const restrict,
b4cafd67 303 GFC_INTEGER_4, GFC_INTEGER_4);
0a6b5f6b 304export_proto(eoshift3_'atype_kind`_char);
1a9a4a12 305
306void
0a6b5f6b 307eoshift3_'atype_kind`_char (gfc_array_char * const restrict ret,
b4cafd67 308 GFC_INTEGER_4 ret_length __attribute__((unused)),
309 const gfc_array_char * const restrict array,
0a6b5f6b 310 const 'atype` * const restrict h,
b4cafd67 311 const gfc_array_char * const restrict bound,
0a6b5f6b 312 const 'atype_name` * const restrict pwhich,
827aef63 313 GFC_INTEGER_4 array_length __attribute__((unused)),
b4cafd67 314 GFC_INTEGER_4 bound_length __attribute__((unused)))
1a9a4a12 315{
827aef63 316 eoshift3 (ret, array, h, bound, pwhich, " ", 1);
329f13ad 317}
318
319
320extern void eoshift3_'atype_kind`_char4 (gfc_array_char * const restrict,
321 GFC_INTEGER_4,
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);
327export_proto(eoshift3_'atype_kind`_char4);
328
329void
330eoshift3_'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,
827aef63 336 GFC_INTEGER_4 array_length __attribute__((unused)),
329f13ad 337 GFC_INTEGER_4 bound_length __attribute__((unused)))
338{
339 static const gfc_char4_t space = (unsigned char) ''` ''`;
827aef63 340 eoshift3 (ret, array, h, bound, pwhich,
329f13ad 341 (const char *) &space, sizeof (gfc_char4_t));
1a9a4a12 342}
920e54ef 343
0a6b5f6b 344#endif'