xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/generated/findloc0_s1.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg 
2627f7eb2Smrg /* Implementation of the FINDLOC intrinsic
3*4c3eb207Smrg    Copyright (C) 2018-2020 Free Software Foundation, Inc.
4627f7eb2Smrg    Contributed by Thomas König <tk@tkoenig.net>
5627f7eb2Smrg 
6627f7eb2Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
7627f7eb2Smrg 
8627f7eb2Smrg Libgfortran is free software; you can redistribute it and/or
9627f7eb2Smrg modify it under the terms of the GNU General Public
10627f7eb2Smrg License as published by the Free Software Foundation; either
11627f7eb2Smrg version 3 of the License, or (at your option) any later version.
12627f7eb2Smrg 
13627f7eb2Smrg Libgfortran is distributed in the hope that it will be useful,
14627f7eb2Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
15627f7eb2Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16627f7eb2Smrg GNU General Public License for more details.
17627f7eb2Smrg 
18627f7eb2Smrg Under Section 7 of GPL version 3, you are granted additional
19627f7eb2Smrg permissions described in the GCC Runtime Library Exception, version
20627f7eb2Smrg 3.1, as published by the Free Software Foundation.
21627f7eb2Smrg 
22627f7eb2Smrg You should have received a copy of the GNU General Public License and
23627f7eb2Smrg a copy of the GCC Runtime Library Exception along with this program;
24627f7eb2Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25627f7eb2Smrg <http://www.gnu.org/licenses/>.  */
26627f7eb2Smrg 
27627f7eb2Smrg #include "libgfortran.h"
28627f7eb2Smrg #include <assert.h>
29627f7eb2Smrg 
30627f7eb2Smrg #if defined (HAVE_GFC_UINTEGER_1)
31627f7eb2Smrg extern void findloc0_s1 (gfc_array_index_type * const restrict retarray,
32627f7eb2Smrg        	    		gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
33627f7eb2Smrg 			 GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value);
34627f7eb2Smrg 
35627f7eb2Smrg export_proto(findloc0_s1);
36627f7eb2Smrg 
37627f7eb2Smrg void
findloc0_s1(gfc_array_index_type * const restrict retarray,gfc_array_s1 * const restrict array,GFC_UINTEGER_1 * value,GFC_LOGICAL_4 back,gfc_charlen_type len_array,gfc_charlen_type len_value)38627f7eb2Smrg findloc0_s1 (gfc_array_index_type * const restrict retarray,
39627f7eb2Smrg     	    gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
40627f7eb2Smrg 	    GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value)
41627f7eb2Smrg {
42627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
43627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
44627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
45627f7eb2Smrg   index_type dstride;
46627f7eb2Smrg   const GFC_UINTEGER_1 *base;
47627f7eb2Smrg   index_type * restrict dest;
48627f7eb2Smrg   index_type rank;
49627f7eb2Smrg   index_type n;
50627f7eb2Smrg   index_type sz;
51627f7eb2Smrg 
52627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
53627f7eb2Smrg   if (rank <= 0)
54627f7eb2Smrg     runtime_error ("Rank of array needs to be > 0");
55627f7eb2Smrg 
56627f7eb2Smrg   if (retarray->base_addr == NULL)
57627f7eb2Smrg     {
58627f7eb2Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
59627f7eb2Smrg       retarray->dtype.rank = 1;
60627f7eb2Smrg       retarray->offset = 0;
61627f7eb2Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
62627f7eb2Smrg     }
63627f7eb2Smrg   else
64627f7eb2Smrg     {
65627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
66627f7eb2Smrg 	bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
67627f7eb2Smrg 				"FINDLOC");
68627f7eb2Smrg     }
69627f7eb2Smrg 
70627f7eb2Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
71627f7eb2Smrg   dest = retarray->base_addr;
72627f7eb2Smrg 
73627f7eb2Smrg   /* Set the return value.  */
74627f7eb2Smrg   for (n = 0; n < rank; n++)
75627f7eb2Smrg     dest[n * dstride] = 0;
76627f7eb2Smrg 
77627f7eb2Smrg   sz = 1;
78627f7eb2Smrg   for (n = 0; n < rank; n++)
79627f7eb2Smrg     {
80627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
81627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
82627f7eb2Smrg       sz *= extent[n];
83627f7eb2Smrg       if (extent[n] <= 0)
84627f7eb2Smrg 	return;
85627f7eb2Smrg     }
86627f7eb2Smrg 
87627f7eb2Smrg     for (n = 0; n < rank; n++)
88627f7eb2Smrg       count[n] = 0;
89627f7eb2Smrg 
90627f7eb2Smrg   if (back)
91627f7eb2Smrg     {
92627f7eb2Smrg       base = array->base_addr + (sz - 1) * len_array;
93627f7eb2Smrg 
94627f7eb2Smrg       while (1)
95627f7eb2Smrg         {
96627f7eb2Smrg 	  do
97627f7eb2Smrg 	    {
98627f7eb2Smrg 	      if (unlikely(compare_string (len_array, (char *) base, len_value, (char *) value) == 0))
99627f7eb2Smrg 	        {
100627f7eb2Smrg 		  for (n = 0; n < rank; n++)
101627f7eb2Smrg 		    dest[n * dstride] = extent[n] - count[n];
102627f7eb2Smrg 
103627f7eb2Smrg 		  return;
104627f7eb2Smrg 		}
105627f7eb2Smrg 	      base -= sstride[0] * len_array;
106627f7eb2Smrg 	    } while(++count[0] != extent[0]);
107627f7eb2Smrg 
108627f7eb2Smrg 	  n = 0;
109627f7eb2Smrg 	  do
110627f7eb2Smrg 	    {
111627f7eb2Smrg 	      /* When we get to the end of a dimension, reset it and increment
112627f7eb2Smrg 		 the next dimension.  */
113627f7eb2Smrg 	      count[n] = 0;
114627f7eb2Smrg 	      /* We could precalculate these products, but this is a less
115627f7eb2Smrg 		 frequently used path so probably not worth it.  */
116627f7eb2Smrg 	      base += sstride[n] * extent[n] * len_array;
117627f7eb2Smrg 	      n++;
118627f7eb2Smrg 	      if (n >= rank)
119627f7eb2Smrg 	        return;
120627f7eb2Smrg 	      else
121627f7eb2Smrg 		{
122627f7eb2Smrg 		  count[n]++;
123627f7eb2Smrg 		  base -= sstride[n] * len_array;
124627f7eb2Smrg 		}
125627f7eb2Smrg 	    } while (count[n] == extent[n]);
126627f7eb2Smrg 	}
127627f7eb2Smrg     }
128627f7eb2Smrg   else
129627f7eb2Smrg     {
130627f7eb2Smrg       base = array->base_addr;
131627f7eb2Smrg       while (1)
132627f7eb2Smrg         {
133627f7eb2Smrg 	  do
134627f7eb2Smrg 	    {
135627f7eb2Smrg 	      if (unlikely(compare_string (len_array, (char *) base, len_value, (char *) value) == 0))
136627f7eb2Smrg 	        {
137627f7eb2Smrg 		  for (n = 0; n < rank; n++)
138627f7eb2Smrg 		    dest[n * dstride] = count[n] + 1;
139627f7eb2Smrg 
140627f7eb2Smrg 		  return;
141627f7eb2Smrg 		}
142627f7eb2Smrg 	      base += sstride[0] * len_array;
143627f7eb2Smrg 	    } while(++count[0] != extent[0]);
144627f7eb2Smrg 
145627f7eb2Smrg 	  n = 0;
146627f7eb2Smrg 	  do
147627f7eb2Smrg 	    {
148627f7eb2Smrg 	      /* When we get to the end of a dimension, reset it and increment
149627f7eb2Smrg 		 the next dimension.  */
150627f7eb2Smrg 	      count[n] = 0;
151627f7eb2Smrg 	      /* We could precalculate these products, but this is a less
152627f7eb2Smrg 		 frequently used path so probably not worth it.  */
153627f7eb2Smrg 	      base -= sstride[n] * extent[n] * len_array;
154627f7eb2Smrg 	      n++;
155627f7eb2Smrg 	      if (n >= rank)
156627f7eb2Smrg 	        return;
157627f7eb2Smrg 	      else
158627f7eb2Smrg 		{
159627f7eb2Smrg 		  count[n]++;
160627f7eb2Smrg 		  base += sstride[n] * len_array;
161627f7eb2Smrg 		}
162627f7eb2Smrg 	    } while (count[n] == extent[n]);
163627f7eb2Smrg 	}
164627f7eb2Smrg     }
165627f7eb2Smrg   return;
166627f7eb2Smrg }
167627f7eb2Smrg 
168627f7eb2Smrg extern void mfindloc0_s1 (gfc_array_index_type * const restrict retarray,
169627f7eb2Smrg        	    		gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
170627f7eb2Smrg 			 gfc_array_l1 *const restrict, GFC_LOGICAL_4 back, gfc_charlen_type len_array,
171627f7eb2Smrg 			 gfc_charlen_type len_value);
172627f7eb2Smrg export_proto(mfindloc0_s1);
173627f7eb2Smrg 
174627f7eb2Smrg void
mfindloc0_s1(gfc_array_index_type * const restrict retarray,gfc_array_s1 * const restrict array,GFC_UINTEGER_1 * value,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back,gfc_charlen_type len_array,gfc_charlen_type len_value)175627f7eb2Smrg mfindloc0_s1 (gfc_array_index_type * const restrict retarray,
176627f7eb2Smrg     	    gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
177627f7eb2Smrg 	    gfc_array_l1 *const restrict mask, GFC_LOGICAL_4 back,
178627f7eb2Smrg 	    gfc_charlen_type len_array, gfc_charlen_type len_value)
179627f7eb2Smrg {
180627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
181627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
182627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
183627f7eb2Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
184627f7eb2Smrg   index_type dstride;
185627f7eb2Smrg   const GFC_UINTEGER_1 *base;
186627f7eb2Smrg   index_type * restrict dest;
187627f7eb2Smrg   GFC_LOGICAL_1 *mbase;
188627f7eb2Smrg   index_type rank;
189627f7eb2Smrg   index_type n;
190627f7eb2Smrg   int mask_kind;
191627f7eb2Smrg   index_type sz;
192627f7eb2Smrg 
193627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
194627f7eb2Smrg   if (rank <= 0)
195627f7eb2Smrg     runtime_error ("Rank of array needs to be > 0");
196627f7eb2Smrg 
197627f7eb2Smrg   if (retarray->base_addr == NULL)
198627f7eb2Smrg     {
199627f7eb2Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
200627f7eb2Smrg       retarray->dtype.rank = 1;
201627f7eb2Smrg       retarray->offset = 0;
202627f7eb2Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
203627f7eb2Smrg     }
204627f7eb2Smrg   else
205627f7eb2Smrg     {
206627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
207627f7eb2Smrg 	{
208627f7eb2Smrg 	  bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
209627f7eb2Smrg 				  "FINDLOC");
210627f7eb2Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
211627f7eb2Smrg 				"MASK argument", "FINDLOC");
212627f7eb2Smrg 	}
213627f7eb2Smrg     }
214627f7eb2Smrg 
215627f7eb2Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
216627f7eb2Smrg 
217627f7eb2Smrg   mbase = mask->base_addr;
218627f7eb2Smrg 
219627f7eb2Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
220627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
221627f7eb2Smrg       || mask_kind == 16
222627f7eb2Smrg #endif
223627f7eb2Smrg       )
224627f7eb2Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
225627f7eb2Smrg   else
226627f7eb2Smrg     internal_error (NULL, "Funny sized logical array");
227627f7eb2Smrg 
228627f7eb2Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
229627f7eb2Smrg   dest = retarray->base_addr;
230627f7eb2Smrg 
231627f7eb2Smrg   /* Set the return value.  */
232627f7eb2Smrg   for (n = 0; n < rank; n++)
233627f7eb2Smrg     dest[n * dstride] = 0;
234627f7eb2Smrg 
235627f7eb2Smrg   sz = 1;
236627f7eb2Smrg   for (n = 0; n < rank; n++)
237627f7eb2Smrg     {
238627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
239627f7eb2Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
240627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
241627f7eb2Smrg       sz *= extent[n];
242627f7eb2Smrg       if (extent[n] <= 0)
243627f7eb2Smrg 	return;
244627f7eb2Smrg     }
245627f7eb2Smrg 
246627f7eb2Smrg     for (n = 0; n < rank; n++)
247627f7eb2Smrg       count[n] = 0;
248627f7eb2Smrg 
249627f7eb2Smrg   if (back)
250627f7eb2Smrg     {
251627f7eb2Smrg       base = array->base_addr + (sz - 1) * len_array;
252627f7eb2Smrg       mbase = mbase + (sz - 1) * mask_kind;
253627f7eb2Smrg       while (1)
254627f7eb2Smrg         {
255627f7eb2Smrg 	  do
256627f7eb2Smrg 	    {
257627f7eb2Smrg 	      if (unlikely(*mbase && compare_string (len_array, (char *) base, len_value, (char *) value) == 0))
258627f7eb2Smrg 	        {
259627f7eb2Smrg 		  for (n = 0; n < rank; n++)
260627f7eb2Smrg 		    dest[n * dstride] = extent[n] - count[n];
261627f7eb2Smrg 
262627f7eb2Smrg 		  return;
263627f7eb2Smrg 		}
264627f7eb2Smrg 	      base -= sstride[0] * len_array;
265627f7eb2Smrg 	      mbase -= mstride[0];
266627f7eb2Smrg 	    } while(++count[0] != extent[0]);
267627f7eb2Smrg 
268627f7eb2Smrg 	  n = 0;
269627f7eb2Smrg 	  do
270627f7eb2Smrg 	    {
271627f7eb2Smrg 	      /* When we get to the end of a dimension, reset it and increment
272627f7eb2Smrg 		 the next dimension.  */
273627f7eb2Smrg 	      count[n] = 0;
274627f7eb2Smrg 	      /* We could precalculate these products, but this is a less
275627f7eb2Smrg 		 frequently used path so probably not worth it.  */
276627f7eb2Smrg 	      base += sstride[n] * extent[n] * len_array;
277627f7eb2Smrg 	      mbase -= mstride[n] * extent[n];
278627f7eb2Smrg 	      n++;
279627f7eb2Smrg 	      if (n >= rank)
280627f7eb2Smrg 		return;
281627f7eb2Smrg 	      else
282627f7eb2Smrg 		{
283627f7eb2Smrg 		  count[n]++;
284627f7eb2Smrg 		  base -= sstride[n] * len_array;
285627f7eb2Smrg 		  mbase += mstride[n];
286627f7eb2Smrg 		}
287627f7eb2Smrg 	    } while (count[n] == extent[n]);
288627f7eb2Smrg 	}
289627f7eb2Smrg     }
290627f7eb2Smrg   else
291627f7eb2Smrg     {
292627f7eb2Smrg       base = array->base_addr;
293627f7eb2Smrg       while (1)
294627f7eb2Smrg         {
295627f7eb2Smrg 	  do
296627f7eb2Smrg 	    {
297627f7eb2Smrg 	      if (unlikely(*mbase && compare_string (len_array, (char *) base, len_value, (char *) value) == 0))
298627f7eb2Smrg 	        {
299627f7eb2Smrg 		  for (n = 0; n < rank; n++)
300627f7eb2Smrg 		    dest[n * dstride] = count[n] + 1;
301627f7eb2Smrg 
302627f7eb2Smrg 		  return;
303627f7eb2Smrg 		}
304627f7eb2Smrg 	      base += sstride[0] * len_array;
305627f7eb2Smrg 	      mbase += mstride[0];
306627f7eb2Smrg 	    } while(++count[0] != extent[0]);
307627f7eb2Smrg 
308627f7eb2Smrg 	  n = 0;
309627f7eb2Smrg 	  do
310627f7eb2Smrg 	    {
311627f7eb2Smrg 	      /* When we get to the end of a dimension, reset it and increment
312627f7eb2Smrg 		 the next dimension.  */
313627f7eb2Smrg 	      count[n] = 0;
314627f7eb2Smrg 	      /* We could precalculate these products, but this is a less
315627f7eb2Smrg 		 frequently used path so probably not worth it.  */
316627f7eb2Smrg 	      base -= sstride[n] * extent[n] * len_array;
317627f7eb2Smrg 	      mbase -= mstride[n] * extent[n];
318627f7eb2Smrg 	      n++;
319627f7eb2Smrg 	      if (n >= rank)
320627f7eb2Smrg 		return;
321627f7eb2Smrg 	      else
322627f7eb2Smrg 		{
323627f7eb2Smrg 		  count[n]++;
324627f7eb2Smrg 		  base += sstride[n]* len_array;
325627f7eb2Smrg 		  mbase += mstride[n];
326627f7eb2Smrg 		}
327627f7eb2Smrg 	    } while (count[n] == extent[n]);
328627f7eb2Smrg 	}
329627f7eb2Smrg     }
330627f7eb2Smrg   return;
331627f7eb2Smrg }
332627f7eb2Smrg 
333627f7eb2Smrg extern void sfindloc0_s1 (gfc_array_index_type * const restrict retarray,
334627f7eb2Smrg        	    		gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
335627f7eb2Smrg 			 GFC_LOGICAL_4 *, GFC_LOGICAL_4 back, gfc_charlen_type len_array,
336627f7eb2Smrg 			 gfc_charlen_type len_value);
337627f7eb2Smrg export_proto(sfindloc0_s1);
338627f7eb2Smrg 
339627f7eb2Smrg void
sfindloc0_s1(gfc_array_index_type * const restrict retarray,gfc_array_s1 * const restrict array,GFC_UINTEGER_1 * value,GFC_LOGICAL_4 * mask,GFC_LOGICAL_4 back,gfc_charlen_type len_array,gfc_charlen_type len_value)340627f7eb2Smrg sfindloc0_s1 (gfc_array_index_type * const restrict retarray,
341627f7eb2Smrg     	    gfc_array_s1 * const restrict array, GFC_UINTEGER_1 *value,
342627f7eb2Smrg 	    GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back, gfc_charlen_type len_array,
343627f7eb2Smrg 	    gfc_charlen_type len_value)
344627f7eb2Smrg {
345627f7eb2Smrg   index_type rank;
346627f7eb2Smrg   index_type dstride;
347627f7eb2Smrg   index_type * restrict dest;
348627f7eb2Smrg   index_type n;
349627f7eb2Smrg 
350627f7eb2Smrg   if (mask == NULL || *mask)
351627f7eb2Smrg     {
352627f7eb2Smrg       findloc0_s1 (retarray, array, value, back, len_array, len_value);
353627f7eb2Smrg       return;
354627f7eb2Smrg     }
355627f7eb2Smrg 
356627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
357627f7eb2Smrg 
358627f7eb2Smrg   if (rank <= 0)
359627f7eb2Smrg     internal_error (NULL, "Rank of array needs to be > 0");
360627f7eb2Smrg 
361627f7eb2Smrg   if (retarray->base_addr == NULL)
362627f7eb2Smrg     {
363627f7eb2Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
364627f7eb2Smrg       retarray->dtype.rank = 1;
365627f7eb2Smrg       retarray->offset = 0;
366627f7eb2Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
367627f7eb2Smrg     }
368627f7eb2Smrg   else if (unlikely (compile_options.bounds_check))
369627f7eb2Smrg     {
370627f7eb2Smrg        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
371627f7eb2Smrg 			       "FINDLOC");
372627f7eb2Smrg     }
373627f7eb2Smrg 
374627f7eb2Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
375627f7eb2Smrg   dest = retarray->base_addr;
376627f7eb2Smrg   for (n = 0; n<rank; n++)
377627f7eb2Smrg     dest[n * dstride] = 0 ;
378627f7eb2Smrg }
379627f7eb2Smrg 
380627f7eb2Smrg #endif
381627f7eb2Smrg 
382627f7eb2Smrg 
383627f7eb2Smrg 
384