2006-06-30 Andrew Pinski <pinskia@gmail.com>
[official-gcc.git] / libgfortran / generated / product_c4.c
blob68144dcfbe279cb619f2e60d82f6e7a9df3a9fd2
1 /* Implementation of the PRODUCT intrinsic
2 Copyright 2002 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
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.
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.)
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.
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. */
31 #include "config.h"
32 #include <stdlib.h>
33 #include <assert.h>
34 #include "libgfortran.h"
37 #if defined (HAVE_GFC_COMPLEX_4) && defined (HAVE_GFC_COMPLEX_4)
40 extern void product_c4 (gfc_array_c4 * const restrict,
41 gfc_array_c4 * const restrict, const index_type * const restrict);
42 export_proto(product_c4);
44 void
45 product_c4 (gfc_array_c4 * const restrict retarray,
46 gfc_array_c4 * const restrict array,
47 const index_type * const restrict pdim)
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_COMPLEX_4 * restrict base;
54 GFC_COMPLEX_4 * restrict dest;
55 index_type rank;
56 index_type n;
57 index_type len;
58 index_type delta;
59 index_type dim;
61 /* Make dim zero based to avoid confusion. */
62 dim = (*pdim) - 1;
63 rank = GFC_DESCRIPTOR_RANK (array) - 1;
65 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
66 delta = array->dim[dim].stride;
68 for (n = 0; n < dim; n++)
70 sstride[n] = array->dim[n].stride;
71 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
73 for (n = dim; n < rank; n++)
75 sstride[n] = array->dim[n + 1].stride;
76 extent[n] =
77 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
80 if (retarray->data == NULL)
82 for (n = 0; n < rank; n++)
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];
92 retarray->data
93 = internal_malloc_size (sizeof (GFC_COMPLEX_4)
94 * retarray->dim[rank-1].stride
95 * extent[rank-1]);
96 retarray->offset = 0;
97 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
99 else
101 if (rank != GFC_DESCRIPTOR_RANK (retarray))
102 runtime_error ("rank of return array incorrect");
105 for (n = 0; n < rank; n++)
107 count[n] = 0;
108 dstride[n] = retarray->dim[n].stride;
109 if (extent[n] <= 0)
110 len = 0;
113 base = array->data;
114 dest = retarray->data;
116 while (base)
118 const GFC_COMPLEX_4 * restrict src;
119 GFC_COMPLEX_4 result;
120 src = base;
123 result = 1;
124 if (len <= 0)
125 *dest = 1;
126 else
128 for (n = 0; n < len; n++, src += delta)
131 result *= *src;
133 *dest = result;
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])
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)
153 /* Break out of the look. */
154 base = NULL;
155 break;
157 else
159 count[n]++;
160 base += sstride[n];
161 dest += dstride[n];
168 extern void mproduct_c4 (gfc_array_c4 * const restrict,
169 gfc_array_c4 * const restrict, const index_type * const restrict,
170 gfc_array_l4 * const restrict);
171 export_proto(mproduct_c4);
173 void
174 mproduct_c4 (gfc_array_c4 * const restrict retarray,
175 gfc_array_c4 * const restrict array,
176 const index_type * const restrict pdim,
177 gfc_array_l4 * const restrict mask)
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_COMPLEX_4 * restrict dest;
185 const GFC_COMPLEX_4 * 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;
194 dim = (*pdim) - 1;
195 rank = GFC_DESCRIPTOR_RANK (array) - 1;
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;
203 for (n = 0; n < dim; n++)
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;
209 for (n = dim; n < rank; n++)
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;
217 if (retarray->data == NULL)
219 for (n = 0; n < rank; n++)
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];
229 retarray->data
230 = internal_malloc_size (sizeof (GFC_COMPLEX_4)
231 * retarray->dim[rank-1].stride
232 * extent[rank-1]);
233 retarray->offset = 0;
234 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
236 else
238 if (rank != GFC_DESCRIPTOR_RANK (retarray))
239 runtime_error ("rank of return array incorrect");
242 for (n = 0; n < rank; n++)
244 count[n] = 0;
245 dstride[n] = retarray->dim[n].stride;
246 if (extent[n] <= 0)
247 return;
250 dest = retarray->data;
251 base = array->data;
252 mbase = mask->data;
254 if (GFC_DESCRIPTOR_SIZE (mask) != 4)
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));
264 while (base)
266 const GFC_COMPLEX_4 * restrict src;
267 const GFC_LOGICAL_4 * restrict msrc;
268 GFC_COMPLEX_4 result;
269 src = base;
270 msrc = mbase;
273 result = 1;
274 if (len <= 0)
275 *dest = 1;
276 else
278 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
281 if (*msrc)
282 result *= *src;
284 *dest = result;
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])
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)
306 /* Break out of the look. */
307 base = NULL;
308 break;
310 else
312 count[n]++;
313 base += sstride[n];
314 mbase += mstride[n];
315 dest += dstride[n];
322 extern void sproduct_c4 (gfc_array_c4 * const restrict,
323 gfc_array_c4 * const restrict, const index_type * const restrict,
324 GFC_LOGICAL_4 *);
325 export_proto(sproduct_c4);
327 void
328 sproduct_c4 (gfc_array_c4 * const restrict retarray,
329 gfc_array_c4 * const restrict array,
330 const index_type * const restrict pdim,
331 GFC_LOGICAL_4 * mask)
333 index_type rank;
334 index_type n;
335 index_type dstride;
336 GFC_COMPLEX_4 *dest;
338 if (*mask)
340 product_c4 (retarray, array, pdim);
341 return;
343 rank = GFC_DESCRIPTOR_RANK (array);
344 if (rank <= 0)
345 runtime_error ("Rank of array needs to be > 0");
347 if (retarray->data == NULL)
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_COMPLEX_4) * rank);
356 else
358 if (GFC_DESCRIPTOR_RANK (retarray) != 1)
359 runtime_error ("rank of return array does not equal 1");
361 if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
362 runtime_error ("dimension of return array incorrect");
365 dstride = retarray->dim[0].stride;
366 dest = retarray->data;
368 for (n = 0; n < rank; n++)
369 dest[n * dstride] = 1 ;
372 #endif