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