OSDN Git Service

a7852e0e40a6ee7af3156bd98e6d6479bc755ebc
[pf3gnuchains/gcc-fork.git] / libgfortran / m4 / eoshift1.m4
1 `/* Implementation of the EOSHIFT intrinsic
2    Copyright 2002 Free Software Foundation, Inc.
3    Contributed by Paul Brook <paul@nowt.org>
4
5 This file is part of the GNU Fortran 95 runtime library (libgfor).
6
7 Libgfor is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 Ligbfor is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with libgfor; see the file COPYING.LIB.  If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include "config.h"
23 #include <stdlib.h>
24 #include <assert.h>
25 #include <string.h>
26 #include "libgfortran.h"'
27 include(iparm.m4)dnl
28
29 static const char zeros[16] =
30   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
31
32 void
33 `__eoshift1_'atype_kind (const gfc_array_char * ret, const gfc_array_char * array,
34     const atype * h, const char * pbound, const atype_name * pwhich)
35 {
36   /* r.* indicates the return array.  */
37   index_type rstride[GFC_MAX_DIMENSIONS - 1];
38   index_type rstride0;
39   index_type roffset;
40   char *rptr;
41   char *dest;
42   /* s.* indicates the source array.  */
43   index_type sstride[GFC_MAX_DIMENSIONS - 1];
44   index_type sstride0;
45   index_type soffset;
46   const char *sptr;
47   const char *src;
48 `  /* h.* indicates the shift array.  */'
49   index_type hstride[GFC_MAX_DIMENSIONS - 1];
50   index_type hstride0;
51   const atype_name *hptr;
52
53   index_type count[GFC_MAX_DIMENSIONS - 1];
54   index_type extent[GFC_MAX_DIMENSIONS - 1];
55   index_type dim;
56   index_type size;
57   index_type len;
58   index_type n;
59   int which;
60   atype_name sh;
61   atype_name delta;
62
63   if (pwhich)
64     which = *pwhich - 1;
65   else
66     which = 0;
67
68   if (!pbound)
69     pbound = zeros;
70
71   size = GFC_DESCRIPTOR_SIZE (ret);
72
73   extent[0] = 1;
74   count[0] = 0;
75   size = GFC_DESCRIPTOR_SIZE (array);
76   n = 0;
77   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
78     {
79       if (dim == which)
80         {
81           roffset = ret->dim[dim].stride * size;
82           if (roffset == 0)
83             roffset = size;
84           soffset = array->dim[dim].stride * size;
85           if (soffset == 0)
86             soffset = size;
87           len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
88         }
89       else
90         {
91           count[n] = 0;
92           extent[n] = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
93           rstride[n] = ret->dim[dim].stride * size;
94           sstride[n] = array->dim[dim].stride * size;
95
96           hstride[n] = h->dim[n].stride;
97           n++;
98         }
99     }
100   if (sstride[0] == 0)
101     sstride[0] = size;
102   if (rstride[0] == 0)
103     rstride[0] = size;
104   if (hstride[0] == 0)
105     hstride[0] = 1;
106
107   dim = GFC_DESCRIPTOR_RANK (array);
108   rstride0 = rstride[0];
109   sstride0 = sstride[0];
110   hstride0 = hstride[0];
111   rptr = ret->data;
112   sptr = array->data;
113   hptr = h->data;
114
115   while (rptr)
116     {
117 `      /* Do the shift for this dimension.  */'
118       sh = *hptr;
119       delta = (sh >= 0) ? sh: -sh;
120       if (sh > 0)
121         {
122           src = &sptr[delta * soffset];
123           dest = rptr;
124         }
125       else
126         {
127           src = sptr;
128           dest = &rptr[delta * roffset];
129         }
130       for (n = 0; n < len - delta; n++)
131         {
132           memcpy (dest, src, size);
133           dest += roffset;
134           src += soffset;
135         }
136       if (sh < 0)
137         dest = rptr;
138       n = delta;
139
140       while (n--)
141         {
142           memcpy (dest, pbound, size);
143           dest += roffset;
144         }
145
146       /* Advance to the next section.  */
147       rptr += rstride0;
148       sptr += sstride0;
149       hptr += hstride0;
150       count[0]++;
151       n = 0;
152       while (count[n] == extent[n])
153         {
154           /* When we get to the end of a dimension, reset it and increment
155              the next dimension.  */
156           count[n] = 0;
157           /* We could precalculate these products, but this is a less
158              frequently used path so proabably not worth it.  */
159           rptr -= rstride[n] * extent[n];
160           sptr -= sstride[n] * extent[n];
161           hptr -= hstride[n] * extent[n];
162           n++;
163           if (n >= dim - 1)
164             {
165               /* Break out of the loop.  */
166               rptr = NULL;
167               break;
168             }
169           else
170             {
171               count[n]++;
172               rptr += rstride[n];
173               sptr += sstride[n];
174               hptr += hstride[n];
175             }
176         }
177     }
178 }
179