xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/findloc0_s4.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1181254a7Smrg 
2181254a7Smrg /* Implementation of the FINDLOC intrinsic
3*b1e83836Smrg    Copyright (C) 2018-2022 Free Software Foundation, Inc.
4181254a7Smrg    Contributed by Thomas König <tk@tkoenig.net>
5181254a7Smrg 
6181254a7Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
7181254a7Smrg 
8181254a7Smrg Libgfortran is free software; you can redistribute it and/or
9181254a7Smrg modify it under the terms of the GNU General Public
10181254a7Smrg License as published by the Free Software Foundation; either
11181254a7Smrg version 3 of the License, or (at your option) any later version.
12181254a7Smrg 
13181254a7Smrg Libgfortran is distributed in the hope that it will be useful,
14181254a7Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
15181254a7Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16181254a7Smrg GNU General Public License for more details.
17181254a7Smrg 
18181254a7Smrg Under Section 7 of GPL version 3, you are granted additional
19181254a7Smrg permissions described in the GCC Runtime Library Exception, version
20181254a7Smrg 3.1, as published by the Free Software Foundation.
21181254a7Smrg 
22181254a7Smrg You should have received a copy of the GNU General Public License and
23181254a7Smrg a copy of the GCC Runtime Library Exception along with this program;
24181254a7Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25181254a7Smrg <http://www.gnu.org/licenses/>.  */
26181254a7Smrg 
27181254a7Smrg #include "libgfortran.h"
28181254a7Smrg #include <assert.h>
29181254a7Smrg 
30181254a7Smrg #if defined (HAVE_GFC_UINTEGER_4)
31181254a7Smrg extern void findloc0_s4 (gfc_array_index_type * const restrict retarray,
32181254a7Smrg        	    		gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *value,
33181254a7Smrg 			 GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value);
34181254a7Smrg 
35181254a7Smrg export_proto(findloc0_s4);
36181254a7Smrg 
37181254a7Smrg void
findloc0_s4(gfc_array_index_type * const restrict retarray,gfc_array_s4 * const restrict array,GFC_UINTEGER_4 * value,GFC_LOGICAL_4 back,gfc_charlen_type len_array,gfc_charlen_type len_value)38181254a7Smrg findloc0_s4 (gfc_array_index_type * const restrict retarray,
39181254a7Smrg     	    gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *value,
40181254a7Smrg 	    GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value)
41181254a7Smrg {
42181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
43181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
44181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
45181254a7Smrg   index_type dstride;
46181254a7Smrg   const GFC_UINTEGER_4 *base;
47181254a7Smrg   index_type * restrict dest;
48181254a7Smrg   index_type rank;
49181254a7Smrg   index_type n;
50181254a7Smrg   index_type sz;
51181254a7Smrg 
52181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
53181254a7Smrg   if (rank <= 0)
54181254a7Smrg     runtime_error ("Rank of array needs to be > 0");
55181254a7Smrg 
56181254a7Smrg   if (retarray->base_addr == NULL)
57181254a7Smrg     {
58181254a7Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
59181254a7Smrg       retarray->dtype.rank = 1;
60181254a7Smrg       retarray->offset = 0;
61181254a7Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
62181254a7Smrg     }
63181254a7Smrg   else
64181254a7Smrg     {
65181254a7Smrg       if (unlikely (compile_options.bounds_check))
66181254a7Smrg 	bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
67181254a7Smrg 				"FINDLOC");
68181254a7Smrg     }
69181254a7Smrg 
70181254a7Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
71181254a7Smrg   dest = retarray->base_addr;
72181254a7Smrg 
73181254a7Smrg   /* Set the return value.  */
74181254a7Smrg   for (n = 0; n < rank; n++)
75181254a7Smrg     dest[n * dstride] = 0;
76181254a7Smrg 
77181254a7Smrg   sz = 1;
78181254a7Smrg   for (n = 0; n < rank; n++)
79181254a7Smrg     {
80181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
81181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
82181254a7Smrg       sz *= extent[n];
83181254a7Smrg       if (extent[n] <= 0)
84181254a7Smrg 	return;
85181254a7Smrg     }
86181254a7Smrg 
87181254a7Smrg     for (n = 0; n < rank; n++)
88181254a7Smrg       count[n] = 0;
89181254a7Smrg 
90181254a7Smrg   if (back)
91181254a7Smrg     {
92181254a7Smrg       base = array->base_addr + (sz - 1) * len_array;
93181254a7Smrg 
94181254a7Smrg       while (1)
95181254a7Smrg         {
96181254a7Smrg 	  do
97181254a7Smrg 	    {
98181254a7Smrg 	      if (unlikely(compare_string_char4 (len_array, base, len_value, value) == 0))
99181254a7Smrg 	        {
100181254a7Smrg 		  for (n = 0; n < rank; n++)
101181254a7Smrg 		    dest[n * dstride] = extent[n] - count[n];
102181254a7Smrg 
103181254a7Smrg 		  return;
104181254a7Smrg 		}
105181254a7Smrg 	      base -= sstride[0] * len_array;
106181254a7Smrg 	    } while(++count[0] != extent[0]);
107181254a7Smrg 
108181254a7Smrg 	  n = 0;
109181254a7Smrg 	  do
110181254a7Smrg 	    {
111181254a7Smrg 	      /* When we get to the end of a dimension, reset it and increment
112181254a7Smrg 		 the next dimension.  */
113181254a7Smrg 	      count[n] = 0;
114181254a7Smrg 	      /* We could precalculate these products, but this is a less
115181254a7Smrg 		 frequently used path so probably not worth it.  */
116181254a7Smrg 	      base += sstride[n] * extent[n] * len_array;
117181254a7Smrg 	      n++;
118181254a7Smrg 	      if (n >= rank)
119181254a7Smrg 	        return;
120181254a7Smrg 	      else
121181254a7Smrg 		{
122181254a7Smrg 		  count[n]++;
123181254a7Smrg 		  base -= sstride[n] * len_array;
124181254a7Smrg 		}
125181254a7Smrg 	    } while (count[n] == extent[n]);
126181254a7Smrg 	}
127181254a7Smrg     }
128181254a7Smrg   else
129181254a7Smrg     {
130181254a7Smrg       base = array->base_addr;
131181254a7Smrg       while (1)
132181254a7Smrg         {
133181254a7Smrg 	  do
134181254a7Smrg 	    {
135181254a7Smrg 	      if (unlikely(compare_string_char4 (len_array, base, len_value, value) == 0))
136181254a7Smrg 	        {
137181254a7Smrg 		  for (n = 0; n < rank; n++)
138181254a7Smrg 		    dest[n * dstride] = count[n] + 1;
139181254a7Smrg 
140181254a7Smrg 		  return;
141181254a7Smrg 		}
142181254a7Smrg 	      base += sstride[0] * len_array;
143181254a7Smrg 	    } while(++count[0] != extent[0]);
144181254a7Smrg 
145181254a7Smrg 	  n = 0;
146181254a7Smrg 	  do
147181254a7Smrg 	    {
148181254a7Smrg 	      /* When we get to the end of a dimension, reset it and increment
149181254a7Smrg 		 the next dimension.  */
150181254a7Smrg 	      count[n] = 0;
151181254a7Smrg 	      /* We could precalculate these products, but this is a less
152181254a7Smrg 		 frequently used path so probably not worth it.  */
153181254a7Smrg 	      base -= sstride[n] * extent[n] * len_array;
154181254a7Smrg 	      n++;
155181254a7Smrg 	      if (n >= rank)
156181254a7Smrg 	        return;
157181254a7Smrg 	      else
158181254a7Smrg 		{
159181254a7Smrg 		  count[n]++;
160181254a7Smrg 		  base += sstride[n] * len_array;
161181254a7Smrg 		}
162181254a7Smrg 	    } while (count[n] == extent[n]);
163181254a7Smrg 	}
164181254a7Smrg     }
165181254a7Smrg   return;
166181254a7Smrg }
167181254a7Smrg 
168181254a7Smrg extern void mfindloc0_s4 (gfc_array_index_type * const restrict retarray,
169181254a7Smrg        	    		gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *value,
170181254a7Smrg 			 gfc_array_l1 *const restrict, GFC_LOGICAL_4 back, gfc_charlen_type len_array,
171181254a7Smrg 			 gfc_charlen_type len_value);
172181254a7Smrg export_proto(mfindloc0_s4);
173181254a7Smrg 
174181254a7Smrg void
mfindloc0_s4(gfc_array_index_type * const restrict retarray,gfc_array_s4 * const restrict array,GFC_UINTEGER_4 * value,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back,gfc_charlen_type len_array,gfc_charlen_type len_value)175181254a7Smrg mfindloc0_s4 (gfc_array_index_type * const restrict retarray,
176181254a7Smrg     	    gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *value,
177181254a7Smrg 	    gfc_array_l1 *const restrict mask, GFC_LOGICAL_4 back,
178181254a7Smrg 	    gfc_charlen_type len_array, gfc_charlen_type len_value)
179181254a7Smrg {
180181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
181181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
182181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
183181254a7Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
184181254a7Smrg   index_type dstride;
185181254a7Smrg   const GFC_UINTEGER_4 *base;
186181254a7Smrg   index_type * restrict dest;
187181254a7Smrg   GFC_LOGICAL_1 *mbase;
188181254a7Smrg   index_type rank;
189181254a7Smrg   index_type n;
190181254a7Smrg   int mask_kind;
191181254a7Smrg   index_type sz;
192181254a7Smrg 
193181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
194181254a7Smrg   if (rank <= 0)
195181254a7Smrg     runtime_error ("Rank of array needs to be > 0");
196181254a7Smrg 
197181254a7Smrg   if (retarray->base_addr == NULL)
198181254a7Smrg     {
199181254a7Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
200181254a7Smrg       retarray->dtype.rank = 1;
201181254a7Smrg       retarray->offset = 0;
202181254a7Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
203181254a7Smrg     }
204181254a7Smrg   else
205181254a7Smrg     {
206181254a7Smrg       if (unlikely (compile_options.bounds_check))
207181254a7Smrg 	{
208181254a7Smrg 	  bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
209181254a7Smrg 				  "FINDLOC");
210181254a7Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
211181254a7Smrg 				"MASK argument", "FINDLOC");
212181254a7Smrg 	}
213181254a7Smrg     }
214181254a7Smrg 
215181254a7Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
216181254a7Smrg 
217181254a7Smrg   mbase = mask->base_addr;
218181254a7Smrg 
219181254a7Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
220181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
221181254a7Smrg       || mask_kind == 16
222181254a7Smrg #endif
223181254a7Smrg       )
224181254a7Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
225181254a7Smrg   else
226181254a7Smrg     internal_error (NULL, "Funny sized logical array");
227181254a7Smrg 
228181254a7Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
229181254a7Smrg   dest = retarray->base_addr;
230181254a7Smrg 
231181254a7Smrg   /* Set the return value.  */
232181254a7Smrg   for (n = 0; n < rank; n++)
233181254a7Smrg     dest[n * dstride] = 0;
234181254a7Smrg 
235181254a7Smrg   sz = 1;
236181254a7Smrg   for (n = 0; n < rank; n++)
237181254a7Smrg     {
238181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
239181254a7Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
240181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
241181254a7Smrg       sz *= extent[n];
242181254a7Smrg       if (extent[n] <= 0)
243181254a7Smrg 	return;
244181254a7Smrg     }
245181254a7Smrg 
246181254a7Smrg     for (n = 0; n < rank; n++)
247181254a7Smrg       count[n] = 0;
248181254a7Smrg 
249181254a7Smrg   if (back)
250181254a7Smrg     {
251181254a7Smrg       base = array->base_addr + (sz - 1) * len_array;
252181254a7Smrg       mbase = mbase + (sz - 1) * mask_kind;
253181254a7Smrg       while (1)
254181254a7Smrg         {
255181254a7Smrg 	  do
256181254a7Smrg 	    {
257181254a7Smrg 	      if (unlikely(*mbase && compare_string_char4 (len_array, base, len_value, value) == 0))
258181254a7Smrg 	        {
259181254a7Smrg 		  for (n = 0; n < rank; n++)
260181254a7Smrg 		    dest[n * dstride] = extent[n] - count[n];
261181254a7Smrg 
262181254a7Smrg 		  return;
263181254a7Smrg 		}
264181254a7Smrg 	      base -= sstride[0] * len_array;
265181254a7Smrg 	      mbase -= mstride[0];
266181254a7Smrg 	    } while(++count[0] != extent[0]);
267181254a7Smrg 
268181254a7Smrg 	  n = 0;
269181254a7Smrg 	  do
270181254a7Smrg 	    {
271181254a7Smrg 	      /* When we get to the end of a dimension, reset it and increment
272181254a7Smrg 		 the next dimension.  */
273181254a7Smrg 	      count[n] = 0;
274181254a7Smrg 	      /* We could precalculate these products, but this is a less
275181254a7Smrg 		 frequently used path so probably not worth it.  */
276181254a7Smrg 	      base += sstride[n] * extent[n] * len_array;
277181254a7Smrg 	      mbase -= mstride[n] * extent[n];
278181254a7Smrg 	      n++;
279181254a7Smrg 	      if (n >= rank)
280181254a7Smrg 		return;
281181254a7Smrg 	      else
282181254a7Smrg 		{
283181254a7Smrg 		  count[n]++;
284181254a7Smrg 		  base -= sstride[n] * len_array;
285181254a7Smrg 		  mbase += mstride[n];
286181254a7Smrg 		}
287181254a7Smrg 	    } while (count[n] == extent[n]);
288181254a7Smrg 	}
289181254a7Smrg     }
290181254a7Smrg   else
291181254a7Smrg     {
292181254a7Smrg       base = array->base_addr;
293181254a7Smrg       while (1)
294181254a7Smrg         {
295181254a7Smrg 	  do
296181254a7Smrg 	    {
297181254a7Smrg 	      if (unlikely(*mbase && compare_string_char4 (len_array, base, len_value, value) == 0))
298181254a7Smrg 	        {
299181254a7Smrg 		  for (n = 0; n < rank; n++)
300181254a7Smrg 		    dest[n * dstride] = count[n] + 1;
301181254a7Smrg 
302181254a7Smrg 		  return;
303181254a7Smrg 		}
304181254a7Smrg 	      base += sstride[0] * len_array;
305181254a7Smrg 	      mbase += mstride[0];
306181254a7Smrg 	    } while(++count[0] != extent[0]);
307181254a7Smrg 
308181254a7Smrg 	  n = 0;
309181254a7Smrg 	  do
310181254a7Smrg 	    {
311181254a7Smrg 	      /* When we get to the end of a dimension, reset it and increment
312181254a7Smrg 		 the next dimension.  */
313181254a7Smrg 	      count[n] = 0;
314181254a7Smrg 	      /* We could precalculate these products, but this is a less
315181254a7Smrg 		 frequently used path so probably not worth it.  */
316181254a7Smrg 	      base -= sstride[n] * extent[n] * len_array;
317181254a7Smrg 	      mbase -= mstride[n] * extent[n];
318181254a7Smrg 	      n++;
319181254a7Smrg 	      if (n >= rank)
320181254a7Smrg 		return;
321181254a7Smrg 	      else
322181254a7Smrg 		{
323181254a7Smrg 		  count[n]++;
324181254a7Smrg 		  base += sstride[n]* len_array;
325181254a7Smrg 		  mbase += mstride[n];
326181254a7Smrg 		}
327181254a7Smrg 	    } while (count[n] == extent[n]);
328181254a7Smrg 	}
329181254a7Smrg     }
330181254a7Smrg   return;
331181254a7Smrg }
332181254a7Smrg 
333181254a7Smrg extern void sfindloc0_s4 (gfc_array_index_type * const restrict retarray,
334181254a7Smrg        	    		gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *value,
335181254a7Smrg 			 GFC_LOGICAL_4 *, GFC_LOGICAL_4 back, gfc_charlen_type len_array,
336181254a7Smrg 			 gfc_charlen_type len_value);
337181254a7Smrg export_proto(sfindloc0_s4);
338181254a7Smrg 
339181254a7Smrg void
sfindloc0_s4(gfc_array_index_type * const restrict retarray,gfc_array_s4 * const restrict array,GFC_UINTEGER_4 * value,GFC_LOGICAL_4 * mask,GFC_LOGICAL_4 back,gfc_charlen_type len_array,gfc_charlen_type len_value)340181254a7Smrg sfindloc0_s4 (gfc_array_index_type * const restrict retarray,
341181254a7Smrg     	    gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *value,
342181254a7Smrg 	    GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back, gfc_charlen_type len_array,
343181254a7Smrg 	    gfc_charlen_type len_value)
344181254a7Smrg {
345181254a7Smrg   index_type rank;
346181254a7Smrg   index_type dstride;
347181254a7Smrg   index_type * restrict dest;
348181254a7Smrg   index_type n;
349181254a7Smrg 
350181254a7Smrg   if (mask == NULL || *mask)
351181254a7Smrg     {
352181254a7Smrg       findloc0_s4 (retarray, array, value, back, len_array, len_value);
353181254a7Smrg       return;
354181254a7Smrg     }
355181254a7Smrg 
356181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
357181254a7Smrg 
358181254a7Smrg   if (rank <= 0)
359181254a7Smrg     internal_error (NULL, "Rank of array needs to be > 0");
360181254a7Smrg 
361181254a7Smrg   if (retarray->base_addr == NULL)
362181254a7Smrg     {
363181254a7Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
364181254a7Smrg       retarray->dtype.rank = 1;
365181254a7Smrg       retarray->offset = 0;
366181254a7Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
367181254a7Smrg     }
368181254a7Smrg   else if (unlikely (compile_options.bounds_check))
369181254a7Smrg     {
370181254a7Smrg        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
371181254a7Smrg 			       "FINDLOC");
372181254a7Smrg     }
373181254a7Smrg 
374181254a7Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
375181254a7Smrg   dest = retarray->base_addr;
376181254a7Smrg   for (n = 0; n<rank; n++)
377181254a7Smrg     dest[n * dstride] = 0 ;
378181254a7Smrg }
379181254a7Smrg 
380181254a7Smrg #endif
381181254a7Smrg 
382181254a7Smrg 
383181254a7Smrg 
384