]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/m4/cshift1.m4
re PR libfortran/36773 (zero-sized arrays with cshift and eoshift)
[thirdparty/gcc.git] / libgfortran / m4 / cshift1.m4
1 `/* Implementation of the CSHIFT intrinsic
2 Copyright 2003, 2007 Free Software Foundation, Inc.
3 Contributed by Feng Wang <wf_cs@yahoo.com>
4
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6
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 2 of the License, or (at your option) any later version.
11
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
19 executable.)
20
21 Ligbfortran is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public
27 License along with libgfortran; see the file COPYING. If not,
28 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
29 Boston, MA 02110-1301, USA. */
30
31 #include "libgfortran.h"
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <string.h>'
35
36 include(iparm.m4)dnl
37
38 `#if defined (HAVE_'atype_name`)
39
40 static void
41 cshift1 (gfc_array_char * const restrict ret,
42 const gfc_array_char * const restrict array,
43 const 'atype` * const restrict h,
44 const 'atype_name` * const restrict pwhich,
45 index_type size)
46 {
47 /* r.* indicates the return array. */
48 index_type rstride[GFC_MAX_DIMENSIONS];
49 index_type rstride0;
50 index_type roffset;
51 char *rptr;
52 char *dest;
53 /* s.* indicates the source array. */
54 index_type sstride[GFC_MAX_DIMENSIONS];
55 index_type sstride0;
56 index_type soffset;
57 const char *sptr;
58 const char *src;
59 /* h.* indicates the shift array. */
60 index_type hstride[GFC_MAX_DIMENSIONS];
61 index_type hstride0;
62 const 'atype_name` *hptr;
63
64 index_type count[GFC_MAX_DIMENSIONS];
65 index_type extent[GFC_MAX_DIMENSIONS];
66 index_type dim;
67 index_type len;
68 index_type n;
69 int which;
70 'atype_name` sh;
71 index_type arraysize;
72
73 if (pwhich)
74 which = *pwhich - 1;
75 else
76 which = 0;
77
78 if (which < 0 || (which + 1) > GFC_DESCRIPTOR_RANK (array))
79 runtime_error ("Argument ''`DIM''` is out of range in call to ''`CSHIFT''`");
80
81 arraysize = size0 ((array_t *)array);
82
83 if (ret->data == NULL)
84 {
85 int i;
86
87 ret->data = internal_malloc_size (size * arraysize);
88 ret->offset = 0;
89 ret->dtype = array->dtype;
90 for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
91 {
92 ret->dim[i].lbound = 0;
93 ret->dim[i].ubound = array->dim[i].ubound - array->dim[i].lbound;
94
95 if (i == 0)
96 ret->dim[i].stride = 1;
97 else
98 ret->dim[i].stride = (ret->dim[i-1].ubound + 1) * ret->dim[i-1].stride;
99 }
100 }
101
102 if (arraysize == 0)
103 return;
104
105 extent[0] = 1;
106 count[0] = 0;
107 n = 0;
108
109 /* Initialized for avoiding compiler warnings. */
110 roffset = size;
111 soffset = size;
112 len = 0;
113
114 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
115 {
116 if (dim == which)
117 {
118 roffset = ret->dim[dim].stride * size;
119 if (roffset == 0)
120 roffset = size;
121 soffset = array->dim[dim].stride * size;
122 if (soffset == 0)
123 soffset = size;
124 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
125 }
126 else
127 {
128 count[n] = 0;
129 extent[n] = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
130 rstride[n] = ret->dim[dim].stride * size;
131 sstride[n] = array->dim[dim].stride * size;
132
133 hstride[n] = h->dim[n].stride;
134 n++;
135 }
136 }
137 if (sstride[0] == 0)
138 sstride[0] = size;
139 if (rstride[0] == 0)
140 rstride[0] = size;
141 if (hstride[0] == 0)
142 hstride[0] = 1;
143
144 dim = GFC_DESCRIPTOR_RANK (array);
145 rstride0 = rstride[0];
146 sstride0 = sstride[0];
147 hstride0 = hstride[0];
148 rptr = ret->data;
149 sptr = array->data;
150 hptr = h->data;
151
152 while (rptr)
153 {
154 /* Do the shift for this dimension. */
155 sh = *hptr;
156 sh = (div (sh, len)).rem;
157 if (sh < 0)
158 sh += len;
159
160 src = &sptr[sh * soffset];
161 dest = rptr;
162
163 for (n = 0; n < len; n++)
164 {
165 memcpy (dest, src, size);
166 dest += roffset;
167 if (n == len - sh - 1)
168 src = sptr;
169 else
170 src += soffset;
171 }
172
173 /* Advance to the next section. */
174 rptr += rstride0;
175 sptr += sstride0;
176 hptr += hstride0;
177 count[0]++;
178 n = 0;
179 while (count[n] == extent[n])
180 {
181 /* When we get to the end of a dimension, reset it and increment
182 the next dimension. */
183 count[n] = 0;
184 /* We could precalculate these products, but this is a less
185 frequently used path so probably not worth it. */
186 rptr -= rstride[n] * extent[n];
187 sptr -= sstride[n] * extent[n];
188 hptr -= hstride[n] * extent[n];
189 n++;
190 if (n >= dim - 1)
191 {
192 /* Break out of the loop. */
193 rptr = NULL;
194 break;
195 }
196 else
197 {
198 count[n]++;
199 rptr += rstride[n];
200 sptr += sstride[n];
201 hptr += hstride[n];
202 }
203 }
204 }
205 }
206
207 void cshift1_'atype_kind` (gfc_array_char * const restrict,
208 const gfc_array_char * const restrict,
209 const 'atype` * const restrict,
210 const 'atype_name` * const restrict);
211 export_proto(cshift1_'atype_kind`);
212
213 void
214 cshift1_'atype_kind` (gfc_array_char * const restrict ret,
215 const gfc_array_char * const restrict array,
216 const 'atype` * const restrict h,
217 const 'atype_name` * const restrict pwhich)
218 {
219 cshift1 (ret, array, h, pwhich, GFC_DESCRIPTOR_SIZE (array));
220 }
221
222
223 void cshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
224 GFC_INTEGER_4,
225 const gfc_array_char * const restrict array,
226 const 'atype` * const restrict h,
227 const 'atype_name` * const restrict pwhich,
228 GFC_INTEGER_4);
229 export_proto(cshift1_'atype_kind`_char);
230
231 void
232 cshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
233 GFC_INTEGER_4 ret_length __attribute__((unused)),
234 const gfc_array_char * const restrict array,
235 const 'atype` * const restrict h,
236 const 'atype_name` * const restrict pwhich,
237 GFC_INTEGER_4 array_length)
238 {
239 cshift1 (ret, array, h, pwhich, array_length);
240 }
241
242
243 void cshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
244 GFC_INTEGER_4,
245 const gfc_array_char * const restrict array,
246 const 'atype` * const restrict h,
247 const 'atype_name` * const restrict pwhich,
248 GFC_INTEGER_4);
249 export_proto(cshift1_'atype_kind`_char4);
250
251 void
252 cshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
253 GFC_INTEGER_4 ret_length __attribute__((unused)),
254 const gfc_array_char * const restrict array,
255 const 'atype` * const restrict h,
256 const 'atype_name` * const restrict pwhich,
257 GFC_INTEGER_4 array_length)
258 {
259 cshift1 (ret, array, h, pwhich, array_length * sizeof (gfc_char4_t));
260 }
261
262 #endif'