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