Merged with mainline at revision 128810.
[official-gcc.git] / libgfortran / generated / maxloc1_16_r4.c
blobbe979ad6cb02e3370e0ceb4d4dd1f222cc25099c
1 /* Implementation of the MAXLOC intrinsic
2 Copyright 2002, 2007 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 "libgfortran.h"
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <limits.h>
37 #if defined (HAVE_GFC_REAL_4) && defined (HAVE_GFC_INTEGER_16)
40 extern void maxloc1_16_r4 (gfc_array_i16 * const restrict,
41 gfc_array_r4 * const restrict, const index_type * const restrict);
42 export_proto(maxloc1_16_r4);
44 void
45 maxloc1_16_r4 (gfc_array_i16 * const restrict retarray,
46 gfc_array_r4 * 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_REAL_4 * restrict base;
54 GFC_INTEGER_16 * 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 if (extent[n] < 0)
74 extent[n] = 0;
76 for (n = dim; n < rank; n++)
78 sstride[n] = array->dim[n + 1].stride;
79 extent[n] =
80 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
82 if (extent[n] < 0)
83 extent[n] = 0;
86 if (retarray->data == NULL)
88 size_t alloc_size;
90 for (n = 0; n < rank; n++)
92 retarray->dim[n].lbound = 0;
93 retarray->dim[n].ubound = extent[n]-1;
94 if (n == 0)
95 retarray->dim[n].stride = 1;
96 else
97 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
100 retarray->offset = 0;
101 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
103 alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
104 * extent[rank-1];
106 if (alloc_size == 0)
108 /* Make sure we have a zero-sized array. */
109 retarray->dim[0].lbound = 0;
110 retarray->dim[0].ubound = -1;
111 return;
113 else
114 retarray->data = internal_malloc_size (alloc_size);
116 else
118 if (rank != GFC_DESCRIPTOR_RANK (retarray))
119 runtime_error ("rank of return array incorrect");
122 for (n = 0; n < rank; n++)
124 count[n] = 0;
125 dstride[n] = retarray->dim[n].stride;
126 if (extent[n] <= 0)
127 len = 0;
130 base = array->data;
131 dest = retarray->data;
133 while (base)
135 const GFC_REAL_4 * restrict src;
136 GFC_INTEGER_16 result;
137 src = base;
140 GFC_REAL_4 maxval;
141 maxval = -GFC_REAL_4_HUGE;
142 result = 0;
143 if (len <= 0)
144 *dest = 0;
145 else
147 for (n = 0; n < len; n++, src += delta)
150 if (*src > maxval || !result)
152 maxval = *src;
153 result = (GFC_INTEGER_16)n + 1;
156 *dest = result;
159 /* Advance to the next element. */
160 count[0]++;
161 base += sstride[0];
162 dest += dstride[0];
163 n = 0;
164 while (count[n] == extent[n])
166 /* When we get to the end of a dimension, reset it and increment
167 the next dimension. */
168 count[n] = 0;
169 /* We could precalculate these products, but this is a less
170 frequently used path so probably not worth it. */
171 base -= sstride[n] * extent[n];
172 dest -= dstride[n] * extent[n];
173 n++;
174 if (n == rank)
176 /* Break out of the look. */
177 base = NULL;
178 break;
180 else
182 count[n]++;
183 base += sstride[n];
184 dest += dstride[n];
191 extern void mmaxloc1_16_r4 (gfc_array_i16 * const restrict,
192 gfc_array_r4 * const restrict, const index_type * const restrict,
193 gfc_array_l1 * const restrict);
194 export_proto(mmaxloc1_16_r4);
196 void
197 mmaxloc1_16_r4 (gfc_array_i16 * const restrict retarray,
198 gfc_array_r4 * const restrict array,
199 const index_type * const restrict pdim,
200 gfc_array_l1 * const restrict mask)
202 index_type count[GFC_MAX_DIMENSIONS];
203 index_type extent[GFC_MAX_DIMENSIONS];
204 index_type sstride[GFC_MAX_DIMENSIONS];
205 index_type dstride[GFC_MAX_DIMENSIONS];
206 index_type mstride[GFC_MAX_DIMENSIONS];
207 GFC_INTEGER_16 * restrict dest;
208 const GFC_REAL_4 * restrict base;
209 const GFC_LOGICAL_1 * restrict mbase;
210 int rank;
211 int dim;
212 index_type n;
213 index_type len;
214 index_type delta;
215 index_type mdelta;
216 int mask_kind;
218 dim = (*pdim) - 1;
219 rank = GFC_DESCRIPTOR_RANK (array) - 1;
221 len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
222 if (len <= 0)
223 return;
225 mbase = mask->data;
227 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
229 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
230 #ifdef HAVE_GFC_LOGICAL_16
231 || mask_kind == 16
232 #endif
234 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
235 else
236 runtime_error ("Funny sized logical array");
238 delta = array->dim[dim].stride;
239 mdelta = mask->dim[dim].stride * mask_kind;
241 for (n = 0; n < dim; n++)
243 sstride[n] = array->dim[n].stride;
244 mstride[n] = mask->dim[n].stride * mask_kind;
245 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
247 if (extent[n] < 0)
248 extent[n] = 0;
251 for (n = dim; n < rank; n++)
253 sstride[n] = array->dim[n + 1].stride;
254 mstride[n] = mask->dim[n + 1].stride * mask_kind;
255 extent[n] =
256 array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
258 if (extent[n] < 0)
259 extent[n] = 0;
262 if (retarray->data == NULL)
264 size_t alloc_size;
266 for (n = 0; n < rank; n++)
268 retarray->dim[n].lbound = 0;
269 retarray->dim[n].ubound = extent[n]-1;
270 if (n == 0)
271 retarray->dim[n].stride = 1;
272 else
273 retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
276 alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
277 * extent[rank-1];
279 retarray->offset = 0;
280 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
282 if (alloc_size == 0)
284 /* Make sure we have a zero-sized array. */
285 retarray->dim[0].lbound = 0;
286 retarray->dim[0].ubound = -1;
287 return;
289 else
290 retarray->data = internal_malloc_size (alloc_size);
293 else
295 if (rank != GFC_DESCRIPTOR_RANK (retarray))
296 runtime_error ("rank of return array incorrect");
299 for (n = 0; n < rank; n++)
301 count[n] = 0;
302 dstride[n] = retarray->dim[n].stride;
303 if (extent[n] <= 0)
304 return;
307 dest = retarray->data;
308 base = array->data;
310 while (base)
312 const GFC_REAL_4 * restrict src;
313 const GFC_LOGICAL_1 * restrict msrc;
314 GFC_INTEGER_16 result;
315 src = base;
316 msrc = mbase;
319 GFC_REAL_4 maxval;
320 maxval = -GFC_REAL_4_HUGE;
321 result = 0;
322 if (len <= 0)
323 *dest = 0;
324 else
326 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
329 if (*msrc && (*src > maxval || !result))
331 maxval = *src;
332 result = (GFC_INTEGER_16)n + 1;
335 *dest = result;
338 /* Advance to the next element. */
339 count[0]++;
340 base += sstride[0];
341 mbase += mstride[0];
342 dest += dstride[0];
343 n = 0;
344 while (count[n] == extent[n])
346 /* When we get to the end of a dimension, reset it and increment
347 the next dimension. */
348 count[n] = 0;
349 /* We could precalculate these products, but this is a less
350 frequently used path so probably not worth it. */
351 base -= sstride[n] * extent[n];
352 mbase -= mstride[n] * extent[n];
353 dest -= dstride[n] * extent[n];
354 n++;
355 if (n == rank)
357 /* Break out of the look. */
358 base = NULL;
359 break;
361 else
363 count[n]++;
364 base += sstride[n];
365 mbase += mstride[n];
366 dest += dstride[n];
373 extern void smaxloc1_16_r4 (gfc_array_i16 * const restrict,
374 gfc_array_r4 * const restrict, const index_type * const restrict,
375 GFC_LOGICAL_4 *);
376 export_proto(smaxloc1_16_r4);
378 void
379 smaxloc1_16_r4 (gfc_array_i16 * const restrict retarray,
380 gfc_array_r4 * const restrict array,
381 const index_type * const restrict pdim,
382 GFC_LOGICAL_4 * mask)
384 index_type rank;
385 index_type n;
386 index_type dstride;
387 GFC_INTEGER_16 *dest;
389 if (*mask)
391 maxloc1_16_r4 (retarray, array, pdim);
392 return;
394 rank = GFC_DESCRIPTOR_RANK (array);
395 if (rank <= 0)
396 runtime_error ("Rank of array needs to be > 0");
398 if (retarray->data == NULL)
400 retarray->dim[0].lbound = 0;
401 retarray->dim[0].ubound = rank-1;
402 retarray->dim[0].stride = 1;
403 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
404 retarray->offset = 0;
405 retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
407 else
409 if (GFC_DESCRIPTOR_RANK (retarray) != 1)
410 runtime_error ("rank of return array does not equal 1");
412 if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
413 runtime_error ("dimension of return array incorrect");
416 dstride = retarray->dim[0].stride;
417 dest = retarray->data;
419 for (n = 0; n < rank; n++)
420 dest[n * dstride] = 0 ;
423 #endif