OSDN Git Service

63dd21a7766e8bb4b8eedb86ba926f50442ad9c4
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / minloc0_8_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., 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 <float.h>
35 #include <limits.h>
36 #include "libgfortran.h"
37
38
39 #if defined (HAVE_GFC_INTEGER_8) && defined (HAVE_GFC_INTEGER_8)
40
41
42 extern void minloc0_8_i8 (gfc_array_i8 * const restrict retarray, 
43         gfc_array_i8 * const restrict array);
44 export_proto(minloc0_8_i8);
45
46 void
47 minloc0_8_i8 (gfc_array_i8 * const restrict retarray, 
48         gfc_array_i8 * const restrict array)
49 {
50   index_type count[GFC_MAX_DIMENSIONS];
51   index_type extent[GFC_MAX_DIMENSIONS];
52   index_type sstride[GFC_MAX_DIMENSIONS];
53   index_type dstride;
54   const GFC_INTEGER_8 *base;
55   GFC_INTEGER_8 *dest;
56   index_type rank;
57   index_type n;
58
59   rank = GFC_DESCRIPTOR_RANK (array);
60   if (rank <= 0)
61     runtime_error ("Rank of array needs to be > 0");
62
63   if (retarray->data == NULL)
64     {
65       retarray->dim[0].lbound = 0;
66       retarray->dim[0].ubound = rank-1;
67       retarray->dim[0].stride = 1;
68       retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
69       retarray->offset = 0;
70       retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
71     }
72   else
73     {
74       if (GFC_DESCRIPTOR_RANK (retarray) != 1)
75         runtime_error ("rank of return array does not equal 1");
76
77       if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
78         runtime_error ("dimension of return array incorrect");
79
80       if (retarray->dim[0].stride == 0)
81         retarray->dim[0].stride = 1;
82     }
83
84   /* TODO:  It should be a front end job to correctly set the strides.  */
85
86   if (array->dim[0].stride == 0)
87     array->dim[0].stride = 1;
88
89   dstride = retarray->dim[0].stride;
90   dest = retarray->data;
91   for (n = 0; n < rank; n++)
92     {
93       sstride[n] = array->dim[n].stride;
94       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
95       count[n] = 0;
96       if (extent[n] <= 0)
97         {
98           /* Set the return value.  */
99           for (n = 0; n < rank; n++)
100             dest[n * dstride] = 0;
101           return;
102         }
103     }
104
105   base = array->data;
106
107   /* Initialize the return value.  */
108   for (n = 0; n < rank; n++)
109     dest[n * dstride] = 0;
110   {
111
112   GFC_INTEGER_8 minval;
113
114   minval = GFC_INTEGER_8_HUGE;
115
116   while (base)
117     {
118       {
119         /* Implementation start.  */
120
121   if (*base < minval || !dest[0])
122     {
123       minval = *base;
124       for (n = 0; n < rank; n++)
125         dest[n * dstride] = count[n] + 1;
126     }
127         /* Implementation end.  */
128       }
129       /* Advance to the next element.  */
130       count[0]++;
131       base += sstride[0];
132       n = 0;
133       while (count[n] == extent[n])
134         {
135           /* When we get to the end of a dimension, reset it and increment
136              the next dimension.  */
137           count[n] = 0;
138           /* We could precalculate these products, but this is a less
139              frequently used path so proabably not worth it.  */
140           base -= sstride[n] * extent[n];
141           n++;
142           if (n == rank)
143             {
144               /* Break out of the loop.  */
145               base = NULL;
146               break;
147             }
148           else
149             {
150               count[n]++;
151               base += sstride[n];
152             }
153         }
154     }
155   }
156 }
157
158
159 extern void mminloc0_8_i8 (gfc_array_i8 * const restrict, 
160         gfc_array_i8 * const restrict, gfc_array_l4 * const restrict);
161 export_proto(mminloc0_8_i8);
162
163 void
164 mminloc0_8_i8 (gfc_array_i8 * const restrict retarray, 
165         gfc_array_i8 * const restrict array,
166         gfc_array_l4 * const restrict mask)
167 {
168   index_type count[GFC_MAX_DIMENSIONS];
169   index_type extent[GFC_MAX_DIMENSIONS];
170   index_type sstride[GFC_MAX_DIMENSIONS];
171   index_type mstride[GFC_MAX_DIMENSIONS];
172   index_type dstride;
173   GFC_INTEGER_8 *dest;
174   const GFC_INTEGER_8 *base;
175   GFC_LOGICAL_4 *mbase;
176   int rank;
177   index_type n;
178
179   rank = GFC_DESCRIPTOR_RANK (array);
180   if (rank <= 0)
181     runtime_error ("Rank of array needs to be > 0");
182
183   if (retarray->data == NULL)
184     {
185       retarray->dim[0].lbound = 0;
186       retarray->dim[0].ubound = rank-1;
187       retarray->dim[0].stride = 1;
188       retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
189       retarray->offset = 0;
190       retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
191     }
192   else
193     {
194       if (GFC_DESCRIPTOR_RANK (retarray) != 1)
195         runtime_error ("rank of return array does not equal 1");
196
197       if (retarray->dim[0].ubound + 1 - retarray->dim[0].lbound != rank)
198         runtime_error ("dimension of return array incorrect");
199
200       if (retarray->dim[0].stride == 0)
201         retarray->dim[0].stride = 1;
202     }
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   dstride = retarray->dim[0].stride;
213   dest = retarray->data;
214   for (n = 0; n < rank; n++)
215     {
216       sstride[n] = array->dim[n].stride;
217       mstride[n] = mask->dim[n].stride;
218       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
219       count[n] = 0;
220       if (extent[n] <= 0)
221         {
222           /* Set the return value.  */
223           for (n = 0; n < rank; n++)
224             dest[n * dstride] = 0;
225           return;
226         }
227     }
228
229   base = array->data;
230   mbase = mask->data;
231
232   if (GFC_DESCRIPTOR_SIZE (mask) != 4)
233     {
234       /* This allows the same loop to be used for all logical types.  */
235       assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
236       for (n = 0; n < rank; n++)
237         mstride[n] <<= 1;
238       mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
239     }
240
241
242   /* Initialize the return value.  */
243   for (n = 0; n < rank; n++)
244     dest[n * dstride] = 0;
245   {
246
247   GFC_INTEGER_8 minval;
248
249   minval = GFC_INTEGER_8_HUGE;
250
251   while (base)
252     {
253       {
254         /* Implementation start.  */
255
256   if (*mbase && (*base < minval || !dest[0]))
257     {
258       minval = *base;
259       for (n = 0; n < rank; n++)
260         dest[n * dstride] = count[n] + 1;
261     }
262         /* Implementation end.  */
263       }
264       /* Advance to the next element.  */
265       count[0]++;
266       base += sstride[0];
267       mbase += mstride[0];
268       n = 0;
269       while (count[n] == extent[n])
270         {
271           /* When we get to the end of a dimension, reset it and increment
272              the next dimension.  */
273           count[n] = 0;
274           /* We could precalculate these products, but this is a less
275              frequently used path so proabably not worth it.  */
276           base -= sstride[n] * extent[n];
277           mbase -= mstride[n] * extent[n];
278           n++;
279           if (n == rank)
280             {
281               /* Break out of the loop.  */
282               base = NULL;
283               break;
284             }
285           else
286             {
287               count[n]++;
288               base += sstride[n];
289               mbase += mstride[n];
290             }
291         }
292     }
293   }
294 }
295
296 #endif