]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/m4/cshift1.m4
re PR fortran/37577 ([meta-bug] change internal array descriptor format for better...
[thirdparty/gcc.git] / libgfortran / m4 / cshift1.m4
CommitLineData
6de9cd9a 1`/* Implementation of the CSHIFT intrinsic
748086b7 2 Copyright 2003, 2007, 2009 Free Software Foundation, Inc.
6de9cd9a
DN
3 Contributed by Feng Wang <wf_cs@yahoo.com>
4
5This file is part of the GNU Fortran 95 runtime library (libgfortran).
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"
6de9cd9a
DN
27#include <stdlib.h>
28#include <assert.h>
36ae8a61
FXC
29#include <string.h>'
30
c9e66eda 31include(iparm.m4)dnl
6de9cd9a 32
adea5e16 33`#if defined (HAVE_'atype_name`)
644cb69f 34
7823229b 35static void
64acfd99
JB
36cshift1 (gfc_array_char * const restrict ret,
37 const gfc_array_char * const restrict array,
adea5e16 38 const 'atype` * const restrict h,
dfb55fdc 39 const 'atype_name` * const restrict pwhich)
6de9cd9a
DN
40{
41 /* r.* indicates the return array. */
e33e218b 42 index_type rstride[GFC_MAX_DIMENSIONS];
6de9cd9a
DN
43 index_type rstride0;
44 index_type roffset;
45 char *rptr;
46 char *dest;
47 /* s.* indicates the source array. */
e33e218b 48 index_type sstride[GFC_MAX_DIMENSIONS];
6de9cd9a
DN
49 index_type sstride0;
50 index_type soffset;
51 const char *sptr;
52 const char *src;
7d7b8bfe 53 /* h.* indicates the shift array. */
e33e218b 54 index_type hstride[GFC_MAX_DIMENSIONS];
6de9cd9a 55 index_type hstride0;
adea5e16 56 const 'atype_name` *hptr;
6de9cd9a 57
e33e218b
TK
58 index_type count[GFC_MAX_DIMENSIONS];
59 index_type extent[GFC_MAX_DIMENSIONS];
6de9cd9a 60 index_type dim;
6de9cd9a
DN
61 index_type len;
62 index_type n;
63 int which;
adea5e16 64 'atype_name` sh;
c44109aa 65 index_type arraysize;
dfb55fdc 66 index_type size;
6de9cd9a
DN
67
68 if (pwhich)
69 which = *pwhich - 1;
70 else
71 which = 0;
72
73 if (which < 0 || (which + 1) > GFC_DESCRIPTOR_RANK (array))
adea5e16 74 runtime_error ("Argument ''`DIM''` is out of range in call to ''`CSHIFT''`");
6de9cd9a 75
dfb55fdc
TK
76 size = GFC_DESCRIPTOR_SIZE(array);
77
c44109aa
TK
78 arraysize = size0 ((array_t *)array);
79
0e6d033b
TK
80 if (ret->data == NULL)
81 {
82 int i;
83
c44109aa 84 ret->data = internal_malloc_size (size * arraysize);
efd4dc1a 85 ret->offset = 0;
0e6d033b
TK
86 ret->dtype = array->dtype;
87 for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
88 {
dfb55fdc
TK
89 index_type ub, str;
90
91 ub = GFC_DESCRIPTOR_EXTENT(array,i) - 1;
0e6d033b
TK
92
93 if (i == 0)
dfb55fdc 94 str = 1;
0e6d033b 95 else
dfb55fdc
TK
96 str = GFC_DESCRIPTOR_EXTENT(ret,i-1) *
97 GFC_DESCRIPTOR_STRIDE(ret,i-1);
98
99 GFC_DIMENSION_SET(ret->dim[i], 0, ub, str);
0e6d033b
TK
100 }
101 }
102
c44109aa
TK
103 if (arraysize == 0)
104 return;
105
6de9cd9a
DN
106 extent[0] = 1;
107 count[0] = 0;
6de9cd9a
DN
108 n = 0;
109
7d7b8bfe 110 /* Initialized for avoiding compiler warnings. */
6de9cd9a
DN
111 roffset = size;
112 soffset = size;
113 len = 0;
114
115 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
116 {
117 if (dim == which)
118 {
dfb55fdc 119 roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
6de9cd9a
DN
120 if (roffset == 0)
121 roffset = size;
dfb55fdc 122 soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
6de9cd9a
DN
123 if (soffset == 0)
124 soffset = size;
dfb55fdc 125 len = GFC_DESCRIPTOR_EXTENT(array,dim);
6de9cd9a
DN
126 }
127 else
128 {
129 count[n] = 0;
dfb55fdc
TK
130 extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
131 rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
132 sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
6de9cd9a 133
dfb55fdc 134 hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
6de9cd9a
DN
135 n++;
136 }
137 }
138 if (sstride[0] == 0)
139 sstride[0] = size;
140 if (rstride[0] == 0)
141 rstride[0] = size;
142 if (hstride[0] == 0)
143 hstride[0] = 1;
144
145 dim = GFC_DESCRIPTOR_RANK (array);
146 rstride0 = rstride[0];
147 sstride0 = sstride[0];
148 hstride0 = hstride[0];
149 rptr = ret->data;
150 sptr = array->data;
151 hptr = h->data;
152
153 while (rptr)
154 {
7d7b8bfe 155 /* Do the shift for this dimension. */
6de9cd9a
DN
156 sh = *hptr;
157 sh = (div (sh, len)).rem;
158 if (sh < 0)
159 sh += len;
160
161 src = &sptr[sh * soffset];
162 dest = rptr;
163
164 for (n = 0; n < len; n++)
165 {
166 memcpy (dest, src, size);
167 dest += roffset;
168 if (n == len - sh - 1)
169 src = sptr;
170 else
171 src += soffset;
172 }
173
174 /* Advance to the next section. */
175 rptr += rstride0;
176 sptr += sstride0;
177 hptr += hstride0;
178 count[0]++;
179 n = 0;
180 while (count[n] == extent[n])
181 {
182 /* When we get to the end of a dimension, reset it and increment
183 the next dimension. */
184 count[n] = 0;
185 /* We could precalculate these products, but this is a less
8b6dba81 186 frequently used path so probably not worth it. */
6de9cd9a
DN
187 rptr -= rstride[n] * extent[n];
188 sptr -= sstride[n] * extent[n];
189 hptr -= hstride[n] * extent[n];
190 n++;
191 if (n >= dim - 1)
192 {
193 /* Break out of the loop. */
194 rptr = NULL;
195 break;
196 }
197 else
198 {
199 count[n]++;
200 rptr += rstride[n];
201 sptr += sstride[n];
202 hptr += hstride[n];
203 }
204 }
205 }
206}
7823229b 207
adea5e16 208void cshift1_'atype_kind` (gfc_array_char * const restrict,
64acfd99 209 const gfc_array_char * const restrict,
adea5e16
TK
210 const 'atype` * const restrict,
211 const 'atype_name` * const restrict);
212export_proto(cshift1_'atype_kind`);
7823229b
RS
213
214void
adea5e16 215cshift1_'atype_kind` (gfc_array_char * const restrict ret,
64acfd99 216 const gfc_array_char * const restrict array,
adea5e16
TK
217 const 'atype` * const restrict h,
218 const 'atype_name` * const restrict pwhich)
7823229b 219{
dfb55fdc 220 cshift1 (ret, array, h, pwhich);
7823229b
RS
221}
222
691da334 223
adea5e16 224void cshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
64acfd99
JB
225 GFC_INTEGER_4,
226 const gfc_array_char * const restrict array,
adea5e16
TK
227 const 'atype` * const restrict h,
228 const 'atype_name` * const restrict pwhich,
64acfd99 229 GFC_INTEGER_4);
adea5e16 230export_proto(cshift1_'atype_kind`_char);
7823229b
RS
231
232void
adea5e16 233cshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
64acfd99
JB
234 GFC_INTEGER_4 ret_length __attribute__((unused)),
235 const gfc_array_char * const restrict array,
adea5e16
TK
236 const 'atype` * const restrict h,
237 const 'atype_name` * const restrict pwhich,
dfb55fdc 238 GFC_INTEGER_4 array_length __attribute__((unused)))
7823229b 239{
dfb55fdc 240 cshift1 (ret, array, h, pwhich);
7823229b 241}
644cb69f 242
691da334
FXC
243
244void cshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
245 GFC_INTEGER_4,
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);
250export_proto(cshift1_'atype_kind`_char4);
251
252void
253cshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
254 GFC_INTEGER_4 ret_length __attribute__((unused)),
255 const gfc_array_char * const restrict array,
256 const 'atype` * const restrict h,
257 const 'atype_name` * const restrict pwhich,
dfb55fdc 258 GFC_INTEGER_4 array_length __attribute__((unused)))
691da334 259{
dfb55fdc 260 cshift1 (ret, array, h, pwhich);
691da334
FXC
261}
262
adea5e16 263#endif'