OSDN Git Service

382537b702968150fee398835c70e87d9d73edeb
[pf3gnuchains/gcc-fork.git] / libgfortran / m4 / cshift1.m4
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 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(types.m4)dnl
28 define(htype_kind, regexp(file, `_\([0-9]+\)\.', `\1'))dnl
29 define(htype_code,`i'rtype_name)dnl
30 define(htype,get_arraytype(i,htype_kind))dnl
31 define(htype_name, get_typename(i,htype_kind))dnl
32
33 void
34 `__cshift1_'htype_kind (const gfc_array_char * ret, const gfc_array_char * array,
35     const htype * h, const htype_name * pwhich)
36 {
37   /* r.* indicates the return array.  */
38   index_type rstride[GFC_MAX_DIMENSIONS - 1];
39   index_type rstride0;
40   index_type roffset;
41   char *rptr;
42   char *dest;
43   /* s.* indicates the source array.  */
44   index_type sstride[GFC_MAX_DIMENSIONS - 1];
45   index_type sstride0;
46   index_type soffset;
47   const char *sptr;
48   const char *src;
49 `  /* h.* indicates the shift array.  */'
50   index_type hstride[GFC_MAX_DIMENSIONS - 1];
51   index_type hstride0;
52   const htype_name *hptr;
53
54   index_type count[GFC_MAX_DIMENSIONS - 1];
55   index_type extent[GFC_MAX_DIMENSIONS - 1];
56   index_type dim;
57   index_type size;
58   index_type len;
59   index_type n;
60   int which;
61   htype_name sh;
62
63   if (pwhich)
64     which = *pwhich - 1;
65   else
66     which = 0;
67
68   if (which < 0 || (which + 1) > GFC_DESCRIPTOR_RANK (array))
69     runtime_error ("Argument 'DIM' is out of range in call to 'CSHIFT'");
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
78 `/* Initialized for avoiding compiler warnings.  */'
79   roffset = size;
80   soffset = size;
81   len = 0;
82
83   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
84     {
85       if (dim == which)
86         {
87           roffset = ret->dim[dim].stride * size;
88           if (roffset == 0)
89             roffset = size;
90           soffset = array->dim[dim].stride * size;
91           if (soffset == 0)
92             soffset = size;
93           len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
94         }
95       else
96         {
97           count[n] = 0;
98           extent[n] = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
99           rstride[n] = ret->dim[dim].stride * size;
100           sstride[n] = array->dim[dim].stride * size;
101
102           hstride[n] = h->dim[n].stride;
103           n++;
104         }
105     }
106   if (sstride[0] == 0)
107     sstride[0] = size;
108   if (rstride[0] == 0)
109     rstride[0] = size;
110   if (hstride[0] == 0)
111     hstride[0] = 1;
112
113   dim = GFC_DESCRIPTOR_RANK (array);
114   rstride0 = rstride[0];
115   sstride0 = sstride[0];
116   hstride0 = hstride[0];
117   rptr = ret->data;
118   sptr = array->data;
119   hptr = h->data;
120
121   while (rptr)
122     {
123 `      /* Do the shift for this dimension.  */'
124       sh = *hptr;
125       sh = (div (sh, len)).rem;
126       if (sh < 0)
127         sh += len;
128
129       src = &sptr[sh * soffset];
130       dest = rptr;
131
132       for (n = 0; n < len; n++)
133         {
134           memcpy (dest, src, size);
135           dest += roffset;
136           if (n == len - sh - 1)
137             src = sptr;
138           else
139             src += soffset;
140         }
141
142       /* Advance to the next section.  */
143       rptr += rstride0;
144       sptr += sstride0;
145       hptr += hstride0;
146       count[0]++;
147       n = 0;
148       while (count[n] == extent[n])
149         {
150           /* When we get to the end of a dimension, reset it and increment
151              the next dimension.  */
152           count[n] = 0;
153           /* We could precalculate these products, but this is a less
154              frequently used path so proabably not worth it.  */
155           rptr -= rstride[n] * extent[n];
156           sptr -= sstride[n] * extent[n];
157           hptr -= hstride[n] * extent[n];
158           n++;
159           if (n >= dim - 1)
160             {
161               /* Break out of the loop.  */
162               rptr = NULL;
163               break;
164             }
165           else
166             {
167               count[n]++;
168               rptr += rstride[n];
169               sptr += sstride[n];
170               hptr += hstride[n];
171             }
172         }
173     }
174 }
175