xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/findloc0_i16.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_INTEGER_16)
31181254a7Smrg extern void findloc0_i16 (gfc_array_index_type * const restrict retarray,
32181254a7Smrg        	    		gfc_array_i16 * const restrict array, GFC_INTEGER_16 value,
33181254a7Smrg 			 GFC_LOGICAL_4);
34181254a7Smrg export_proto(findloc0_i16);
35181254a7Smrg 
36181254a7Smrg void
findloc0_i16(gfc_array_index_type * const restrict retarray,gfc_array_i16 * const restrict array,GFC_INTEGER_16 value,GFC_LOGICAL_4 back)37181254a7Smrg findloc0_i16 (gfc_array_index_type * const restrict retarray,
38181254a7Smrg     	    gfc_array_i16 * const restrict array, GFC_INTEGER_16 value,
39181254a7Smrg 	    GFC_LOGICAL_4 back)
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;
45181254a7Smrg   const GFC_INTEGER_16 *base;
46181254a7Smrg   index_type * restrict dest;
47181254a7Smrg   index_type rank;
48181254a7Smrg   index_type n;
49181254a7Smrg   index_type sz;
50181254a7Smrg 
51181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
52181254a7Smrg   if (rank <= 0)
53181254a7Smrg     runtime_error ("Rank of array needs to be > 0");
54181254a7Smrg 
55181254a7Smrg   if (retarray->base_addr == NULL)
56181254a7Smrg     {
57181254a7Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
58181254a7Smrg       retarray->dtype.rank = 1;
59181254a7Smrg       retarray->offset = 0;
60181254a7Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
61181254a7Smrg     }
62181254a7Smrg   else
63181254a7Smrg     {
64181254a7Smrg       if (unlikely (compile_options.bounds_check))
65181254a7Smrg 	bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
66181254a7Smrg 				"FINDLOC");
67181254a7Smrg     }
68181254a7Smrg 
69181254a7Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
70181254a7Smrg   dest = retarray->base_addr;
71181254a7Smrg 
72181254a7Smrg   /* Set the return value.  */
73181254a7Smrg   for (n = 0; n < rank; n++)
74181254a7Smrg     dest[n * dstride] = 0;
75181254a7Smrg 
76181254a7Smrg   sz = 1;
77181254a7Smrg   for (n = 0; n < rank; n++)
78181254a7Smrg     {
79181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
80181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
81181254a7Smrg       sz *= extent[n];
82181254a7Smrg       if (extent[n] <= 0)
83181254a7Smrg 	return;
84181254a7Smrg     }
85181254a7Smrg 
86181254a7Smrg     for (n = 0; n < rank; n++)
87181254a7Smrg       count[n] = 0;
88181254a7Smrg 
89181254a7Smrg   if (back)
90181254a7Smrg     {
91181254a7Smrg       base = array->base_addr + (sz - 1) * 1;
92181254a7Smrg 
93181254a7Smrg       while (1)
94181254a7Smrg         {
95181254a7Smrg 	  do
96181254a7Smrg 	    {
97181254a7Smrg 	      if (unlikely(*base == value))
98181254a7Smrg 	        {
99181254a7Smrg 		  for (n = 0; n < rank; n++)
100181254a7Smrg 		    dest[n * dstride] = extent[n] - count[n];
101181254a7Smrg 
102181254a7Smrg 		  return;
103181254a7Smrg 		}
104181254a7Smrg 	      base -= sstride[0] * 1;
105181254a7Smrg 	    } while(++count[0] != extent[0]);
106181254a7Smrg 
107181254a7Smrg 	  n = 0;
108181254a7Smrg 	  do
109181254a7Smrg 	    {
110181254a7Smrg 	      /* When we get to the end of a dimension, reset it and increment
111181254a7Smrg 		 the next dimension.  */
112181254a7Smrg 	      count[n] = 0;
113181254a7Smrg 	      /* We could precalculate these products, but this is a less
114181254a7Smrg 		 frequently used path so probably not worth it.  */
115181254a7Smrg 	      base += sstride[n] * extent[n] * 1;
116181254a7Smrg 	      n++;
117181254a7Smrg 	      if (n >= rank)
118181254a7Smrg 	        return;
119181254a7Smrg 	      else
120181254a7Smrg 		{
121181254a7Smrg 		  count[n]++;
122181254a7Smrg 		  base -= sstride[n] * 1;
123181254a7Smrg 		}
124181254a7Smrg 	    } while (count[n] == extent[n]);
125181254a7Smrg 	}
126181254a7Smrg     }
127181254a7Smrg   else
128181254a7Smrg     {
129181254a7Smrg       base = array->base_addr;
130181254a7Smrg       while (1)
131181254a7Smrg         {
132181254a7Smrg 	  do
133181254a7Smrg 	    {
134181254a7Smrg 	      if (unlikely(*base == value))
135181254a7Smrg 	        {
136181254a7Smrg 		  for (n = 0; n < rank; n++)
137181254a7Smrg 		    dest[n * dstride] = count[n] + 1;
138181254a7Smrg 
139181254a7Smrg 		  return;
140181254a7Smrg 		}
141181254a7Smrg 	      base += sstride[0] * 1;
142181254a7Smrg 	    } while(++count[0] != extent[0]);
143181254a7Smrg 
144181254a7Smrg 	  n = 0;
145181254a7Smrg 	  do
146181254a7Smrg 	    {
147181254a7Smrg 	      /* When we get to the end of a dimension, reset it and increment
148181254a7Smrg 		 the next dimension.  */
149181254a7Smrg 	      count[n] = 0;
150181254a7Smrg 	      /* We could precalculate these products, but this is a less
151181254a7Smrg 		 frequently used path so probably not worth it.  */
152181254a7Smrg 	      base -= sstride[n] * extent[n] * 1;
153181254a7Smrg 	      n++;
154181254a7Smrg 	      if (n >= rank)
155181254a7Smrg 	        return;
156181254a7Smrg 	      else
157181254a7Smrg 		{
158181254a7Smrg 		  count[n]++;
159181254a7Smrg 		  base += sstride[n] * 1;
160181254a7Smrg 		}
161181254a7Smrg 	    } while (count[n] == extent[n]);
162181254a7Smrg 	}
163181254a7Smrg     }
164181254a7Smrg   return;
165181254a7Smrg }
166181254a7Smrg 
167181254a7Smrg extern void mfindloc0_i16 (gfc_array_index_type * const restrict retarray,
168181254a7Smrg        	    		gfc_array_i16 * const restrict array, GFC_INTEGER_16 value,
169181254a7Smrg 			 gfc_array_l1 *const restrict, GFC_LOGICAL_4);
170181254a7Smrg export_proto(mfindloc0_i16);
171181254a7Smrg 
172181254a7Smrg void
mfindloc0_i16(gfc_array_index_type * const restrict retarray,gfc_array_i16 * const restrict array,GFC_INTEGER_16 value,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back)173181254a7Smrg mfindloc0_i16 (gfc_array_index_type * const restrict retarray,
174181254a7Smrg     	    gfc_array_i16 * const restrict array, GFC_INTEGER_16 value,
175181254a7Smrg 	    gfc_array_l1 *const restrict mask, GFC_LOGICAL_4 back)
176181254a7Smrg {
177181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
178181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
179181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
180181254a7Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
181181254a7Smrg   index_type dstride;
182181254a7Smrg   const GFC_INTEGER_16 *base;
183181254a7Smrg   index_type * restrict dest;
184181254a7Smrg   GFC_LOGICAL_1 *mbase;
185181254a7Smrg   index_type rank;
186181254a7Smrg   index_type n;
187181254a7Smrg   int mask_kind;
188181254a7Smrg   index_type sz;
189181254a7Smrg 
190181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
191181254a7Smrg   if (rank <= 0)
192181254a7Smrg     runtime_error ("Rank of array needs to be > 0");
193181254a7Smrg 
194181254a7Smrg   if (retarray->base_addr == NULL)
195181254a7Smrg     {
196181254a7Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
197181254a7Smrg       retarray->dtype.rank = 1;
198181254a7Smrg       retarray->offset = 0;
199181254a7Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
200181254a7Smrg     }
201181254a7Smrg   else
202181254a7Smrg     {
203181254a7Smrg       if (unlikely (compile_options.bounds_check))
204181254a7Smrg 	{
205181254a7Smrg 	  bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
206181254a7Smrg 				  "FINDLOC");
207181254a7Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
208181254a7Smrg 				"MASK argument", "FINDLOC");
209181254a7Smrg 	}
210181254a7Smrg     }
211181254a7Smrg 
212181254a7Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
213181254a7Smrg 
214181254a7Smrg   mbase = mask->base_addr;
215181254a7Smrg 
216181254a7Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
217181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
218181254a7Smrg       || mask_kind == 16
219181254a7Smrg #endif
220181254a7Smrg       )
221181254a7Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
222181254a7Smrg   else
223181254a7Smrg     internal_error (NULL, "Funny sized logical array");
224181254a7Smrg 
225181254a7Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
226181254a7Smrg   dest = retarray->base_addr;
227181254a7Smrg 
228181254a7Smrg   /* Set the return value.  */
229181254a7Smrg   for (n = 0; n < rank; n++)
230181254a7Smrg     dest[n * dstride] = 0;
231181254a7Smrg 
232181254a7Smrg   sz = 1;
233181254a7Smrg   for (n = 0; n < rank; n++)
234181254a7Smrg     {
235181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
236181254a7Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
237181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
238181254a7Smrg       sz *= extent[n];
239181254a7Smrg       if (extent[n] <= 0)
240181254a7Smrg 	return;
241181254a7Smrg     }
242181254a7Smrg 
243181254a7Smrg     for (n = 0; n < rank; n++)
244181254a7Smrg       count[n] = 0;
245181254a7Smrg 
246181254a7Smrg   if (back)
247181254a7Smrg     {
248181254a7Smrg       base = array->base_addr + (sz - 1) * 1;
249181254a7Smrg       mbase = mbase + (sz - 1) * mask_kind;
250181254a7Smrg       while (1)
251181254a7Smrg         {
252181254a7Smrg 	  do
253181254a7Smrg 	    {
254181254a7Smrg 	      if (unlikely(*mbase && *base == value))
255181254a7Smrg 	        {
256181254a7Smrg 		  for (n = 0; n < rank; n++)
257181254a7Smrg 		    dest[n * dstride] = extent[n] - count[n];
258181254a7Smrg 
259181254a7Smrg 		  return;
260181254a7Smrg 		}
261181254a7Smrg 	      base -= sstride[0] * 1;
262181254a7Smrg 	      mbase -= mstride[0];
263181254a7Smrg 	    } while(++count[0] != extent[0]);
264181254a7Smrg 
265181254a7Smrg 	  n = 0;
266181254a7Smrg 	  do
267181254a7Smrg 	    {
268181254a7Smrg 	      /* When we get to the end of a dimension, reset it and increment
269181254a7Smrg 		 the next dimension.  */
270181254a7Smrg 	      count[n] = 0;
271181254a7Smrg 	      /* We could precalculate these products, but this is a less
272181254a7Smrg 		 frequently used path so probably not worth it.  */
273181254a7Smrg 	      base += sstride[n] * extent[n] * 1;
274181254a7Smrg 	      mbase -= mstride[n] * extent[n];
275181254a7Smrg 	      n++;
276181254a7Smrg 	      if (n >= rank)
277181254a7Smrg 		return;
278181254a7Smrg 	      else
279181254a7Smrg 		{
280181254a7Smrg 		  count[n]++;
281181254a7Smrg 		  base -= sstride[n] * 1;
282181254a7Smrg 		  mbase += mstride[n];
283181254a7Smrg 		}
284181254a7Smrg 	    } while (count[n] == extent[n]);
285181254a7Smrg 	}
286181254a7Smrg     }
287181254a7Smrg   else
288181254a7Smrg     {
289181254a7Smrg       base = array->base_addr;
290181254a7Smrg       while (1)
291181254a7Smrg         {
292181254a7Smrg 	  do
293181254a7Smrg 	    {
294181254a7Smrg 	      if (unlikely(*mbase && *base == value))
295181254a7Smrg 	        {
296181254a7Smrg 		  for (n = 0; n < rank; n++)
297181254a7Smrg 		    dest[n * dstride] = count[n] + 1;
298181254a7Smrg 
299181254a7Smrg 		  return;
300181254a7Smrg 		}
301181254a7Smrg 	      base += sstride[0] * 1;
302181254a7Smrg 	      mbase += mstride[0];
303181254a7Smrg 	    } while(++count[0] != extent[0]);
304181254a7Smrg 
305181254a7Smrg 	  n = 0;
306181254a7Smrg 	  do
307181254a7Smrg 	    {
308181254a7Smrg 	      /* When we get to the end of a dimension, reset it and increment
309181254a7Smrg 		 the next dimension.  */
310181254a7Smrg 	      count[n] = 0;
311181254a7Smrg 	      /* We could precalculate these products, but this is a less
312181254a7Smrg 		 frequently used path so probably not worth it.  */
313181254a7Smrg 	      base -= sstride[n] * extent[n] * 1;
314181254a7Smrg 	      mbase -= mstride[n] * extent[n];
315181254a7Smrg 	      n++;
316181254a7Smrg 	      if (n >= rank)
317181254a7Smrg 		return;
318181254a7Smrg 	      else
319181254a7Smrg 		{
320181254a7Smrg 		  count[n]++;
321181254a7Smrg 		  base += sstride[n]* 1;
322181254a7Smrg 		  mbase += mstride[n];
323181254a7Smrg 		}
324181254a7Smrg 	    } while (count[n] == extent[n]);
325181254a7Smrg 	}
326181254a7Smrg     }
327181254a7Smrg   return;
328181254a7Smrg }
329181254a7Smrg 
330181254a7Smrg extern void sfindloc0_i16 (gfc_array_index_type * const restrict retarray,
331181254a7Smrg        	    		gfc_array_i16 * const restrict array, GFC_INTEGER_16 value,
332181254a7Smrg 			 GFC_LOGICAL_4 *, GFC_LOGICAL_4);
333181254a7Smrg export_proto(sfindloc0_i16);
334181254a7Smrg 
335181254a7Smrg void
sfindloc0_i16(gfc_array_index_type * const restrict retarray,gfc_array_i16 * const restrict array,GFC_INTEGER_16 value,GFC_LOGICAL_4 * mask,GFC_LOGICAL_4 back)336181254a7Smrg sfindloc0_i16 (gfc_array_index_type * const restrict retarray,
337181254a7Smrg     	    gfc_array_i16 * const restrict array, GFC_INTEGER_16 value,
338181254a7Smrg 	    GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
339181254a7Smrg {
340181254a7Smrg   index_type rank;
341181254a7Smrg   index_type dstride;
342181254a7Smrg   index_type * restrict dest;
343181254a7Smrg   index_type n;
344181254a7Smrg 
345181254a7Smrg   if (mask == NULL || *mask)
346181254a7Smrg     {
347181254a7Smrg       findloc0_i16 (retarray, array, value, back);
348181254a7Smrg       return;
349181254a7Smrg     }
350181254a7Smrg 
351181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
352181254a7Smrg 
353181254a7Smrg   if (rank <= 0)
354181254a7Smrg     internal_error (NULL, "Rank of array needs to be > 0");
355181254a7Smrg 
356181254a7Smrg   if (retarray->base_addr == NULL)
357181254a7Smrg     {
358181254a7Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
359181254a7Smrg       retarray->dtype.rank = 1;
360181254a7Smrg       retarray->offset = 0;
361181254a7Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
362181254a7Smrg     }
363181254a7Smrg   else if (unlikely (compile_options.bounds_check))
364181254a7Smrg     {
365181254a7Smrg        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
366181254a7Smrg 			       "FINDLOC");
367181254a7Smrg     }
368181254a7Smrg 
369181254a7Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
370181254a7Smrg   dest = retarray->base_addr;
371181254a7Smrg   for (n = 0; n<rank; n++)
372181254a7Smrg     dest[n * dstride] = 0 ;
373181254a7Smrg }
374181254a7Smrg 
375181254a7Smrg #endif
376