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