xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/any_l1.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1181254a7Smrg /* Implementation of the ANY intrinsic
2*b1e83836Smrg    Copyright (C) 2002-2022 Free Software Foundation, Inc.
3181254a7Smrg    Contributed by Paul Brook <paul@nowt.org>
4181254a7Smrg 
5181254a7Smrg This file is part of the GNU Fortran runtime library (libgfortran).
6181254a7Smrg 
7181254a7Smrg Libgfortran is free software; you can redistribute it and/or
8181254a7Smrg modify it under the terms of the GNU General Public
9181254a7Smrg License as published by the Free Software Foundation; either
10181254a7Smrg version 3 of the License, or (at your option) any later version.
11181254a7Smrg 
12181254a7Smrg Libgfortran is distributed in the hope that it will be useful,
13181254a7Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14181254a7Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15181254a7Smrg GNU General Public License for more details.
16181254a7Smrg 
17181254a7Smrg Under Section 7 of GPL version 3, you are granted additional
18181254a7Smrg permissions described in the GCC Runtime Library Exception, version
19181254a7Smrg 3.1, as published by the Free Software Foundation.
20181254a7Smrg 
21181254a7Smrg You should have received a copy of the GNU General Public License and
22181254a7Smrg a copy of the GCC Runtime Library Exception along with this program;
23181254a7Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24181254a7Smrg <http://www.gnu.org/licenses/>.  */
25181254a7Smrg 
26181254a7Smrg #include "libgfortran.h"
27181254a7Smrg 
28181254a7Smrg 
29181254a7Smrg #if defined (HAVE_GFC_LOGICAL_1)
30181254a7Smrg 
31181254a7Smrg 
32181254a7Smrg extern void any_l1 (gfc_array_l1 * const restrict,
33181254a7Smrg 	gfc_array_l1 * const restrict, const index_type * const restrict);
34181254a7Smrg export_proto(any_l1);
35181254a7Smrg 
36181254a7Smrg void
any_l1(gfc_array_l1 * const restrict retarray,gfc_array_l1 * const restrict array,const index_type * const restrict pdim)37181254a7Smrg any_l1 (gfc_array_l1 * const restrict retarray,
38181254a7Smrg 	gfc_array_l1 * const restrict array,
39181254a7Smrg 	const index_type * const restrict pdim)
40181254a7Smrg {
41181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
42181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
43181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
44181254a7Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
45181254a7Smrg   const GFC_LOGICAL_1 * restrict base;
46181254a7Smrg   GFC_LOGICAL_1 * restrict dest;
47181254a7Smrg   index_type rank;
48181254a7Smrg   index_type n;
49181254a7Smrg   index_type len;
50181254a7Smrg   index_type delta;
51181254a7Smrg   index_type dim;
52181254a7Smrg   int src_kind;
53181254a7Smrg   int continue_loop;
54181254a7Smrg 
55181254a7Smrg   /* Make dim zero based to avoid confusion.  */
56181254a7Smrg   dim = (*pdim) - 1;
57181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
58181254a7Smrg 
59181254a7Smrg   src_kind = GFC_DESCRIPTOR_SIZE (array);
60181254a7Smrg 
61181254a7Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
62181254a7Smrg   if (len < 0)
63181254a7Smrg     len = 0;
64181254a7Smrg 
65181254a7Smrg   delta = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
66181254a7Smrg 
67181254a7Smrg   for (n = 0; n < dim; n++)
68181254a7Smrg     {
69181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n);
70181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
71181254a7Smrg 
72181254a7Smrg       if (extent[n] < 0)
73181254a7Smrg 	extent[n] = 0;
74181254a7Smrg     }
75181254a7Smrg   for (n = dim; n < rank; n++)
76181254a7Smrg     {
77181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n + 1);
78181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1);
79181254a7Smrg 
80181254a7Smrg       if (extent[n] < 0)
81181254a7Smrg 	extent[n] = 0;
82181254a7Smrg     }
83181254a7Smrg 
84181254a7Smrg   if (retarray->base_addr == NULL)
85181254a7Smrg     {
86181254a7Smrg       size_t alloc_size, str;
87181254a7Smrg 
88181254a7Smrg       for (n = 0; n < rank; n++)
89181254a7Smrg         {
90181254a7Smrg           if (n == 0)
91181254a7Smrg             str = 1;
92181254a7Smrg           else
93181254a7Smrg             str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
94181254a7Smrg 
95181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
96181254a7Smrg 
97181254a7Smrg         }
98181254a7Smrg 
99181254a7Smrg       retarray->offset = 0;
100181254a7Smrg       retarray->dtype.rank = rank;
101181254a7Smrg 
102181254a7Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
103181254a7Smrg 
104181254a7Smrg       if (alloc_size == 0)
105181254a7Smrg 	{
106181254a7Smrg 	  /* Make sure we have a zero-sized array.  */
107181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
108181254a7Smrg 	  return;
109181254a7Smrg 	}
110181254a7Smrg       else
111181254a7Smrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_LOGICAL_1));
112181254a7Smrg     }
113181254a7Smrg   else
114181254a7Smrg     {
115181254a7Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
116181254a7Smrg 	runtime_error ("rank of return array incorrect in"
117181254a7Smrg 		       " ANY intrinsic: is %ld, should be %ld",
118181254a7Smrg 		       (long int) GFC_DESCRIPTOR_RANK (retarray),
119181254a7Smrg 		       (long int) rank);
120181254a7Smrg 
121181254a7Smrg       if (unlikely (compile_options.bounds_check))
122181254a7Smrg 	{
123181254a7Smrg 	  for (n=0; n < rank; n++)
124181254a7Smrg 	    {
125181254a7Smrg 	      index_type ret_extent;
126181254a7Smrg 
127181254a7Smrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
128181254a7Smrg 	      if (extent[n] != ret_extent)
129181254a7Smrg 		runtime_error ("Incorrect extent in return value of"
130181254a7Smrg 			       " ANY intrinsic in dimension %d:"
131181254a7Smrg 			       " is %ld, should be %ld", (int) n + 1,
132181254a7Smrg 			       (long int) ret_extent, (long int) extent[n]);
133181254a7Smrg 	    }
134181254a7Smrg 	}
135181254a7Smrg     }
136181254a7Smrg 
137181254a7Smrg   for (n = 0; n < rank; n++)
138181254a7Smrg     {
139181254a7Smrg       count[n] = 0;
140181254a7Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
141181254a7Smrg       if (extent[n] <= 0)
142181254a7Smrg 	return;
143181254a7Smrg     }
144181254a7Smrg 
145181254a7Smrg   base = array->base_addr;
146181254a7Smrg 
147181254a7Smrg   if (src_kind == 1 || src_kind == 2 || src_kind == 4 || src_kind == 8
148181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
149181254a7Smrg       || src_kind == 16
150181254a7Smrg #endif
151181254a7Smrg     )
152181254a7Smrg     {
153181254a7Smrg       if (base)
154181254a7Smrg 	base = GFOR_POINTER_TO_L1 (base, src_kind);
155181254a7Smrg     }
156181254a7Smrg   else
157181254a7Smrg     internal_error (NULL, "Funny sized logical array in ANY intrinsic");
158181254a7Smrg 
159181254a7Smrg   dest = retarray->base_addr;
160181254a7Smrg 
161181254a7Smrg   continue_loop = 1;
162181254a7Smrg   while (continue_loop)
163181254a7Smrg     {
164181254a7Smrg       const GFC_LOGICAL_1 * restrict src;
165181254a7Smrg       GFC_LOGICAL_1 result;
166181254a7Smrg       src = base;
167181254a7Smrg       {
168181254a7Smrg 
169181254a7Smrg   result = 0;
170181254a7Smrg         if (len <= 0)
171181254a7Smrg 	  *dest = 0;
172181254a7Smrg 	else
173181254a7Smrg 	  {
174181254a7Smrg 	    for (n = 0; n < len; n++, src += delta)
175181254a7Smrg 	      {
176181254a7Smrg 
177181254a7Smrg   /* Return true if any of the elements are set.  */
178181254a7Smrg   if (*src)
179181254a7Smrg     {
180181254a7Smrg       result = 1;
181181254a7Smrg       break;
182181254a7Smrg     }
183181254a7Smrg           }
184181254a7Smrg 	    *dest = result;
185181254a7Smrg 	  }
186181254a7Smrg       }
187181254a7Smrg       /* Advance to the next element.  */
188181254a7Smrg       count[0]++;
189181254a7Smrg       base += sstride[0];
190181254a7Smrg       dest += dstride[0];
191181254a7Smrg       n = 0;
192181254a7Smrg       while (count[n] == extent[n])
193181254a7Smrg         {
194181254a7Smrg           /* When we get to the end of a dimension, reset it and increment
195181254a7Smrg              the next dimension.  */
196181254a7Smrg           count[n] = 0;
197181254a7Smrg           /* We could precalculate these products, but this is a less
198181254a7Smrg              frequently used path so probably not worth it.  */
199181254a7Smrg           base -= sstride[n] * extent[n];
200181254a7Smrg           dest -= dstride[n] * extent[n];
201181254a7Smrg           n++;
202181254a7Smrg           if (n >= rank)
203181254a7Smrg             {
204181254a7Smrg               /* Break out of the loop.  */
205181254a7Smrg               continue_loop = 0;
206181254a7Smrg               break;
207181254a7Smrg             }
208181254a7Smrg           else
209181254a7Smrg             {
210181254a7Smrg               count[n]++;
211181254a7Smrg               base += sstride[n];
212181254a7Smrg               dest += dstride[n];
213181254a7Smrg             }
214181254a7Smrg         }
215181254a7Smrg     }
216181254a7Smrg }
217181254a7Smrg 
218181254a7Smrg #endif
219