OSDN Git Service

gcc/fortran/
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / cshift1_4.c
1 /* Implementation of the CSHIFT intrinsic
2    Copyright 2003 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 "config.h"
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <string.h>
35 #include "libgfortran.h"
36
37 static void
38 cshift1 (gfc_array_char * ret, const gfc_array_char * array,
39          const gfc_array_i4 * h, const GFC_INTEGER_4 * pwhich, index_type size)
40 {
41   /* r.* indicates the return array.  */
42   index_type rstride[GFC_MAX_DIMENSIONS];
43   index_type rstride0;
44   index_type roffset;
45   char *rptr;
46   char *dest;
47   /* s.* indicates the source array.  */
48   index_type sstride[GFC_MAX_DIMENSIONS];
49   index_type sstride0;
50   index_type soffset;
51   const char *sptr;
52   const char *src;
53   /* h.* indicates the  array.  */
54   index_type hstride[GFC_MAX_DIMENSIONS];
55   index_type hstride0;
56   const GFC_INTEGER_4 *hptr;
57
58   index_type count[GFC_MAX_DIMENSIONS];
59   index_type extent[GFC_MAX_DIMENSIONS];
60   index_type dim;
61   index_type len;
62   index_type n;
63   int which;
64   GFC_INTEGER_4 sh;
65
66   if (pwhich)
67     which = *pwhich - 1;
68   else
69     which = 0;
70
71   if (which < 0 || (which + 1) > GFC_DESCRIPTOR_RANK (array))
72     runtime_error ("Argument 'DIM' is out of range in call to 'CSHIFT'");
73
74   if (ret->data == NULL)
75     {
76       int i;
77
78       ret->data = internal_malloc_size (size * size0 ((array_t *)array));
79       ret->offset = 0;
80       ret->dtype = array->dtype;
81       for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
82         {
83           ret->dim[i].lbound = 0;
84           ret->dim[i].ubound = array->dim[i].ubound - array->dim[i].lbound;
85
86           if (i == 0)
87             ret->dim[i].stride = 1;
88           else
89             ret->dim[i].stride = (ret->dim[i-1].ubound + 1) * ret->dim[i-1].stride;
90         }
91     }
92
93   extent[0] = 1;
94   count[0] = 0;
95   n = 0;
96
97   /* Initialized for avoiding compiler warnings.  */
98   roffset = size;
99   soffset = size;
100   len = 0;
101
102   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
103     {
104       if (dim == which)
105         {
106           roffset = ret->dim[dim].stride * size;
107           if (roffset == 0)
108             roffset = size;
109           soffset = array->dim[dim].stride * size;
110           if (soffset == 0)
111             soffset = size;
112           len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
113         }
114       else
115         {
116           count[n] = 0;
117           extent[n] = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
118           rstride[n] = ret->dim[dim].stride * size;
119           sstride[n] = array->dim[dim].stride * size;
120
121           hstride[n] = h->dim[n].stride;
122           n++;
123         }
124     }
125   if (sstride[0] == 0)
126     sstride[0] = size;
127   if (rstride[0] == 0)
128     rstride[0] = size;
129   if (hstride[0] == 0)
130     hstride[0] = 1;
131
132   dim = GFC_DESCRIPTOR_RANK (array);
133   rstride0 = rstride[0];
134   sstride0 = sstride[0];
135   hstride0 = hstride[0];
136   rptr = ret->data;
137   sptr = array->data;
138   hptr = h->data;
139
140   while (rptr)
141     {
142       /* Do the  for this dimension.  */
143       sh = *hptr;
144       sh = (div (sh, len)).rem;
145       if (sh < 0)
146         sh += len;
147
148       src = &sptr[sh * soffset];
149       dest = rptr;
150
151       for (n = 0; n < len; n++)
152         {
153           memcpy (dest, src, size);
154           dest += roffset;
155           if (n == len - sh - 1)
156             src = sptr;
157           else
158             src += soffset;
159         }
160
161       /* Advance to the next section.  */
162       rptr += rstride0;
163       sptr += sstride0;
164       hptr += hstride0;
165       count[0]++;
166       n = 0;
167       while (count[n] == extent[n])
168         {
169           /* When we get to the end of a dimension, reset it and increment
170              the next dimension.  */
171           count[n] = 0;
172           /* We could precalculate these products, but this is a less
173              frequently used path so proabably not worth it.  */
174           rptr -= rstride[n] * extent[n];
175           sptr -= sstride[n] * extent[n];
176           hptr -= hstride[n] * extent[n];
177           n++;
178           if (n >= dim - 1)
179             {
180               /* Break out of the loop.  */
181               rptr = NULL;
182               break;
183             }
184           else
185             {
186               count[n]++;
187               rptr += rstride[n];
188               sptr += sstride[n];
189               hptr += hstride[n];
190             }
191         }
192     }
193 }
194
195 void cshift1_4 (gfc_array_char *, const gfc_array_char *,
196                            const gfc_array_i4 *, const GFC_INTEGER_4 *);
197 export_proto(cshift1_4);
198
199 void
200 cshift1_4 (gfc_array_char * ret,
201                       const gfc_array_char * array,
202                       const gfc_array_i4 * h, const GFC_INTEGER_4 * pwhich)
203 {
204   cshift1 (ret, array, h, pwhich, GFC_DESCRIPTOR_SIZE (array));
205 }
206
207 void cshift1_4_char (gfc_array_char * ret, GFC_INTEGER_4,
208                                   const gfc_array_char * array,
209                                   const gfc_array_i4 * h, const GFC_INTEGER_4 * pwhich,
210                                   GFC_INTEGER_4);
211 export_proto(cshift1_4_char);
212
213 void
214 cshift1_4_char (gfc_array_char * ret,
215                              GFC_INTEGER_4 ret_length __attribute__((unused)),
216                              const gfc_array_char * array,
217                              const gfc_array_i4 * h, const GFC_INTEGER_4 * pwhich,
218                              GFC_INTEGER_4 array_length)
219 {
220   cshift1 (ret, array, h, pwhich, array_length);
221 }