OSDN Git Service

2008-07-21 Thomas Koenig <tkoenig@gcc.gnu.org>
[pf3gnuchains/gcc-fork.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'