2018-11-13 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgfortran / m4 / ifindloc1.m4
blob70638be793b669a44fd3289f465e4c3bc3df32f9
1 `/* Implementation of the FINDLOC intrinsic
2    Copyright (C) 2018 Free Software Foundation, Inc.
3    Contributed by Thomas König <tk@tkoenig.net>
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 3 of the License, or (at your option) any later version.
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 <http://www.gnu.org/licenses/>.  */
26 #include "libgfortran.h"
27 #include <assert.h>
29 #if defined (HAVE_'atype_name`)
30 'header1`
32   index_type count[GFC_MAX_DIMENSIONS];
33   index_type extent[GFC_MAX_DIMENSIONS];
34   index_type sstride[GFC_MAX_DIMENSIONS];
35   index_type dstride[GFC_MAX_DIMENSIONS];
36   const 'atype_name`'` * restrict base;
37   index_type * restrict dest;
38   index_type rank;
39   index_type n;
40   index_type len;
41   index_type delta;
42   index_type dim;
43   int continue_loop;
45   /* Make dim zero based to avoid confusion.  */
46   rank = GFC_DESCRIPTOR_RANK (array) - 1;
47   dim = (*pdim) - 1;
49   if (unlikely (dim < 0 || dim > rank))
50     {
51       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
52                      "is %ld, should be between 1 and %ld",
53                      (long int) dim + 1, (long int) rank + 1);
54     }
56   len = GFC_DESCRIPTOR_EXTENT(array,dim);
57   if (len < 0)
58     len = 0;
59   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
61   for (n = 0; n < dim; n++)
62     {
63       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
64       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
66       if (extent[n] < 0)
67         extent[n] = 0;
68     }
69   for (n = dim; n < rank; n++)
70     {
71       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
72       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
74       if (extent[n] < 0)
75         extent[n] = 0;
76     }
78   if (retarray->base_addr == NULL)
79     {
80       size_t alloc_size, str;
82       for (n = 0; n < rank; n++)
83         {
84           if (n == 0)
85             str = 1;
86           else
87             str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
89           GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
91         }
93       retarray->offset = 0;
94       retarray->dtype.rank = rank;
96       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
98       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
99       if (alloc_size == 0)
100         {
101           /* Make sure we have a zero-sized array.  */
102           GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
103           return;
104         }
105     }
106   else
107     {
108       if (rank != GFC_DESCRIPTOR_RANK (retarray))
109         runtime_error ("rank of return array incorrect in"
110                        " FINDLOC intrinsic: is %ld, should be %ld",
111                        (long int) (GFC_DESCRIPTOR_RANK (retarray)),
112                        (long int) rank);
114       if (unlikely (compile_options.bounds_check))
115         bounds_ifunction_return ((array_t *) retarray, extent,
116                                  "return value", "FINDLOC");
117     }
119   for (n = 0; n < rank; n++)
120     {
121       count[n] = 0;
122       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
123       if (extent[n] <= 0)
124         return;
125     }
127   dest = retarray->base_addr;
128   continue_loop = 1;
130   base = array->base_addr;
131   while (continue_loop)
132     {
133       const 'atype_name`'` * restrict src;
134       index_type result;
136       result = 0;
137       if (back)
138         {
139           src = base + (len - 1) * delta * 'base_mult`;
140           for (n = len; n > 0; n--, src -= delta * 'base_mult`)
141             {
142               if ('comparison`'`)
143                 {
144                   result = n;
145                   break;
146                 }
147             }
148         }
149       else
150         {
151           src = base;
152           for (n = 1; n <= len; n++, src += delta * 'base_mult`)
153             {
154               if ('comparison`'`)
155                 {
156                   result = n;
157                   break;
158                 }
159             }
160         }
161       *dest = result;
163       count[0]++;
164       base += sstride[0] * 'base_mult`;
165       dest += dstride[0];
166       n = 0;
167       while (count[n] == extent[n])
168         {
169           count[n] = 0;
170           base -= sstride[n] * extent[n] * 'base_mult`;
171           dest -= dstride[n] * extent[n];
172           n++;
173           if (n >= rank)
174             {
175               continue_loop = 0;
176               break;
177             }
178           else
179             {
180               count[n]++;
181               base += sstride[n] * 'base_mult`;
182               dest += dstride[n];
183             }
184         }
185     }
187 'header2`'`
189   index_type count[GFC_MAX_DIMENSIONS];
190   index_type extent[GFC_MAX_DIMENSIONS];
191   index_type sstride[GFC_MAX_DIMENSIONS];
192   index_type mstride[GFC_MAX_DIMENSIONS];
193   index_type dstride[GFC_MAX_DIMENSIONS];
194   const 'atype_name`'` * restrict base;
195   const GFC_LOGICAL_1 * restrict mbase;
196   index_type * restrict dest;
197   index_type rank;
198   index_type n;
199   index_type len;
200   index_type delta;
201   index_type mdelta;
202   index_type dim;
203   int mask_kind;
204   int continue_loop;
206   /* Make dim zero based to avoid confusion.  */
207   rank = GFC_DESCRIPTOR_RANK (array) - 1;
208   dim = (*pdim) - 1;
210   if (unlikely (dim < 0 || dim > rank))
211     {
212       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
213                      "is %ld, should be between 1 and %ld",
214                      (long int) dim + 1, (long int) rank + 1);
215     }
217   len = GFC_DESCRIPTOR_EXTENT(array,dim);
218   if (len < 0)
219     len = 0;
221   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
222   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
224   mbase = mask->base_addr;
226   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
228   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
229 #ifdef HAVE_GFC_LOGICAL_16
230       || mask_kind == 16
231 #endif
232       )
233     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
234   else
235     internal_error (NULL, "Funny sized logical array");
237   for (n = 0; n < dim; n++)
238     {
239       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
240       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
241       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
243       if (extent[n] < 0)
244         extent[n] = 0;
245     }
246   for (n = dim; n < rank; n++)
247     {
248       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
249       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
250       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
252       if (extent[n] < 0)
253         extent[n] = 0;
254     }
256   if (retarray->base_addr == NULL)
257     {
258       size_t alloc_size, str;
260       for (n = 0; n < rank; n++)
261         {
262           if (n == 0)
263             str = 1;
264           else
265             str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
267           GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
269         }
271       retarray->offset = 0;
272       retarray->dtype.rank = rank;
274       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
276       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
277       if (alloc_size == 0)
278         {
279           /* Make sure we have a zero-sized array.  */
280           GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
281           return;
282         }
283     }
284   else
285     {
286       if (rank != GFC_DESCRIPTOR_RANK (retarray))
287         runtime_error ("rank of return array incorrect in"
288                        " FINDLOC intrinsic: is %ld, should be %ld",
289                        (long int) (GFC_DESCRIPTOR_RANK (retarray)),
290                        (long int) rank);
292       if (unlikely (compile_options.bounds_check))
293         bounds_ifunction_return ((array_t *) retarray, extent,
294                                  "return value", "FINDLOC");
295     }
297   for (n = 0; n < rank; n++)
298     {
299       count[n] = 0;
300       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
301       if (extent[n] <= 0)
302         return;
303     }
305   dest = retarray->base_addr;
306   continue_loop = 1;
308   base = array->base_addr;
309   while (continue_loop)
310     {
311       const 'atype_name`'` * restrict src;
312       const GFC_LOGICAL_1 * restrict msrc;
313       index_type result;
315       result = 0;
316       if (back)
317         {
318           src = base + (len - 1) * delta * 'base_mult`;
319           msrc = mbase + (len - 1) * mdelta; 
320           for (n = len; n > 0; n--, src -= delta * 'base_mult`, msrc -= mdelta)
321             {
322               if (*msrc && 'comparison`'`)
323                 {
324                   result = n;
325                   break;
326                 }
327             }
328         }
329       else
330         {
331           src = base;
332           msrc = mbase;
333           for (n = 1; n <= len; n++, src += delta * 'base_mult`, msrc += mdelta)
334             {
335               if (*msrc && 'comparison`'`)
336                 {
337                   result = n;
338                   break;
339                 }
340             }
341         }
342       *dest = result;
344       count[0]++;
345       base += sstride[0] * 'base_mult`;
346       mbase += mstride[0];
347       dest += dstride[0];
348       n = 0;
349       while (count[n] == extent[n])
350         {
351           count[n] = 0;
352           base -= sstride[n] * extent[n] * 'base_mult`;
353           mbase -= mstride[n] * extent[n];
354           dest -= dstride[n] * extent[n];
355           n++;
356           if (n >= rank)
357             {
358               continue_loop = 0;
359               break;
360             }
361           else
362             {
363               count[n]++;
364               base += sstride[n] * 'base_mult`;
365               dest += dstride[n];
366             }
367         }
368     }
370 'header3`'`
372   index_type count[GFC_MAX_DIMENSIONS];
373   index_type extent[GFC_MAX_DIMENSIONS];
374   index_type dstride[GFC_MAX_DIMENSIONS];
375   index_type * restrict dest;
376   index_type rank;
377   index_type n;
378   index_type len;
379   index_type dim;
380   bool continue_loop;
382   if (*mask)
383     {
384       findloc1_'atype_code`'` (retarray, array, value, pdim, back'len_arg`'`);
385       return;
386     }
387     /* Make dim zero based to avoid confusion.  */
388   rank = GFC_DESCRIPTOR_RANK (array) - 1;
389   dim = (*pdim) - 1;
391   if (unlikely (dim < 0 || dim > rank))
392     {
393       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
394                      "is %ld, should be between 1 and %ld",
395                      (long int) dim + 1, (long int) rank + 1);
396     }
398   len = GFC_DESCRIPTOR_EXTENT(array,dim);
399   if (len < 0)
400     len = 0;
402   for (n = 0; n < dim; n++)
403     {
404       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
406       if (extent[n] <= 0)
407         extent[n] = 0;
408     }
410   for (n = dim; n < rank; n++)
411     {
412       extent[n] =
413         GFC_DESCRIPTOR_EXTENT(array,n + 1);
415       if (extent[n] <= 0)
416         extent[n] = 0;
417     }
420   if (retarray->base_addr == NULL)
421     {
422       size_t alloc_size, str;
424       for (n = 0; n < rank; n++)
425         {
426           if (n == 0)
427             str = 1;
428           else
429             str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
431           GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
432         }
434       retarray->offset = 0;
435       retarray->dtype.rank = rank;
437       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
439       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
440       if (alloc_size == 0)
441         {
442           /* Make sure we have a zero-sized array.  */
443           GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
444           return;
445         }
446     }
447   else
448     {
449       if (rank != GFC_DESCRIPTOR_RANK (retarray))
450         runtime_error ("rank of return array incorrect in"
451                        " FINDLOC intrinsic: is %ld, should be %ld",
452                        (long int) (GFC_DESCRIPTOR_RANK (retarray)),
453                        (long int) rank);
455       if (unlikely (compile_options.bounds_check))
456         bounds_ifunction_return ((array_t *) retarray, extent,
457                                  "return value", "FINDLOC");
458     }
460   for (n = 0; n < rank; n++)
461     {
462       count[n] = 0;
463       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
464       if (extent[n] <= 0)
465         return;
466     }
467   dest = retarray->base_addr;
468   continue_loop = 1;
470   while (continue_loop)
471     {
472       *dest = 0;
474       count[0]++;
475       dest += dstride[0];
476       n = 0;
477       while (count[n] == extent[n])
478         {
479           count[n] = 0;
480           dest -= dstride[n] * extent[n];
481           n++;
482           if (n >= rank)
483             {
484               continue_loop = 0;
485               break;
486             }
487           else
488             {
489               count[n]++;
490               dest += dstride[n];
491             }
492         }
493     }
495 #endif'