Merge from trunk @ 138209
[official-gcc.git] / libgfortran / m4 / eoshift3.m4
blob6a6929ca0c70bbbd73337184b2c676fb60b36c11
1 `/* Implementation of the EOSHIFT intrinsic
2    Copyright 2002, 2005, 2007 Free Software Foundation, Inc.
3    Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran 95 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 2 of the License, or (at your option) any later version.
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.)
21 Libgfortran 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.
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.  */
31 #include "libgfortran.h"
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <string.h>'
36 include(iparm.m4)dnl
38 `#if defined (HAVE_'atype_name`)
40 static void
41 eoshift3 (gfc_array_char * const restrict ret, 
42         const gfc_array_char * const restrict array, 
43         const 'atype` * const restrict h,
44         const gfc_array_char * const restrict bound, 
45         const 'atype_name` * const restrict pwhich,
46         index_type size, const char * filler, index_type filler_len)
48   /* r.* indicates the return array.  */
49   index_type rstride[GFC_MAX_DIMENSIONS];
50   index_type rstride0;
51   index_type roffset;
52   char *rptr;
53   char * restrict dest;
54   /* s.* indicates the source array.  */
55   index_type sstride[GFC_MAX_DIMENSIONS];
56   index_type sstride0;
57   index_type soffset;
58   const char *sptr;
59   const char *src;
60   /* h.* indicates the shift array.  */
61   index_type hstride[GFC_MAX_DIMENSIONS];
62   index_type hstride0;
63   const 'atype_name` *hptr;
64   /* b.* indicates the bound array.  */
65   index_type bstride[GFC_MAX_DIMENSIONS];
66   index_type bstride0;
67   const char *bptr;
69   index_type count[GFC_MAX_DIMENSIONS];
70   index_type extent[GFC_MAX_DIMENSIONS];
71   index_type dim;
72   index_type len;
73   index_type n;
74   int which;
75   'atype_name` sh;
76   'atype_name` delta;
78   /* The compiler cannot figure out that these are set, initialize
79      them to avoid warnings.  */
80   len = 0;
81   soffset = 0;
82   roffset = 0;
84   if (pwhich)
85     which = *pwhich - 1;
86   else
87     which = 0;
89   if (ret->data == NULL)
90     {
91       int i;
93       ret->data = internal_malloc_size (size * size0 ((array_t *)array));
94       ret->offset = 0;
95       ret->dtype = array->dtype;
96       for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
97         {
98           ret->dim[i].lbound = 0;
99           ret->dim[i].ubound = array->dim[i].ubound - array->dim[i].lbound;
101           if (i == 0)
102             ret->dim[i].stride = 1;
103           else
104             ret->dim[i].stride = (ret->dim[i-1].ubound + 1) * ret->dim[i-1].stride;
105         }
106     }
107   else
108     {
109       if (size0 ((array_t *) ret) == 0)
110         return;
111     }
114   extent[0] = 1;
115   count[0] = 0;
116   n = 0;
117   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
118     {
119       if (dim == which)
120         {
121           roffset = ret->dim[dim].stride * size;
122           if (roffset == 0)
123             roffset = size;
124           soffset = array->dim[dim].stride * size;
125           if (soffset == 0)
126             soffset = size;
127           len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
128         }
129       else
130         {
131           count[n] = 0;
132           extent[n] = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
133           rstride[n] = ret->dim[dim].stride * size;
134           sstride[n] = array->dim[dim].stride * size;
136           hstride[n] = h->dim[n].stride;
137           if (bound)
138             bstride[n] = bound->dim[n].stride * size;
139           else
140             bstride[n] = 0;
141           n++;
142         }
143     }
144   if (sstride[0] == 0)
145     sstride[0] = size;
146   if (rstride[0] == 0)
147     rstride[0] = size;
148   if (hstride[0] == 0)
149     hstride[0] = 1;
150   if (bound && bstride[0] == 0)
151     bstride[0] = size;
153   dim = GFC_DESCRIPTOR_RANK (array);
154   rstride0 = rstride[0];
155   sstride0 = sstride[0];
156   hstride0 = hstride[0];
157   bstride0 = bstride[0];
158   rptr = ret->data;
159   sptr = array->data;
160   hptr = h->data;
161   if (bound)
162     bptr = bound->data;
163   else
164     bptr = NULL;
166   while (rptr)
167     {
168       /* Do the shift for this dimension.  */
169       sh = *hptr;
170       if (( sh >= 0 ? sh : -sh ) > len)
171         {
172           delta = len;
173           sh = len;
174         }
175       else
176         delta = (sh >= 0) ? sh: -sh;
178       if (sh > 0)
179         {
180           src = &sptr[delta * soffset];
181           dest = rptr;
182         }
183       else
184         {
185           src = sptr;
186           dest = &rptr[delta * roffset];
187         }
188       for (n = 0; n < len - delta; n++)
189         {
190           memcpy (dest, src, size);
191           dest += roffset;
192           src += soffset;
193         }
194       if (sh < 0)
195         dest = rptr;
196       n = delta;
198       if (bptr)
199         while (n--)
200           {
201             memcpy (dest, bptr, size);
202             dest += roffset;
203           }
204       else
205         while (n--)
206           {
207             index_type i;
209             if (filler_len == 1)
210               memset (dest, filler[0], size);
211             else
212               for (i = 0; i < size; i += filler_len)
213                 memcpy (&dest[i], filler, filler_len);
215             dest += roffset;
216           }
218       /* Advance to the next section.  */
219       rptr += rstride0;
220       sptr += sstride0;
221       hptr += hstride0;
222       bptr += bstride0;
223       count[0]++;
224       n = 0;
225       while (count[n] == extent[n])
226         {
227           /* When we get to the end of a dimension, reset it and increment
228              the next dimension.  */
229           count[n] = 0;
230           /* We could precalculate these products, but this is a less
231              frequently used path so probably not worth it.  */
232           rptr -= rstride[n] * extent[n];
233           sptr -= sstride[n] * extent[n];
234           hptr -= hstride[n] * extent[n];
235           bptr -= bstride[n] * extent[n];
236           n++;
237           if (n >= dim - 1)
238             {
239               /* Break out of the loop.  */
240               rptr = NULL;
241               break;
242             }
243           else
244             {
245               count[n]++;
246               rptr += rstride[n];
247               sptr += sstride[n];
248               hptr += hstride[n];
249               bptr += bstride[n];
250             }
251         }
252     }
255 extern void eoshift3_'atype_kind` (gfc_array_char * const restrict, 
256         const gfc_array_char * const restrict,
257         const 'atype` * const restrict, 
258         const gfc_array_char * const restrict,
259         const 'atype_name` *);
260 export_proto(eoshift3_'atype_kind`);
262 void
263 eoshift3_'atype_kind` (gfc_array_char * const restrict ret, 
264         const gfc_array_char * const restrict array,
265         const 'atype` * const restrict h, 
266         const gfc_array_char * const restrict bound,
267         const 'atype_name` * const restrict pwhich)
269   eoshift3 (ret, array, h, bound, pwhich, GFC_DESCRIPTOR_SIZE (array),
270             "\0", 1);
274 extern void eoshift3_'atype_kind`_char (gfc_array_char * const restrict, 
275         GFC_INTEGER_4,
276         const gfc_array_char * const restrict,
277         const 'atype` * const restrict,
278         const gfc_array_char * const restrict,
279         const 'atype_name` * const restrict, 
280         GFC_INTEGER_4, GFC_INTEGER_4);
281 export_proto(eoshift3_'atype_kind`_char);
283 void
284 eoshift3_'atype_kind`_char (gfc_array_char * const restrict ret,
285         GFC_INTEGER_4 ret_length __attribute__((unused)),
286         const gfc_array_char * const restrict array, 
287         const 'atype` *  const restrict h,
288         const gfc_array_char * const restrict bound,
289         const 'atype_name` * const restrict pwhich,
290         GFC_INTEGER_4 array_length,
291         GFC_INTEGER_4 bound_length __attribute__((unused)))
293   eoshift3 (ret, array, h, bound, pwhich, array_length, " ", 1);
297 extern void eoshift3_'atype_kind`_char4 (gfc_array_char * const restrict, 
298         GFC_INTEGER_4,
299         const gfc_array_char * const restrict,
300         const 'atype` * const restrict,
301         const gfc_array_char * const restrict,
302         const 'atype_name` * const restrict, 
303         GFC_INTEGER_4, GFC_INTEGER_4);
304 export_proto(eoshift3_'atype_kind`_char4);
306 void
307 eoshift3_'atype_kind`_char4 (gfc_array_char * const restrict ret,
308         GFC_INTEGER_4 ret_length __attribute__((unused)),
309         const gfc_array_char * const restrict array, 
310         const 'atype` *  const restrict h,
311         const gfc_array_char * const restrict bound,
312         const 'atype_name` * const restrict pwhich,
313         GFC_INTEGER_4 array_length,
314         GFC_INTEGER_4 bound_length __attribute__((unused)))
316   static const gfc_char4_t space = (unsigned char) ''` ''`;
317   eoshift3 (ret, array, h, bound, pwhich, array_length * sizeof (gfc_char4_t),
318             (const char *) &space, sizeof (gfc_char4_t));
321 #endif'