OSDN Git Service

2005-05-04 Thomas Koenig <Thomas.Koenig@online.de>
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / minloc1_4_i8.c
1 /* Implementation of the MINLOC 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., 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.  */
30
31 #include "config.h"
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <float.h>
35 #include <limits.h>
36 #include "libgfortran.h"
37
38
39 extern void minloc1_4_i8 (gfc_array_i4 *, gfc_array_i8 *, index_type *);
40 export_proto(minloc1_4_i8);
41
42 void
43 minloc1_4_i8 (gfc_array_i4 *retarray, gfc_array_i8 *array, index_type *pdim)
44 {
45   index_type count[GFC_MAX_DIMENSIONS];
46   index_type extent[GFC_MAX_DIMENSIONS];
47   index_type sstride[GFC_MAX_DIMENSIONS];
48   index_type dstride[GFC_MAX_DIMENSIONS];
49   GFC_INTEGER_8 *base;
50   GFC_INTEGER_4 *dest;
51   index_type rank;
52   index_type n;
53   index_type len;
54   index_type delta;
55   index_type dim;
56
57   /* Make dim zero based to avoid confusion.  */
58   dim = (*pdim) - 1;
59   rank = GFC_DESCRIPTOR_RANK (array) - 1;
60
61   /* TODO:  It should be a front end job to correctly set the strides.  */
62
63   if (array->dim[0].stride == 0)
64     array->dim[0].stride = 1;
65
66   len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
67   delta = array->dim[dim].stride;
68
69   for (n = 0; n < dim; n++)
70     {
71       sstride[n] = array->dim[n].stride;
72       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
73     }
74   for (n = dim; n < rank; n++)
75     {
76       sstride[n] = array->dim[n + 1].stride;
77       extent[n] =
78         array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
79     }
80
81   if (retarray->data == NULL)
82     {
83       for (n = 0; n < rank; n++)
84         {
85           retarray->dim[n].lbound = 0;
86           retarray->dim[n].ubound = extent[n]-1;
87           if (n == 0)
88             retarray->dim[n].stride = 1;
89           else
90             retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
91         }
92
93       retarray->data
94          = internal_malloc_size (sizeof (GFC_INTEGER_4)
95                                  * retarray->dim[rank-1].stride
96                                  * extent[rank-1]);
97       retarray->base = 0;
98       retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
99     }
100   else
101     {
102       if (retarray->dim[0].stride == 0)
103         retarray->dim[0].stride = 1;
104
105       if (rank != GFC_DESCRIPTOR_RANK (retarray))
106         runtime_error ("rank of return array incorrect");
107     }
108
109   for (n = 0; n < rank; n++)
110     {
111       count[n] = 0;
112       dstride[n] = retarray->dim[n].stride;
113       if (extent[n] <= 0)
114         len = 0;
115     }
116
117   base = array->data;
118   dest = retarray->data;
119
120   while (base)
121     {
122       GFC_INTEGER_8 *src;
123       GFC_INTEGER_4 result;
124       src = base;
125       {
126
127   GFC_INTEGER_8 minval;
128   minval = GFC_INTEGER_8_HUGE;
129   result = 1;
130         if (len <= 0)
131           *dest = 0;
132         else
133           {
134             for (n = 0; n < len; n++, src += delta)
135               {
136
137   if (*src < minval)
138     {
139       minval = *src;
140       result = (GFC_INTEGER_4)n + 1;
141     }
142           }
143             *dest = result;
144           }
145       }
146       /* Advance to the next element.  */
147       count[0]++;
148       base += sstride[0];
149       dest += dstride[0];
150       n = 0;
151       while (count[n] == extent[n])
152         {
153           /* When we get to the end of a dimension, reset it and increment
154              the next dimension.  */
155           count[n] = 0;
156           /* We could precalculate these products, but this is a less
157              frequently used path so proabably not worth it.  */
158           base -= sstride[n] * extent[n];
159           dest -= dstride[n] * extent[n];
160           n++;
161           if (n == rank)
162             {
163               /* Break out of the look.  */
164               base = NULL;
165               break;
166             }
167           else
168             {
169               count[n]++;
170               base += sstride[n];
171               dest += dstride[n];
172             }
173         }
174     }
175 }
176
177
178 extern void mminloc1_4_i8 (gfc_array_i4 *, gfc_array_i8 *, index_type *,
179                                                gfc_array_l4 *);
180 export_proto(mminloc1_4_i8);
181
182 void
183 mminloc1_4_i8 (gfc_array_i4 * retarray, gfc_array_i8 * array,
184                                   index_type *pdim, gfc_array_l4 * mask)
185 {
186   index_type count[GFC_MAX_DIMENSIONS];
187   index_type extent[GFC_MAX_DIMENSIONS];
188   index_type sstride[GFC_MAX_DIMENSIONS];
189   index_type dstride[GFC_MAX_DIMENSIONS];
190   index_type mstride[GFC_MAX_DIMENSIONS];
191   GFC_INTEGER_4 *dest;
192   GFC_INTEGER_8 *base;
193   GFC_LOGICAL_4 *mbase;
194   int rank;
195   int dim;
196   index_type n;
197   index_type len;
198   index_type delta;
199   index_type mdelta;
200
201   dim = (*pdim) - 1;
202   rank = GFC_DESCRIPTOR_RANK (array) - 1;
203
204   /* TODO:  It should be a front end job to correctly set the strides.  */
205
206   if (array->dim[0].stride == 0)
207     array->dim[0].stride = 1;
208
209   if (mask->dim[0].stride == 0)
210     mask->dim[0].stride = 1;
211
212   len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
213   if (len <= 0)
214     return;
215   delta = array->dim[dim].stride;
216   mdelta = mask->dim[dim].stride;
217
218   for (n = 0; n < dim; n++)
219     {
220       sstride[n] = array->dim[n].stride;
221       mstride[n] = mask->dim[n].stride;
222       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
223     }
224   for (n = dim; n < rank; n++)
225     {
226       sstride[n] = array->dim[n + 1].stride;
227       mstride[n] = mask->dim[n + 1].stride;
228       extent[n] =
229         array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
230     }
231
232   if (retarray->data == NULL)
233     {
234       for (n = 0; n < rank; n++)
235         {
236           retarray->dim[n].lbound = 0;
237           retarray->dim[n].ubound = extent[n]-1;
238           if (n == 0)
239             retarray->dim[n].stride = 1;
240           else
241             retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
242         }
243
244       retarray->data
245          = internal_malloc_size (sizeof (GFC_INTEGER_4)
246                                  * retarray->dim[rank-1].stride
247                                  * extent[rank-1]);
248       retarray->base = 0;
249       retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
250     }
251   else
252     {
253       if (retarray->dim[0].stride == 0)
254         retarray->dim[0].stride = 1;
255
256       if (rank != GFC_DESCRIPTOR_RANK (retarray))
257         runtime_error ("rank of return array incorrect");
258     }
259
260   for (n = 0; n < rank; n++)
261     {
262       count[n] = 0;
263       dstride[n] = retarray->dim[n].stride;
264       if (extent[n] <= 0)
265         return;
266     }
267
268   dest = retarray->data;
269   base = array->data;
270   mbase = mask->data;
271
272   if (GFC_DESCRIPTOR_SIZE (mask) != 4)
273     {
274       /* This allows the same loop to be used for all logical types.  */
275       assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
276       for (n = 0; n < rank; n++)
277         mstride[n] <<= 1;
278       mdelta <<= 1;
279       mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
280     }
281
282   while (base)
283     {
284       GFC_INTEGER_8 *src;
285       GFC_LOGICAL_4 *msrc;
286       GFC_INTEGER_4 result;
287       src = base;
288       msrc = mbase;
289       {
290
291   GFC_INTEGER_8 minval;
292   minval = GFC_INTEGER_8_HUGE;
293   result = 1;
294         if (len <= 0)
295           *dest = 0;
296         else
297           {
298             for (n = 0; n < len; n++, src += delta, msrc += mdelta)
299               {
300
301   if (*msrc && *src < minval)
302     {
303       minval = *src;
304       result = (GFC_INTEGER_4)n + 1;
305     }
306               }
307             *dest = result;
308           }
309       }
310       /* Advance to the next element.  */
311       count[0]++;
312       base += sstride[0];
313       mbase += mstride[0];
314       dest += dstride[0];
315       n = 0;
316       while (count[n] == extent[n])
317         {
318           /* When we get to the end of a dimension, reset it and increment
319              the next dimension.  */
320           count[n] = 0;
321           /* We could precalculate these products, but this is a less
322              frequently used path so proabably not worth it.  */
323           base -= sstride[n] * extent[n];
324           mbase -= mstride[n] * extent[n];
325           dest -= dstride[n] * extent[n];
326           n++;
327           if (n == rank)
328             {
329               /* Break out of the look.  */
330               base = NULL;
331               break;
332             }
333           else
334             {
335               count[n]++;
336               base += sstride[n];
337               mbase += mstride[n];
338               dest += dstride[n];
339             }
340         }
341     }
342 }
343