]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/generated/cshift0_i2.c
libgfortran.h: Include <stdlib.h> header.
[thirdparty/gcc.git] / libgfortran / generated / cshift0_i2.c
CommitLineData
c2b00cdc 1/* Helper function for cshift functions.
818ab71a 2 Copyright (C) 2008-2016 Free Software Foundation, Inc.
c2b00cdc
TK
3 Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>
4
21d1335b 5This file is part of the GNU Fortran runtime library (libgfortran).
c2b00cdc
TK
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
748086b7 10version 3 of the License, or (at your option) any later version.
c2b00cdc
TK
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
748086b7
JJ
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/>. */
c2b00cdc
TK
25
26#include "libgfortran.h"
c2b00cdc
TK
27#include <string.h>
28
29
30#if defined (HAVE_GFC_INTEGER_2)
31
32void
44720bef 33cshift0_i2 (gfc_array_i2 *ret, const gfc_array_i2 *array, ptrdiff_t shift,
c2b00cdc
TK
34 int which)
35{
36 /* r.* indicates the return array. */
37 index_type rstride[GFC_MAX_DIMENSIONS];
38 index_type rstride0;
39 index_type roffset;
40 GFC_INTEGER_2 *rptr;
41
42 /* s.* indicates the source array. */
43 index_type sstride[GFC_MAX_DIMENSIONS];
44 index_type sstride0;
45 index_type soffset;
46 const GFC_INTEGER_2 *sptr;
47
48 index_type count[GFC_MAX_DIMENSIONS];
49 index_type extent[GFC_MAX_DIMENSIONS];
50 index_type dim;
51 index_type len;
52 index_type n;
53
54 which = which - 1;
55 sstride[0] = 0;
56 rstride[0] = 0;
57
58 extent[0] = 1;
59 count[0] = 0;
60 n = 0;
61 /* Initialized for avoiding compiler warnings. */
62 roffset = 1;
63 soffset = 1;
64 len = 0;
65
66 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
67 {
68 if (dim == which)
69 {
dfb55fdc 70 roffset = GFC_DESCRIPTOR_STRIDE(ret,dim);
c2b00cdc
TK
71 if (roffset == 0)
72 roffset = 1;
dfb55fdc 73 soffset = GFC_DESCRIPTOR_STRIDE(array,dim);
c2b00cdc
TK
74 if (soffset == 0)
75 soffset = 1;
dfb55fdc 76 len = GFC_DESCRIPTOR_EXTENT(array,dim);
c2b00cdc
TK
77 }
78 else
79 {
80 count[n] = 0;
dfb55fdc
TK
81 extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
82 rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,dim);
83 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,dim);
c2b00cdc
TK
84 n++;
85 }
86 }
87 if (sstride[0] == 0)
88 sstride[0] = 1;
89 if (rstride[0] == 0)
90 rstride[0] = 1;
91
92 dim = GFC_DESCRIPTOR_RANK (array);
93 rstride0 = rstride[0];
94 sstride0 = sstride[0];
21d1335b
TB
95 rptr = ret->base_addr;
96 sptr = array->base_addr;
c2b00cdc 97
b43645b8
MM
98 /* Avoid the costly modulo for trivially in-bound shifts. */
99 if (shift < 0 || shift >= len)
100 {
101 shift = len == 0 ? 0 : shift % (ptrdiff_t)len;
102 if (shift < 0)
103 shift += len;
104 }
c2b00cdc
TK
105
106 while (rptr)
107 {
108 /* Do the shift for this dimension. */
109
110 /* If elements are contiguous, perform the operation
111 in two block moves. */
112 if (soffset == 1 && roffset == 1)
113 {
114 size_t len1 = shift * sizeof (GFC_INTEGER_2);
115 size_t len2 = (len - shift) * sizeof (GFC_INTEGER_2);
116 memcpy (rptr, sptr + shift, len2);
117 memcpy (rptr + (len - shift), sptr, len1);
118 }
119 else
120 {
121 /* Otherwise, we will have to perform the copy one element at
122 a time. */
123 GFC_INTEGER_2 *dest = rptr;
124 const GFC_INTEGER_2 *src = &sptr[shift * soffset];
125
126 for (n = 0; n < len - shift; n++)
127 {
128 *dest = *src;
129 dest += roffset;
130 src += soffset;
131 }
132 for (src = sptr, n = 0; n < shift; n++)
133 {
134 *dest = *src;
135 dest += roffset;
136 src += soffset;
137 }
138 }
139
140 /* Advance to the next section. */
141 rptr += rstride0;
142 sptr += sstride0;
143 count[0]++;
144 n = 0;
145 while (count[n] == extent[n])
146 {
147 /* When we get to the end of a dimension, reset it and increment
148 the next dimension. */
149 count[n] = 0;
150 /* We could precalculate these products, but this is a less
151 frequently used path so probably not worth it. */
152 rptr -= rstride[n] * extent[n];
153 sptr -= sstride[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 }
167 }
168 }
169
170 return;
171}
172
173#endif