xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/findloc0_c10.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1fb8a8121Smrg 
2fb8a8121Smrg /* Implementation of the FINDLOC intrinsic
3*b1e83836Smrg    Copyright (C) 2018-2022 Free Software Foundation, Inc.
4fb8a8121Smrg    Contributed by Thomas König <tk@tkoenig.net>
5fb8a8121Smrg 
6fb8a8121Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
7fb8a8121Smrg 
8fb8a8121Smrg Libgfortran is free software; you can redistribute it and/or
9fb8a8121Smrg modify it under the terms of the GNU General Public
10fb8a8121Smrg License as published by the Free Software Foundation; either
11fb8a8121Smrg version 3 of the License, or (at your option) any later version.
12fb8a8121Smrg 
13fb8a8121Smrg Libgfortran is distributed in the hope that it will be useful,
14fb8a8121Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
15fb8a8121Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16fb8a8121Smrg GNU General Public License for more details.
17fb8a8121Smrg 
18fb8a8121Smrg Under Section 7 of GPL version 3, you are granted additional
19fb8a8121Smrg permissions described in the GCC Runtime Library Exception, version
20fb8a8121Smrg 3.1, as published by the Free Software Foundation.
21fb8a8121Smrg 
22fb8a8121Smrg You should have received a copy of the GNU General Public License and
23fb8a8121Smrg a copy of the GCC Runtime Library Exception along with this program;
24fb8a8121Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25fb8a8121Smrg <http://www.gnu.org/licenses/>.  */
26fb8a8121Smrg 
27fb8a8121Smrg #include "libgfortran.h"
28fb8a8121Smrg #include <assert.h>
29fb8a8121Smrg 
30fb8a8121Smrg #if defined (HAVE_GFC_COMPLEX_10)
31fb8a8121Smrg extern void findloc0_c10 (gfc_array_index_type * const restrict retarray,
32fb8a8121Smrg        	    		gfc_array_c10 * const restrict array, GFC_COMPLEX_10 value,
33fb8a8121Smrg 			 GFC_LOGICAL_4);
34fb8a8121Smrg export_proto(findloc0_c10);
35fb8a8121Smrg 
36fb8a8121Smrg void
findloc0_c10(gfc_array_index_type * const restrict retarray,gfc_array_c10 * const restrict array,GFC_COMPLEX_10 value,GFC_LOGICAL_4 back)37fb8a8121Smrg findloc0_c10 (gfc_array_index_type * const restrict retarray,
38fb8a8121Smrg     	    gfc_array_c10 * const restrict array, GFC_COMPLEX_10 value,
39fb8a8121Smrg 	    GFC_LOGICAL_4 back)
40fb8a8121Smrg {
41fb8a8121Smrg   index_type count[GFC_MAX_DIMENSIONS];
42fb8a8121Smrg   index_type extent[GFC_MAX_DIMENSIONS];
43fb8a8121Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
44fb8a8121Smrg   index_type dstride;
45fb8a8121Smrg   const GFC_COMPLEX_10 *base;
46fb8a8121Smrg   index_type * restrict dest;
47fb8a8121Smrg   index_type rank;
48fb8a8121Smrg   index_type n;
49fb8a8121Smrg   index_type sz;
50fb8a8121Smrg 
51fb8a8121Smrg   rank = GFC_DESCRIPTOR_RANK (array);
52fb8a8121Smrg   if (rank <= 0)
53fb8a8121Smrg     runtime_error ("Rank of array needs to be > 0");
54fb8a8121Smrg 
55fb8a8121Smrg   if (retarray->base_addr == NULL)
56fb8a8121Smrg     {
57fb8a8121Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
58fb8a8121Smrg       retarray->dtype.rank = 1;
59fb8a8121Smrg       retarray->offset = 0;
60fb8a8121Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
61fb8a8121Smrg     }
62fb8a8121Smrg   else
63fb8a8121Smrg     {
64fb8a8121Smrg       if (unlikely (compile_options.bounds_check))
65fb8a8121Smrg 	bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
66fb8a8121Smrg 				"FINDLOC");
67fb8a8121Smrg     }
68fb8a8121Smrg 
69fb8a8121Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
70fb8a8121Smrg   dest = retarray->base_addr;
71fb8a8121Smrg 
72fb8a8121Smrg   /* Set the return value.  */
73fb8a8121Smrg   for (n = 0; n < rank; n++)
74fb8a8121Smrg     dest[n * dstride] = 0;
75fb8a8121Smrg 
76fb8a8121Smrg   sz = 1;
77fb8a8121Smrg   for (n = 0; n < rank; n++)
78fb8a8121Smrg     {
79fb8a8121Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
80fb8a8121Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
81fb8a8121Smrg       sz *= extent[n];
82fb8a8121Smrg       if (extent[n] <= 0)
83fb8a8121Smrg 	return;
84fb8a8121Smrg     }
85fb8a8121Smrg 
86fb8a8121Smrg     for (n = 0; n < rank; n++)
87fb8a8121Smrg       count[n] = 0;
88fb8a8121Smrg 
89fb8a8121Smrg   if (back)
90fb8a8121Smrg     {
91fb8a8121Smrg       base = array->base_addr + (sz - 1) * 1;
92fb8a8121Smrg 
93fb8a8121Smrg       while (1)
94fb8a8121Smrg         {
95fb8a8121Smrg 	  do
96fb8a8121Smrg 	    {
97fb8a8121Smrg 	      if (unlikely(*base == value))
98fb8a8121Smrg 	        {
99fb8a8121Smrg 		  for (n = 0; n < rank; n++)
100fb8a8121Smrg 		    dest[n * dstride] = extent[n] - count[n];
101fb8a8121Smrg 
102fb8a8121Smrg 		  return;
103fb8a8121Smrg 		}
104fb8a8121Smrg 	      base -= sstride[0] * 1;
105fb8a8121Smrg 	    } while(++count[0] != extent[0]);
106fb8a8121Smrg 
107fb8a8121Smrg 	  n = 0;
108fb8a8121Smrg 	  do
109fb8a8121Smrg 	    {
110fb8a8121Smrg 	      /* When we get to the end of a dimension, reset it and increment
111fb8a8121Smrg 		 the next dimension.  */
112fb8a8121Smrg 	      count[n] = 0;
113fb8a8121Smrg 	      /* We could precalculate these products, but this is a less
114fb8a8121Smrg 		 frequently used path so probably not worth it.  */
115fb8a8121Smrg 	      base += sstride[n] * extent[n] * 1;
116fb8a8121Smrg 	      n++;
117fb8a8121Smrg 	      if (n >= rank)
118fb8a8121Smrg 	        return;
119fb8a8121Smrg 	      else
120fb8a8121Smrg 		{
121fb8a8121Smrg 		  count[n]++;
122fb8a8121Smrg 		  base -= sstride[n] * 1;
123fb8a8121Smrg 		}
124fb8a8121Smrg 	    } while (count[n] == extent[n]);
125fb8a8121Smrg 	}
126fb8a8121Smrg     }
127fb8a8121Smrg   else
128fb8a8121Smrg     {
129fb8a8121Smrg       base = array->base_addr;
130fb8a8121Smrg       while (1)
131fb8a8121Smrg         {
132fb8a8121Smrg 	  do
133fb8a8121Smrg 	    {
134fb8a8121Smrg 	      if (unlikely(*base == value))
135fb8a8121Smrg 	        {
136fb8a8121Smrg 		  for (n = 0; n < rank; n++)
137fb8a8121Smrg 		    dest[n * dstride] = count[n] + 1;
138fb8a8121Smrg 
139fb8a8121Smrg 		  return;
140fb8a8121Smrg 		}
141fb8a8121Smrg 	      base += sstride[0] * 1;
142fb8a8121Smrg 	    } while(++count[0] != extent[0]);
143fb8a8121Smrg 
144fb8a8121Smrg 	  n = 0;
145fb8a8121Smrg 	  do
146fb8a8121Smrg 	    {
147fb8a8121Smrg 	      /* When we get to the end of a dimension, reset it and increment
148fb8a8121Smrg 		 the next dimension.  */
149fb8a8121Smrg 	      count[n] = 0;
150fb8a8121Smrg 	      /* We could precalculate these products, but this is a less
151fb8a8121Smrg 		 frequently used path so probably not worth it.  */
152fb8a8121Smrg 	      base -= sstride[n] * extent[n] * 1;
153fb8a8121Smrg 	      n++;
154fb8a8121Smrg 	      if (n >= rank)
155fb8a8121Smrg 	        return;
156fb8a8121Smrg 	      else
157fb8a8121Smrg 		{
158fb8a8121Smrg 		  count[n]++;
159fb8a8121Smrg 		  base += sstride[n] * 1;
160fb8a8121Smrg 		}
161fb8a8121Smrg 	    } while (count[n] == extent[n]);
162fb8a8121Smrg 	}
163fb8a8121Smrg     }
164fb8a8121Smrg   return;
165fb8a8121Smrg }
166fb8a8121Smrg 
167fb8a8121Smrg extern void mfindloc0_c10 (gfc_array_index_type * const restrict retarray,
168fb8a8121Smrg        	    		gfc_array_c10 * const restrict array, GFC_COMPLEX_10 value,
169fb8a8121Smrg 			 gfc_array_l1 *const restrict, GFC_LOGICAL_4);
170fb8a8121Smrg export_proto(mfindloc0_c10);
171fb8a8121Smrg 
172fb8a8121Smrg void
mfindloc0_c10(gfc_array_index_type * const restrict retarray,gfc_array_c10 * const restrict array,GFC_COMPLEX_10 value,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back)173fb8a8121Smrg mfindloc0_c10 (gfc_array_index_type * const restrict retarray,
174fb8a8121Smrg     	    gfc_array_c10 * const restrict array, GFC_COMPLEX_10 value,
175fb8a8121Smrg 	    gfc_array_l1 *const restrict mask, GFC_LOGICAL_4 back)
176fb8a8121Smrg {
177fb8a8121Smrg   index_type count[GFC_MAX_DIMENSIONS];
178fb8a8121Smrg   index_type extent[GFC_MAX_DIMENSIONS];
179fb8a8121Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
180fb8a8121Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
181fb8a8121Smrg   index_type dstride;
182fb8a8121Smrg   const GFC_COMPLEX_10 *base;
183fb8a8121Smrg   index_type * restrict dest;
184fb8a8121Smrg   GFC_LOGICAL_1 *mbase;
185fb8a8121Smrg   index_type rank;
186fb8a8121Smrg   index_type n;
187fb8a8121Smrg   int mask_kind;
188fb8a8121Smrg   index_type sz;
189fb8a8121Smrg 
190fb8a8121Smrg   rank = GFC_DESCRIPTOR_RANK (array);
191fb8a8121Smrg   if (rank <= 0)
192fb8a8121Smrg     runtime_error ("Rank of array needs to be > 0");
193fb8a8121Smrg 
194fb8a8121Smrg   if (retarray->base_addr == NULL)
195fb8a8121Smrg     {
196fb8a8121Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
197fb8a8121Smrg       retarray->dtype.rank = 1;
198fb8a8121Smrg       retarray->offset = 0;
199fb8a8121Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
200fb8a8121Smrg     }
201fb8a8121Smrg   else
202fb8a8121Smrg     {
203fb8a8121Smrg       if (unlikely (compile_options.bounds_check))
204fb8a8121Smrg 	{
205fb8a8121Smrg 	  bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
206fb8a8121Smrg 				  "FINDLOC");
207fb8a8121Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
208fb8a8121Smrg 				"MASK argument", "FINDLOC");
209fb8a8121Smrg 	}
210fb8a8121Smrg     }
211fb8a8121Smrg 
212fb8a8121Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
213fb8a8121Smrg 
214fb8a8121Smrg   mbase = mask->base_addr;
215fb8a8121Smrg 
216fb8a8121Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
217fb8a8121Smrg #ifdef HAVE_GFC_LOGICAL_16
218fb8a8121Smrg       || mask_kind == 16
219fb8a8121Smrg #endif
220fb8a8121Smrg       )
221fb8a8121Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
222fb8a8121Smrg   else
223fb8a8121Smrg     internal_error (NULL, "Funny sized logical array");
224fb8a8121Smrg 
225fb8a8121Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
226fb8a8121Smrg   dest = retarray->base_addr;
227fb8a8121Smrg 
228fb8a8121Smrg   /* Set the return value.  */
229fb8a8121Smrg   for (n = 0; n < rank; n++)
230fb8a8121Smrg     dest[n * dstride] = 0;
231fb8a8121Smrg 
232fb8a8121Smrg   sz = 1;
233fb8a8121Smrg   for (n = 0; n < rank; n++)
234fb8a8121Smrg     {
235fb8a8121Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
236fb8a8121Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
237fb8a8121Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
238fb8a8121Smrg       sz *= extent[n];
239fb8a8121Smrg       if (extent[n] <= 0)
240fb8a8121Smrg 	return;
241fb8a8121Smrg     }
242fb8a8121Smrg 
243fb8a8121Smrg     for (n = 0; n < rank; n++)
244fb8a8121Smrg       count[n] = 0;
245fb8a8121Smrg 
246fb8a8121Smrg   if (back)
247fb8a8121Smrg     {
248fb8a8121Smrg       base = array->base_addr + (sz - 1) * 1;
249fb8a8121Smrg       mbase = mbase + (sz - 1) * mask_kind;
250fb8a8121Smrg       while (1)
251fb8a8121Smrg         {
252fb8a8121Smrg 	  do
253fb8a8121Smrg 	    {
254fb8a8121Smrg 	      if (unlikely(*mbase && *base == value))
255fb8a8121Smrg 	        {
256fb8a8121Smrg 		  for (n = 0; n < rank; n++)
257fb8a8121Smrg 		    dest[n * dstride] = extent[n] - count[n];
258fb8a8121Smrg 
259fb8a8121Smrg 		  return;
260fb8a8121Smrg 		}
261fb8a8121Smrg 	      base -= sstride[0] * 1;
262fb8a8121Smrg 	      mbase -= mstride[0];
263fb8a8121Smrg 	    } while(++count[0] != extent[0]);
264fb8a8121Smrg 
265fb8a8121Smrg 	  n = 0;
266fb8a8121Smrg 	  do
267fb8a8121Smrg 	    {
268fb8a8121Smrg 	      /* When we get to the end of a dimension, reset it and increment
269fb8a8121Smrg 		 the next dimension.  */
270fb8a8121Smrg 	      count[n] = 0;
271fb8a8121Smrg 	      /* We could precalculate these products, but this is a less
272fb8a8121Smrg 		 frequently used path so probably not worth it.  */
273fb8a8121Smrg 	      base += sstride[n] * extent[n] * 1;
274fb8a8121Smrg 	      mbase -= mstride[n] * extent[n];
275fb8a8121Smrg 	      n++;
276fb8a8121Smrg 	      if (n >= rank)
277fb8a8121Smrg 		return;
278fb8a8121Smrg 	      else
279fb8a8121Smrg 		{
280fb8a8121Smrg 		  count[n]++;
281fb8a8121Smrg 		  base -= sstride[n] * 1;
282fb8a8121Smrg 		  mbase += mstride[n];
283fb8a8121Smrg 		}
284fb8a8121Smrg 	    } while (count[n] == extent[n]);
285fb8a8121Smrg 	}
286fb8a8121Smrg     }
287fb8a8121Smrg   else
288fb8a8121Smrg     {
289fb8a8121Smrg       base = array->base_addr;
290fb8a8121Smrg       while (1)
291fb8a8121Smrg         {
292fb8a8121Smrg 	  do
293fb8a8121Smrg 	    {
294fb8a8121Smrg 	      if (unlikely(*mbase && *base == value))
295fb8a8121Smrg 	        {
296fb8a8121Smrg 		  for (n = 0; n < rank; n++)
297fb8a8121Smrg 		    dest[n * dstride] = count[n] + 1;
298fb8a8121Smrg 
299fb8a8121Smrg 		  return;
300fb8a8121Smrg 		}
301fb8a8121Smrg 	      base += sstride[0] * 1;
302fb8a8121Smrg 	      mbase += mstride[0];
303fb8a8121Smrg 	    } while(++count[0] != extent[0]);
304fb8a8121Smrg 
305fb8a8121Smrg 	  n = 0;
306fb8a8121Smrg 	  do
307fb8a8121Smrg 	    {
308fb8a8121Smrg 	      /* When we get to the end of a dimension, reset it and increment
309fb8a8121Smrg 		 the next dimension.  */
310fb8a8121Smrg 	      count[n] = 0;
311fb8a8121Smrg 	      /* We could precalculate these products, but this is a less
312fb8a8121Smrg 		 frequently used path so probably not worth it.  */
313fb8a8121Smrg 	      base -= sstride[n] * extent[n] * 1;
314fb8a8121Smrg 	      mbase -= mstride[n] * extent[n];
315fb8a8121Smrg 	      n++;
316fb8a8121Smrg 	      if (n >= rank)
317fb8a8121Smrg 		return;
318fb8a8121Smrg 	      else
319fb8a8121Smrg 		{
320fb8a8121Smrg 		  count[n]++;
321fb8a8121Smrg 		  base += sstride[n]* 1;
322fb8a8121Smrg 		  mbase += mstride[n];
323fb8a8121Smrg 		}
324fb8a8121Smrg 	    } while (count[n] == extent[n]);
325fb8a8121Smrg 	}
326fb8a8121Smrg     }
327fb8a8121Smrg   return;
328fb8a8121Smrg }
329fb8a8121Smrg 
330fb8a8121Smrg extern void sfindloc0_c10 (gfc_array_index_type * const restrict retarray,
331fb8a8121Smrg        	    		gfc_array_c10 * const restrict array, GFC_COMPLEX_10 value,
332fb8a8121Smrg 			 GFC_LOGICAL_4 *, GFC_LOGICAL_4);
333fb8a8121Smrg export_proto(sfindloc0_c10);
334fb8a8121Smrg 
335fb8a8121Smrg void
sfindloc0_c10(gfc_array_index_type * const restrict retarray,gfc_array_c10 * const restrict array,GFC_COMPLEX_10 value,GFC_LOGICAL_4 * mask,GFC_LOGICAL_4 back)336fb8a8121Smrg sfindloc0_c10 (gfc_array_index_type * const restrict retarray,
337fb8a8121Smrg     	    gfc_array_c10 * const restrict array, GFC_COMPLEX_10 value,
338fb8a8121Smrg 	    GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
339fb8a8121Smrg {
340fb8a8121Smrg   index_type rank;
341fb8a8121Smrg   index_type dstride;
342fb8a8121Smrg   index_type * restrict dest;
343fb8a8121Smrg   index_type n;
344fb8a8121Smrg 
345fb8a8121Smrg   if (mask == NULL || *mask)
346fb8a8121Smrg     {
347fb8a8121Smrg       findloc0_c10 (retarray, array, value, back);
348fb8a8121Smrg       return;
349fb8a8121Smrg     }
350fb8a8121Smrg 
351fb8a8121Smrg   rank = GFC_DESCRIPTOR_RANK (array);
352fb8a8121Smrg 
353fb8a8121Smrg   if (rank <= 0)
354fb8a8121Smrg     internal_error (NULL, "Rank of array needs to be > 0");
355fb8a8121Smrg 
356fb8a8121Smrg   if (retarray->base_addr == NULL)
357fb8a8121Smrg     {
358fb8a8121Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
359fb8a8121Smrg       retarray->dtype.rank = 1;
360fb8a8121Smrg       retarray->offset = 0;
361fb8a8121Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
362fb8a8121Smrg     }
363fb8a8121Smrg   else if (unlikely (compile_options.bounds_check))
364fb8a8121Smrg     {
365fb8a8121Smrg        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
366fb8a8121Smrg 			       "FINDLOC");
367fb8a8121Smrg     }
368fb8a8121Smrg 
369fb8a8121Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
370fb8a8121Smrg   dest = retarray->base_addr;
371fb8a8121Smrg   for (n = 0; n<rank; n++)
372fb8a8121Smrg     dest[n * dstride] = 0 ;
373fb8a8121Smrg }
374fb8a8121Smrg 
375fb8a8121Smrg #endif
376