]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/generated/sum_i8.c
in_pack.m4: Add TODO comment about detecting temporaries...
[thirdparty/gcc.git] / libgfortran / generated / sum_i8.c
1 /* Implementation of the SUM intrinsic
2 Copyright 2002 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
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 General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
19 executable.)
20
21 Libgfortran is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public
27 License along with libgfortran; see the file COPYING. If not,
28 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
29 Boston, MA 02110-1301, USA. */
30
31 #include "config.h"
32 #include <stdlib.h>
33 #include <assert.h>
34 #include "libgfortran.h"
35
36
37 #if defined (HAVE_GFC_INTEGER_8) && defined (HAVE_GFC_INTEGER_8)
38
39
40 extern void sum_i8 (gfc_array_i8 * const restrict,
41 gfc_array_i8 * const restrict, const index_type * const restrict);
42 export_proto(sum_i8);
43
44 void
45 sum_i8 (gfc_array_i8 * const restrict retarray,
46 gfc_array_i8 * const restrict array,
47 const index_type * const restrict pdim)
48 {
49 index_type count[GFC_MAX_DIMENSIONS];
50 index_type extent[GFC_MAX_DIMENSIONS];
51 index_type sstride[GFC_MAX_DIMENSIONS];
52 index_type dstride[GFC_MAX_DIMENSIONS];
53 const GFC_INTEGER_8 * restrict base;
54 GFC_INTEGER_8 * restrict dest;
55 index_type rank;
56 index_type n;
57 index_type len;
58 index_type delta;
59 index_type dim;
60
61 /* Make dim zero based to avoid confusion. */
62 dim = (*pdim) - 1;
63 rank = GFC_DESCRIPTOR_RANK (array) - 1;
64
65 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
66 delta = array->dim[dim].stride;
67
68 for (n = 0; n < dim; n++)
69 {
70 sstride[n] = array->dim[n].stride;
71 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
72 }
73 for (n = dim; n < rank; n++)
74 {
75 sstride[n] = array->dim[n + 1].stride;
76 extent[n] =
77 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
78 }
79
80 if (retarray->data == NULL)
81 {
82 for (n = 0; n < rank; n++)
83 {
84 retarray->dim[n].lbound = 0;
85 retarray->dim[n].ubound = extent[n]-1;
86 if (n == 0)
87 retarray->dim[n].stride = 1;
88 else
89 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
90 }
91
92 retarray->data
93 = internal_malloc_size (sizeof (GFC_INTEGER_8)
94 * retarray->dim[rank-1].stride
95 * extent[rank-1]);
96 retarray->offset = 0;
97 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
98 }
99 else
100 {
101 if (rank != GFC_DESCRIPTOR_RANK (retarray))
102 runtime_error ("rank of return array incorrect");
103 }
104
105 for (n = 0; n < rank; n++)
106 {
107 count[n] = 0;
108 dstride[n] = retarray->dim[n].stride;
109 if (extent[n] <= 0)
110 len = 0;
111 }
112
113 base = array->data;
114 dest = retarray->data;
115
116 while (base)
117 {
118 const GFC_INTEGER_8 * restrict src;
119 GFC_INTEGER_8 result;
120 src = base;
121 {
122
123 result = 0;
124 if (len <= 0)
125 *dest = 0;
126 else
127 {
128 for (n = 0; n < len; n++, src += delta)
129 {
130
131 result += *src;
132 }
133 *dest = result;
134 }
135 }
136 /* Advance to the next element. */
137 count[0]++;
138 base += sstride[0];
139 dest += dstride[0];
140 n = 0;
141 while (count[n] == extent[n])
142 {
143 /* When we get to the end of a dimension, reset it and increment
144 the next dimension. */
145 count[n] = 0;
146 /* We could precalculate these products, but this is a less
147 frequently used path so proabably not worth it. */
148 base -= sstride[n] * extent[n];
149 dest -= dstride[n] * extent[n];
150 n++;
151 if (n == rank)
152 {
153 /* Break out of the look. */
154 base = NULL;
155 break;
156 }
157 else
158 {
159 count[n]++;
160 base += sstride[n];
161 dest += dstride[n];
162 }
163 }
164 }
165 }
166
167
168 extern void msum_i8 (gfc_array_i8 * const restrict,
169 gfc_array_i8 * const restrict, const index_type * const restrict,
170 gfc_array_l4 * const restrict);
171 export_proto(msum_i8);
172
173 void
174 msum_i8 (gfc_array_i8 * const restrict retarray,
175 gfc_array_i8 * const restrict array,
176 const index_type * const restrict pdim,
177 gfc_array_l4 * const restrict mask)
178 {
179 index_type count[GFC_MAX_DIMENSIONS];
180 index_type extent[GFC_MAX_DIMENSIONS];
181 index_type sstride[GFC_MAX_DIMENSIONS];
182 index_type dstride[GFC_MAX_DIMENSIONS];
183 index_type mstride[GFC_MAX_DIMENSIONS];
184 GFC_INTEGER_8 * restrict dest;
185 const GFC_INTEGER_8 * restrict base;
186 const GFC_LOGICAL_4 * restrict mbase;
187 int rank;
188 int dim;
189 index_type n;
190 index_type len;
191 index_type delta;
192 index_type mdelta;
193
194 dim = (*pdim) - 1;
195 rank = GFC_DESCRIPTOR_RANK (array) - 1;
196
197 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
198 if (len <= 0)
199 return;
200 delta = array->dim[dim].stride;
201 mdelta = mask->dim[dim].stride;
202
203 for (n = 0; n < dim; n++)
204 {
205 sstride[n] = array->dim[n].stride;
206 mstride[n] = mask->dim[n].stride;
207 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
208 }
209 for (n = dim; n < rank; n++)
210 {
211 sstride[n] = array->dim[n + 1].stride;
212 mstride[n] = mask->dim[n + 1].stride;
213 extent[n] =
214 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
215 }
216
217 if (retarray->data == NULL)
218 {
219 for (n = 0; n < rank; n++)
220 {
221 retarray->dim[n].lbound = 0;
222 retarray->dim[n].ubound = extent[n]-1;
223 if (n == 0)
224 retarray->dim[n].stride = 1;
225 else
226 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
227 }
228
229 retarray->data
230 = internal_malloc_size (sizeof (GFC_INTEGER_8)
231 * retarray->dim[rank-1].stride
232 * extent[rank-1]);
233 retarray->offset = 0;
234 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
235 }
236 else
237 {
238 if (rank != GFC_DESCRIPTOR_RANK (retarray))
239 runtime_error ("rank of return array incorrect");
240 }
241
242 for (n = 0; n < rank; n++)
243 {
244 count[n] = 0;
245 dstride[n] = retarray->dim[n].stride;
246 if (extent[n] <= 0)
247 return;
248 }
249
250 dest = retarray->data;
251 base = array->data;
252 mbase = mask->data;
253
254 if (GFC_DESCRIPTOR_SIZE (mask) != 4)
255 {
256 /* This allows the same loop to be used for all logical types. */
257 assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
258 for (n = 0; n < rank; n++)
259 mstride[n] <<= 1;
260 mdelta <<= 1;
261 mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
262 }
263
264 while (base)
265 {
266 const GFC_INTEGER_8 * restrict src;
267 const GFC_LOGICAL_4 * restrict msrc;
268 GFC_INTEGER_8 result;
269 src = base;
270 msrc = mbase;
271 {
272
273 result = 0;
274 if (len <= 0)
275 *dest = 0;
276 else
277 {
278 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
279 {
280
281 if (*msrc)
282 result += *src;
283 }
284 *dest = result;
285 }
286 }
287 /* Advance to the next element. */
288 count[0]++;
289 base += sstride[0];
290 mbase += mstride[0];
291 dest += dstride[0];
292 n = 0;
293 while (count[n] == extent[n])
294 {
295 /* When we get to the end of a dimension, reset it and increment
296 the next dimension. */
297 count[n] = 0;
298 /* We could precalculate these products, but this is a less
299 frequently used path so proabably not worth it. */
300 base -= sstride[n] * extent[n];
301 mbase -= mstride[n] * extent[n];
302 dest -= dstride[n] * extent[n];
303 n++;
304 if (n == rank)
305 {
306 /* Break out of the look. */
307 base = NULL;
308 break;
309 }
310 else
311 {
312 count[n]++;
313 base += sstride[n];
314 mbase += mstride[n];
315 dest += dstride[n];
316 }
317 }
318 }
319 }
320
321
322 extern void ssum_i8 (gfc_array_i8 * const restrict,
323 gfc_array_i8 * const restrict, const index_type * const restrict,
324 GFC_LOGICAL_4 *);
325 export_proto(ssum_i8);
326
327 void
328 ssum_i8 (gfc_array_i8 * const restrict retarray,
329 gfc_array_i8 * const restrict array,
330 const index_type * const restrict pdim,
331 GFC_LOGICAL_4 * mask)
332 {
333 index_type rank;
334 index_type n;
335 index_type dstride;
336 GFC_INTEGER_8 *dest;
337
338 if (*mask)
339 {
340 sum_i8 (retarray, array, pdim);
341 return;
342 }
343 rank = GFC_DESCRIPTOR_RANK (array);
344 if (rank <= 0)
345 runtime_error ("Rank of array needs to be > 0");
346
347 if (retarray->data == NULL)
348 {
349 retarray->dim[0].lbound = 0;
350 retarray->dim[0].ubound = rank-1;
351 retarray->dim[0].stride = 1;
352 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
353 retarray->offset = 0;
354 retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
355 }
356 else
357 {
358 if (GFC_DESCRIPTOR_RANK (retarray) != 1)
359 runtime_error ("rank of return array does not equal 1");
360
361 if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
362 runtime_error ("dimension of return array incorrect");
363 }
364
365 dstride = retarray->dim[0].stride;
366 dest = retarray->data;
367
368 for (n = 0; n < rank; n++)
369 dest[n * dstride] = 0 ;
370 }
371
372 #endif