]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/m4/cshift0.m4
Update copyright years.
[thirdparty/gcc.git] / libgfortran / m4 / cshift0.m4
CommitLineData
95f15c5b 1`/* Helper function for cshift functions.
f1717362 2 Copyright (C) 2008-2016 Free Software Foundation, Inc.
95f15c5b 3 Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>
4
553877d9 5This file is part of the GNU Fortran runtime library (libgfortran).
95f15c5b 6
7Libgfortran is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public
9License as published by the Free Software Foundation; either
6bc9506f 10version 3 of the License, or (at your option) any later version.
95f15c5b 11
12Libgfortran 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 General Public License for more details.
16
6bc9506f 17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
95f15c5b 25
26#include "libgfortran.h"
27#include <stdlib.h>
28#include <assert.h>
29#include <string.h>'
30
31include(iparm.m4)dnl
32
33`#if defined (HAVE_'rtype_name`)
34
35void
c75dca49 36cshift0_'rtype_code` ('rtype` *ret, const 'rtype` *array, ptrdiff_t shift,
95f15c5b 37 int which)
38{
39 /* r.* indicates the return array. */
40 index_type rstride[GFC_MAX_DIMENSIONS];
41 index_type rstride0;
42 index_type roffset;
43 'rtype_name` *rptr;
44
45 /* s.* indicates the source array. */
46 index_type sstride[GFC_MAX_DIMENSIONS];
47 index_type sstride0;
48 index_type soffset;
49 const 'rtype_name` *sptr;
50
51 index_type count[GFC_MAX_DIMENSIONS];
52 index_type extent[GFC_MAX_DIMENSIONS];
53 index_type dim;
54 index_type len;
55 index_type n;
56
57 which = which - 1;
58 sstride[0] = 0;
59 rstride[0] = 0;
60
61 extent[0] = 1;
62 count[0] = 0;
63 n = 0;
64 /* Initialized for avoiding compiler warnings. */
65 roffset = 1;
66 soffset = 1;
67 len = 0;
68
69 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
70 {
71 if (dim == which)
72 {
827aef63 73 roffset = GFC_DESCRIPTOR_STRIDE(ret,dim);
95f15c5b 74 if (roffset == 0)
75 roffset = 1;
827aef63 76 soffset = GFC_DESCRIPTOR_STRIDE(array,dim);
95f15c5b 77 if (soffset == 0)
78 soffset = 1;
827aef63 79 len = GFC_DESCRIPTOR_EXTENT(array,dim);
95f15c5b 80 }
81 else
82 {
83 count[n] = 0;
827aef63 84 extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
85 rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,dim);
86 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,dim);
95f15c5b 87 n++;
88 }
89 }
90 if (sstride[0] == 0)
91 sstride[0] = 1;
92 if (rstride[0] == 0)
93 rstride[0] = 1;
94
95 dim = GFC_DESCRIPTOR_RANK (array);
96 rstride0 = rstride[0];
97 sstride0 = sstride[0];
553877d9 98 rptr = ret->base_addr;
99 sptr = array->base_addr;
95f15c5b 100
37598f0f 101 /* Avoid the costly modulo for trivially in-bound shifts. */
102 if (shift < 0 || shift >= len)
103 {
104 shift = len == 0 ? 0 : shift % (ptrdiff_t)len;
105 if (shift < 0)
106 shift += len;
107 }
95f15c5b 108
109 while (rptr)
110 {
111 /* Do the shift for this dimension. */
112
113 /* If elements are contiguous, perform the operation
114 in two block moves. */
115 if (soffset == 1 && roffset == 1)
116 {
117 size_t len1 = shift * sizeof ('rtype_name`);
118 size_t len2 = (len - shift) * sizeof ('rtype_name`);
119 memcpy (rptr, sptr + shift, len2);
120 memcpy (rptr + (len - shift), sptr, len1);
121 }
122 else
123 {
124 /* Otherwise, we will have to perform the copy one element at
125 a time. */
126 'rtype_name` *dest = rptr;
127 const 'rtype_name` *src = &sptr[shift * soffset];
128
129 for (n = 0; n < len - shift; n++)
130 {
131 *dest = *src;
132 dest += roffset;
133 src += soffset;
134 }
135 for (src = sptr, n = 0; n < shift; n++)
136 {
137 *dest = *src;
138 dest += roffset;
139 src += soffset;
140 }
141 }
142
143 /* Advance to the next section. */
144 rptr += rstride0;
145 sptr += sstride0;
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 probably not worth it. */
155 rptr -= rstride[n] * extent[n];
156 sptr -= sstride[n] * extent[n];
157 n++;
158 if (n >= dim - 1)
159 {
160 /* Break out of the loop. */
161 rptr = NULL;
162 break;
163 }
164 else
165 {
166 count[n]++;
167 rptr += rstride[n];
168 sptr += sstride[n];
169 }
170 }
171 }
172
173 return;
174}
175
176#endif'