xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/generated/findloc0_r16.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_REAL_16)
31627f7eb2Smrg extern void findloc0_r16 (gfc_array_index_type * const restrict retarray,
32627f7eb2Smrg        	    		gfc_array_r16 * const restrict array, GFC_REAL_16 value,
33627f7eb2Smrg 			 GFC_LOGICAL_4);
34627f7eb2Smrg export_proto(findloc0_r16);
35627f7eb2Smrg 
36627f7eb2Smrg void
findloc0_r16(gfc_array_index_type * const restrict retarray,gfc_array_r16 * const restrict array,GFC_REAL_16 value,GFC_LOGICAL_4 back)37627f7eb2Smrg findloc0_r16 (gfc_array_index_type * const restrict retarray,
38627f7eb2Smrg     	    gfc_array_r16 * const restrict array, GFC_REAL_16 value,
39627f7eb2Smrg 	    GFC_LOGICAL_4 back)
40627f7eb2Smrg {
41627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
42627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
43627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
44627f7eb2Smrg   index_type dstride;
45627f7eb2Smrg   const GFC_REAL_16 *base;
46627f7eb2Smrg   index_type * restrict dest;
47627f7eb2Smrg   index_type rank;
48627f7eb2Smrg   index_type n;
49627f7eb2Smrg   index_type sz;
50627f7eb2Smrg 
51627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
52627f7eb2Smrg   if (rank <= 0)
53627f7eb2Smrg     runtime_error ("Rank of array needs to be > 0");
54627f7eb2Smrg 
55627f7eb2Smrg   if (retarray->base_addr == NULL)
56627f7eb2Smrg     {
57627f7eb2Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
58627f7eb2Smrg       retarray->dtype.rank = 1;
59627f7eb2Smrg       retarray->offset = 0;
60627f7eb2Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
61627f7eb2Smrg     }
62627f7eb2Smrg   else
63627f7eb2Smrg     {
64627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
65627f7eb2Smrg 	bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
66627f7eb2Smrg 				"FINDLOC");
67627f7eb2Smrg     }
68627f7eb2Smrg 
69627f7eb2Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
70627f7eb2Smrg   dest = retarray->base_addr;
71627f7eb2Smrg 
72627f7eb2Smrg   /* Set the return value.  */
73627f7eb2Smrg   for (n = 0; n < rank; n++)
74627f7eb2Smrg     dest[n * dstride] = 0;
75627f7eb2Smrg 
76627f7eb2Smrg   sz = 1;
77627f7eb2Smrg   for (n = 0; n < rank; n++)
78627f7eb2Smrg     {
79627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
80627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
81627f7eb2Smrg       sz *= extent[n];
82627f7eb2Smrg       if (extent[n] <= 0)
83627f7eb2Smrg 	return;
84627f7eb2Smrg     }
85627f7eb2Smrg 
86627f7eb2Smrg     for (n = 0; n < rank; n++)
87627f7eb2Smrg       count[n] = 0;
88627f7eb2Smrg 
89627f7eb2Smrg   if (back)
90627f7eb2Smrg     {
91627f7eb2Smrg       base = array->base_addr + (sz - 1) * 1;
92627f7eb2Smrg 
93627f7eb2Smrg       while (1)
94627f7eb2Smrg         {
95627f7eb2Smrg 	  do
96627f7eb2Smrg 	    {
97627f7eb2Smrg 	      if (unlikely(*base == value))
98627f7eb2Smrg 	        {
99627f7eb2Smrg 		  for (n = 0; n < rank; n++)
100627f7eb2Smrg 		    dest[n * dstride] = extent[n] - count[n];
101627f7eb2Smrg 
102627f7eb2Smrg 		  return;
103627f7eb2Smrg 		}
104627f7eb2Smrg 	      base -= sstride[0] * 1;
105627f7eb2Smrg 	    } while(++count[0] != extent[0]);
106627f7eb2Smrg 
107627f7eb2Smrg 	  n = 0;
108627f7eb2Smrg 	  do
109627f7eb2Smrg 	    {
110627f7eb2Smrg 	      /* When we get to the end of a dimension, reset it and increment
111627f7eb2Smrg 		 the next dimension.  */
112627f7eb2Smrg 	      count[n] = 0;
113627f7eb2Smrg 	      /* We could precalculate these products, but this is a less
114627f7eb2Smrg 		 frequently used path so probably not worth it.  */
115627f7eb2Smrg 	      base += sstride[n] * extent[n] * 1;
116627f7eb2Smrg 	      n++;
117627f7eb2Smrg 	      if (n >= rank)
118627f7eb2Smrg 	        return;
119627f7eb2Smrg 	      else
120627f7eb2Smrg 		{
121627f7eb2Smrg 		  count[n]++;
122627f7eb2Smrg 		  base -= sstride[n] * 1;
123627f7eb2Smrg 		}
124627f7eb2Smrg 	    } while (count[n] == extent[n]);
125627f7eb2Smrg 	}
126627f7eb2Smrg     }
127627f7eb2Smrg   else
128627f7eb2Smrg     {
129627f7eb2Smrg       base = array->base_addr;
130627f7eb2Smrg       while (1)
131627f7eb2Smrg         {
132627f7eb2Smrg 	  do
133627f7eb2Smrg 	    {
134627f7eb2Smrg 	      if (unlikely(*base == value))
135627f7eb2Smrg 	        {
136627f7eb2Smrg 		  for (n = 0; n < rank; n++)
137627f7eb2Smrg 		    dest[n * dstride] = count[n] + 1;
138627f7eb2Smrg 
139627f7eb2Smrg 		  return;
140627f7eb2Smrg 		}
141627f7eb2Smrg 	      base += sstride[0] * 1;
142627f7eb2Smrg 	    } while(++count[0] != extent[0]);
143627f7eb2Smrg 
144627f7eb2Smrg 	  n = 0;
145627f7eb2Smrg 	  do
146627f7eb2Smrg 	    {
147627f7eb2Smrg 	      /* When we get to the end of a dimension, reset it and increment
148627f7eb2Smrg 		 the next dimension.  */
149627f7eb2Smrg 	      count[n] = 0;
150627f7eb2Smrg 	      /* We could precalculate these products, but this is a less
151627f7eb2Smrg 		 frequently used path so probably not worth it.  */
152627f7eb2Smrg 	      base -= sstride[n] * extent[n] * 1;
153627f7eb2Smrg 	      n++;
154627f7eb2Smrg 	      if (n >= rank)
155627f7eb2Smrg 	        return;
156627f7eb2Smrg 	      else
157627f7eb2Smrg 		{
158627f7eb2Smrg 		  count[n]++;
159627f7eb2Smrg 		  base += sstride[n] * 1;
160627f7eb2Smrg 		}
161627f7eb2Smrg 	    } while (count[n] == extent[n]);
162627f7eb2Smrg 	}
163627f7eb2Smrg     }
164627f7eb2Smrg   return;
165627f7eb2Smrg }
166627f7eb2Smrg 
167627f7eb2Smrg extern void mfindloc0_r16 (gfc_array_index_type * const restrict retarray,
168627f7eb2Smrg        	    		gfc_array_r16 * const restrict array, GFC_REAL_16 value,
169627f7eb2Smrg 			 gfc_array_l1 *const restrict, GFC_LOGICAL_4);
170627f7eb2Smrg export_proto(mfindloc0_r16);
171627f7eb2Smrg 
172627f7eb2Smrg void
mfindloc0_r16(gfc_array_index_type * const restrict retarray,gfc_array_r16 * const restrict array,GFC_REAL_16 value,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back)173627f7eb2Smrg mfindloc0_r16 (gfc_array_index_type * const restrict retarray,
174627f7eb2Smrg     	    gfc_array_r16 * const restrict array, GFC_REAL_16 value,
175627f7eb2Smrg 	    gfc_array_l1 *const restrict mask, GFC_LOGICAL_4 back)
176627f7eb2Smrg {
177627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
178627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
179627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
180627f7eb2Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
181627f7eb2Smrg   index_type dstride;
182627f7eb2Smrg   const GFC_REAL_16 *base;
183627f7eb2Smrg   index_type * restrict dest;
184627f7eb2Smrg   GFC_LOGICAL_1 *mbase;
185627f7eb2Smrg   index_type rank;
186627f7eb2Smrg   index_type n;
187627f7eb2Smrg   int mask_kind;
188627f7eb2Smrg   index_type sz;
189627f7eb2Smrg 
190627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
191627f7eb2Smrg   if (rank <= 0)
192627f7eb2Smrg     runtime_error ("Rank of array needs to be > 0");
193627f7eb2Smrg 
194627f7eb2Smrg   if (retarray->base_addr == NULL)
195627f7eb2Smrg     {
196627f7eb2Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
197627f7eb2Smrg       retarray->dtype.rank = 1;
198627f7eb2Smrg       retarray->offset = 0;
199627f7eb2Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
200627f7eb2Smrg     }
201627f7eb2Smrg   else
202627f7eb2Smrg     {
203627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
204627f7eb2Smrg 	{
205627f7eb2Smrg 	  bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
206627f7eb2Smrg 				  "FINDLOC");
207627f7eb2Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
208627f7eb2Smrg 				"MASK argument", "FINDLOC");
209627f7eb2Smrg 	}
210627f7eb2Smrg     }
211627f7eb2Smrg 
212627f7eb2Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
213627f7eb2Smrg 
214627f7eb2Smrg   mbase = mask->base_addr;
215627f7eb2Smrg 
216627f7eb2Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
217627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
218627f7eb2Smrg       || mask_kind == 16
219627f7eb2Smrg #endif
220627f7eb2Smrg       )
221627f7eb2Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
222627f7eb2Smrg   else
223627f7eb2Smrg     internal_error (NULL, "Funny sized logical array");
224627f7eb2Smrg 
225627f7eb2Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
226627f7eb2Smrg   dest = retarray->base_addr;
227627f7eb2Smrg 
228627f7eb2Smrg   /* Set the return value.  */
229627f7eb2Smrg   for (n = 0; n < rank; n++)
230627f7eb2Smrg     dest[n * dstride] = 0;
231627f7eb2Smrg 
232627f7eb2Smrg   sz = 1;
233627f7eb2Smrg   for (n = 0; n < rank; n++)
234627f7eb2Smrg     {
235627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
236627f7eb2Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
237627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
238627f7eb2Smrg       sz *= extent[n];
239627f7eb2Smrg       if (extent[n] <= 0)
240627f7eb2Smrg 	return;
241627f7eb2Smrg     }
242627f7eb2Smrg 
243627f7eb2Smrg     for (n = 0; n < rank; n++)
244627f7eb2Smrg       count[n] = 0;
245627f7eb2Smrg 
246627f7eb2Smrg   if (back)
247627f7eb2Smrg     {
248627f7eb2Smrg       base = array->base_addr + (sz - 1) * 1;
249627f7eb2Smrg       mbase = mbase + (sz - 1) * mask_kind;
250627f7eb2Smrg       while (1)
251627f7eb2Smrg         {
252627f7eb2Smrg 	  do
253627f7eb2Smrg 	    {
254627f7eb2Smrg 	      if (unlikely(*mbase && *base == value))
255627f7eb2Smrg 	        {
256627f7eb2Smrg 		  for (n = 0; n < rank; n++)
257627f7eb2Smrg 		    dest[n * dstride] = extent[n] - count[n];
258627f7eb2Smrg 
259627f7eb2Smrg 		  return;
260627f7eb2Smrg 		}
261627f7eb2Smrg 	      base -= sstride[0] * 1;
262627f7eb2Smrg 	      mbase -= mstride[0];
263627f7eb2Smrg 	    } while(++count[0] != extent[0]);
264627f7eb2Smrg 
265627f7eb2Smrg 	  n = 0;
266627f7eb2Smrg 	  do
267627f7eb2Smrg 	    {
268627f7eb2Smrg 	      /* When we get to the end of a dimension, reset it and increment
269627f7eb2Smrg 		 the next dimension.  */
270627f7eb2Smrg 	      count[n] = 0;
271627f7eb2Smrg 	      /* We could precalculate these products, but this is a less
272627f7eb2Smrg 		 frequently used path so probably not worth it.  */
273627f7eb2Smrg 	      base += sstride[n] * extent[n] * 1;
274627f7eb2Smrg 	      mbase -= mstride[n] * extent[n];
275627f7eb2Smrg 	      n++;
276627f7eb2Smrg 	      if (n >= rank)
277627f7eb2Smrg 		return;
278627f7eb2Smrg 	      else
279627f7eb2Smrg 		{
280627f7eb2Smrg 		  count[n]++;
281627f7eb2Smrg 		  base -= sstride[n] * 1;
282627f7eb2Smrg 		  mbase += mstride[n];
283627f7eb2Smrg 		}
284627f7eb2Smrg 	    } while (count[n] == extent[n]);
285627f7eb2Smrg 	}
286627f7eb2Smrg     }
287627f7eb2Smrg   else
288627f7eb2Smrg     {
289627f7eb2Smrg       base = array->base_addr;
290627f7eb2Smrg       while (1)
291627f7eb2Smrg         {
292627f7eb2Smrg 	  do
293627f7eb2Smrg 	    {
294627f7eb2Smrg 	      if (unlikely(*mbase && *base == value))
295627f7eb2Smrg 	        {
296627f7eb2Smrg 		  for (n = 0; n < rank; n++)
297627f7eb2Smrg 		    dest[n * dstride] = count[n] + 1;
298627f7eb2Smrg 
299627f7eb2Smrg 		  return;
300627f7eb2Smrg 		}
301627f7eb2Smrg 	      base += sstride[0] * 1;
302627f7eb2Smrg 	      mbase += mstride[0];
303627f7eb2Smrg 	    } while(++count[0] != extent[0]);
304627f7eb2Smrg 
305627f7eb2Smrg 	  n = 0;
306627f7eb2Smrg 	  do
307627f7eb2Smrg 	    {
308627f7eb2Smrg 	      /* When we get to the end of a dimension, reset it and increment
309627f7eb2Smrg 		 the next dimension.  */
310627f7eb2Smrg 	      count[n] = 0;
311627f7eb2Smrg 	      /* We could precalculate these products, but this is a less
312627f7eb2Smrg 		 frequently used path so probably not worth it.  */
313627f7eb2Smrg 	      base -= sstride[n] * extent[n] * 1;
314627f7eb2Smrg 	      mbase -= mstride[n] * extent[n];
315627f7eb2Smrg 	      n++;
316627f7eb2Smrg 	      if (n >= rank)
317627f7eb2Smrg 		return;
318627f7eb2Smrg 	      else
319627f7eb2Smrg 		{
320627f7eb2Smrg 		  count[n]++;
321627f7eb2Smrg 		  base += sstride[n]* 1;
322627f7eb2Smrg 		  mbase += mstride[n];
323627f7eb2Smrg 		}
324627f7eb2Smrg 	    } while (count[n] == extent[n]);
325627f7eb2Smrg 	}
326627f7eb2Smrg     }
327627f7eb2Smrg   return;
328627f7eb2Smrg }
329627f7eb2Smrg 
330627f7eb2Smrg extern void sfindloc0_r16 (gfc_array_index_type * const restrict retarray,
331627f7eb2Smrg        	    		gfc_array_r16 * const restrict array, GFC_REAL_16 value,
332627f7eb2Smrg 			 GFC_LOGICAL_4 *, GFC_LOGICAL_4);
333627f7eb2Smrg export_proto(sfindloc0_r16);
334627f7eb2Smrg 
335627f7eb2Smrg void
sfindloc0_r16(gfc_array_index_type * const restrict retarray,gfc_array_r16 * const restrict array,GFC_REAL_16 value,GFC_LOGICAL_4 * mask,GFC_LOGICAL_4 back)336627f7eb2Smrg sfindloc0_r16 (gfc_array_index_type * const restrict retarray,
337627f7eb2Smrg     	    gfc_array_r16 * const restrict array, GFC_REAL_16 value,
338627f7eb2Smrg 	    GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
339627f7eb2Smrg {
340627f7eb2Smrg   index_type rank;
341627f7eb2Smrg   index_type dstride;
342627f7eb2Smrg   index_type * restrict dest;
343627f7eb2Smrg   index_type n;
344627f7eb2Smrg 
345627f7eb2Smrg   if (mask == NULL || *mask)
346627f7eb2Smrg     {
347627f7eb2Smrg       findloc0_r16 (retarray, array, value, back);
348627f7eb2Smrg       return;
349627f7eb2Smrg     }
350627f7eb2Smrg 
351627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
352627f7eb2Smrg 
353627f7eb2Smrg   if (rank <= 0)
354627f7eb2Smrg     internal_error (NULL, "Rank of array needs to be > 0");
355627f7eb2Smrg 
356627f7eb2Smrg   if (retarray->base_addr == NULL)
357627f7eb2Smrg     {
358627f7eb2Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
359627f7eb2Smrg       retarray->dtype.rank = 1;
360627f7eb2Smrg       retarray->offset = 0;
361627f7eb2Smrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
362627f7eb2Smrg     }
363627f7eb2Smrg   else if (unlikely (compile_options.bounds_check))
364627f7eb2Smrg     {
365627f7eb2Smrg        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
366627f7eb2Smrg 			       "FINDLOC");
367627f7eb2Smrg     }
368627f7eb2Smrg 
369627f7eb2Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
370627f7eb2Smrg   dest = retarray->base_addr;
371627f7eb2Smrg   for (n = 0; n<rank; n++)
372627f7eb2Smrg     dest[n * dstride] = 0 ;
373627f7eb2Smrg }
374627f7eb2Smrg 
375627f7eb2Smrg #endif
376