xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/generated/minloc0_8_i2.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg /* Implementation of the MINLOC intrinsic
2*4c3eb207Smrg    Copyright (C) 2002-2020 Free Software Foundation, Inc.
3627f7eb2Smrg    Contributed by Paul Brook <paul@nowt.org>
4627f7eb2Smrg 
5627f7eb2Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
6627f7eb2Smrg 
7627f7eb2Smrg Libgfortran is free software; you can redistribute it and/or
8627f7eb2Smrg modify it under the terms of the GNU General Public
9627f7eb2Smrg License as published by the Free Software Foundation; either
10627f7eb2Smrg version 3 of the License, or (at your option) any later version.
11627f7eb2Smrg 
12627f7eb2Smrg Libgfortran is distributed in the hope that it will be useful,
13627f7eb2Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14627f7eb2Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15627f7eb2Smrg GNU General Public License for more details.
16627f7eb2Smrg 
17627f7eb2Smrg Under Section 7 of GPL version 3, you are granted additional
18627f7eb2Smrg permissions described in the GCC Runtime Library Exception, version
19627f7eb2Smrg 3.1, as published by the Free Software Foundation.
20627f7eb2Smrg 
21627f7eb2Smrg You should have received a copy of the GNU General Public License and
22627f7eb2Smrg a copy of the GCC Runtime Library Exception along with this program;
23627f7eb2Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24627f7eb2Smrg <http://www.gnu.org/licenses/>.  */
25627f7eb2Smrg 
26627f7eb2Smrg #include "libgfortran.h"
27627f7eb2Smrg #include <assert.h>
28627f7eb2Smrg 
29627f7eb2Smrg 
30627f7eb2Smrg #if defined (HAVE_GFC_INTEGER_2) && defined (HAVE_GFC_INTEGER_8)
31627f7eb2Smrg 
32627f7eb2Smrg 
33627f7eb2Smrg extern void minloc0_8_i2 (gfc_array_i8 * const restrict retarray,
34627f7eb2Smrg 	gfc_array_i2 * const restrict array, GFC_LOGICAL_4);
35627f7eb2Smrg export_proto(minloc0_8_i2);
36627f7eb2Smrg 
37627f7eb2Smrg void
minloc0_8_i2(gfc_array_i8 * const restrict retarray,gfc_array_i2 * const restrict array,GFC_LOGICAL_4 back)38627f7eb2Smrg minloc0_8_i2 (gfc_array_i8 * const restrict retarray,
39627f7eb2Smrg 	gfc_array_i2 * const restrict array, 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_INTEGER_2 *base;
46627f7eb2Smrg   GFC_INTEGER_8 * restrict dest;
47627f7eb2Smrg   index_type rank;
48627f7eb2Smrg   index_type n;
49627f7eb2Smrg 
50627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
51627f7eb2Smrg   if (rank <= 0)
52627f7eb2Smrg     runtime_error ("Rank of array needs to be > 0");
53627f7eb2Smrg 
54627f7eb2Smrg   if (retarray->base_addr == NULL)
55627f7eb2Smrg     {
56627f7eb2Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
57627f7eb2Smrg       retarray->dtype.rank = 1;
58627f7eb2Smrg       retarray->offset = 0;
59627f7eb2Smrg       retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
60627f7eb2Smrg     }
61627f7eb2Smrg   else
62627f7eb2Smrg     {
63627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
64627f7eb2Smrg 	bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
65627f7eb2Smrg 				"MINLOC");
66627f7eb2Smrg     }
67627f7eb2Smrg 
68627f7eb2Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
69627f7eb2Smrg   dest = retarray->base_addr;
70627f7eb2Smrg   for (n = 0; n < rank; n++)
71627f7eb2Smrg     {
72627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
73627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
74627f7eb2Smrg       count[n] = 0;
75627f7eb2Smrg       if (extent[n] <= 0)
76627f7eb2Smrg 	{
77627f7eb2Smrg 	  /* Set the return value.  */
78627f7eb2Smrg 	  for (n = 0; n < rank; n++)
79627f7eb2Smrg 	    dest[n * dstride] = 0;
80627f7eb2Smrg 	  return;
81627f7eb2Smrg 	}
82627f7eb2Smrg     }
83627f7eb2Smrg 
84627f7eb2Smrg   base = array->base_addr;
85627f7eb2Smrg 
86627f7eb2Smrg   /* Initialize the return value.  */
87627f7eb2Smrg   for (n = 0; n < rank; n++)
88627f7eb2Smrg     dest[n * dstride] = 1;
89627f7eb2Smrg   {
90627f7eb2Smrg 
91627f7eb2Smrg     GFC_INTEGER_2 minval;
92627f7eb2Smrg #if defined(GFC_INTEGER_2_QUIET_NAN)
93627f7eb2Smrg     int fast = 0;
94627f7eb2Smrg #endif
95627f7eb2Smrg 
96627f7eb2Smrg #if defined(GFC_INTEGER_2_INFINITY)
97627f7eb2Smrg     minval = GFC_INTEGER_2_INFINITY;
98627f7eb2Smrg #else
99627f7eb2Smrg     minval = GFC_INTEGER_2_HUGE;
100627f7eb2Smrg #endif
101627f7eb2Smrg   while (base)
102627f7eb2Smrg     {
103627f7eb2Smrg 	  /* Implementation start.  */
104627f7eb2Smrg 
105627f7eb2Smrg #if defined(GFC_INTEGER_2_QUIET_NAN)
106627f7eb2Smrg       if (unlikely (!fast))
107627f7eb2Smrg 	{
108627f7eb2Smrg 	  do
109627f7eb2Smrg 	    {
110627f7eb2Smrg 	      if (*base <= minval)
111627f7eb2Smrg 		{
112627f7eb2Smrg 		  fast = 1;
113627f7eb2Smrg 		  minval = *base;
114627f7eb2Smrg 		  for (n = 0; n < rank; n++)
115627f7eb2Smrg 		    dest[n * dstride] = count[n] + 1;
116627f7eb2Smrg 		  break;
117627f7eb2Smrg 		}
118627f7eb2Smrg 	      base += sstride[0];
119627f7eb2Smrg 	    }
120627f7eb2Smrg 	  while (++count[0] != extent[0]);
121627f7eb2Smrg 	  if (likely (fast))
122627f7eb2Smrg 	    continue;
123627f7eb2Smrg 	}
124627f7eb2Smrg       else
125627f7eb2Smrg #endif
126627f7eb2Smrg       if (back)
127627f7eb2Smrg 	do
128627f7eb2Smrg 	  {
129627f7eb2Smrg 	    if (unlikely (*base <= minval))
130627f7eb2Smrg 	      {
131627f7eb2Smrg 		minval = *base;
132627f7eb2Smrg 		for (n = 0; n < rank; n++)
133627f7eb2Smrg 		  dest[n * dstride] = count[n] + 1;
134627f7eb2Smrg 	      }
135627f7eb2Smrg 	    base += sstride[0];
136627f7eb2Smrg 	  }
137627f7eb2Smrg 	while (++count[0] != extent[0]);
138627f7eb2Smrg       else
139627f7eb2Smrg 	do
140627f7eb2Smrg 	  {
141627f7eb2Smrg 	    if (unlikely (*base < minval))
142627f7eb2Smrg 	      {
143627f7eb2Smrg 		minval = *base;
144627f7eb2Smrg 		for (n = 0; n < rank; n++)
145627f7eb2Smrg 		  dest[n * dstride] = count[n] + 1;
146627f7eb2Smrg 	      }
147627f7eb2Smrg 	  /* Implementation end.  */
148627f7eb2Smrg 	  /* Advance to the next element.  */
149627f7eb2Smrg 	  base += sstride[0];
150627f7eb2Smrg 	}
151627f7eb2Smrg       while (++count[0] != extent[0]);
152627f7eb2Smrg       n = 0;
153627f7eb2Smrg       do
154627f7eb2Smrg 	{
155627f7eb2Smrg 	  /* When we get to the end of a dimension, reset it and increment
156627f7eb2Smrg 	     the next dimension.  */
157627f7eb2Smrg 	  count[n] = 0;
158627f7eb2Smrg 	  /* We could precalculate these products, but this is a less
159627f7eb2Smrg 	     frequently used path so probably not worth it.  */
160627f7eb2Smrg 	  base -= sstride[n] * extent[n];
161627f7eb2Smrg 	  n++;
162627f7eb2Smrg 	  if (n >= rank)
163627f7eb2Smrg 	    {
164627f7eb2Smrg 	      /* Break out of the loop.  */
165627f7eb2Smrg 	      base = NULL;
166627f7eb2Smrg 	      break;
167627f7eb2Smrg 	    }
168627f7eb2Smrg 	  else
169627f7eb2Smrg 	    {
170627f7eb2Smrg 	      count[n]++;
171627f7eb2Smrg 	      base += sstride[n];
172627f7eb2Smrg 	    }
173627f7eb2Smrg 	}
174627f7eb2Smrg       while (count[n] == extent[n]);
175627f7eb2Smrg     }
176627f7eb2Smrg   }
177627f7eb2Smrg }
178627f7eb2Smrg 
179627f7eb2Smrg extern void mminloc0_8_i2 (gfc_array_i8 * const restrict,
180627f7eb2Smrg 	gfc_array_i2 * const restrict, gfc_array_l1 * const restrict,
181627f7eb2Smrg 	GFC_LOGICAL_4);
182627f7eb2Smrg export_proto(mminloc0_8_i2);
183627f7eb2Smrg 
184627f7eb2Smrg void
mminloc0_8_i2(gfc_array_i8 * const restrict retarray,gfc_array_i2 * const restrict array,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back)185627f7eb2Smrg mminloc0_8_i2 (gfc_array_i8 * const restrict retarray,
186627f7eb2Smrg 	gfc_array_i2 * const restrict array,
187627f7eb2Smrg 	gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back)
188627f7eb2Smrg {
189627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
190627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
191627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
192627f7eb2Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
193627f7eb2Smrg   index_type dstride;
194627f7eb2Smrg   GFC_INTEGER_8 *dest;
195627f7eb2Smrg   const GFC_INTEGER_2 *base;
196627f7eb2Smrg   GFC_LOGICAL_1 *mbase;
197627f7eb2Smrg   int rank;
198627f7eb2Smrg   index_type n;
199627f7eb2Smrg   int mask_kind;
200627f7eb2Smrg 
201627f7eb2Smrg 
202627f7eb2Smrg   if (mask == NULL)
203627f7eb2Smrg     {
204627f7eb2Smrg       minloc0_8_i2 (retarray, array, back);
205627f7eb2Smrg       return;
206627f7eb2Smrg     }
207627f7eb2Smrg 
208627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
209627f7eb2Smrg   if (rank <= 0)
210627f7eb2Smrg     runtime_error ("Rank of array needs to be > 0");
211627f7eb2Smrg 
212627f7eb2Smrg   if (retarray->base_addr == NULL)
213627f7eb2Smrg     {
214627f7eb2Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
215627f7eb2Smrg       retarray->dtype.rank = 1;
216627f7eb2Smrg       retarray->offset = 0;
217627f7eb2Smrg       retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
218627f7eb2Smrg     }
219627f7eb2Smrg   else
220627f7eb2Smrg     {
221627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
222627f7eb2Smrg 	{
223627f7eb2Smrg 
224627f7eb2Smrg 	  bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
225627f7eb2Smrg 				  "MINLOC");
226627f7eb2Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
227627f7eb2Smrg 				  "MASK argument", "MINLOC");
228627f7eb2Smrg 	}
229627f7eb2Smrg     }
230627f7eb2Smrg 
231627f7eb2Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
232627f7eb2Smrg 
233627f7eb2Smrg   mbase = mask->base_addr;
234627f7eb2Smrg 
235627f7eb2Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
236627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
237627f7eb2Smrg       || mask_kind == 16
238627f7eb2Smrg #endif
239627f7eb2Smrg       )
240627f7eb2Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
241627f7eb2Smrg   else
242627f7eb2Smrg     runtime_error ("Funny sized logical array");
243627f7eb2Smrg 
244627f7eb2Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
245627f7eb2Smrg   dest = retarray->base_addr;
246627f7eb2Smrg   for (n = 0; n < rank; n++)
247627f7eb2Smrg     {
248627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
249627f7eb2Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
250627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
251627f7eb2Smrg       count[n] = 0;
252627f7eb2Smrg       if (extent[n] <= 0)
253627f7eb2Smrg 	{
254627f7eb2Smrg 	  /* Set the return value.  */
255627f7eb2Smrg 	  for (n = 0; n < rank; n++)
256627f7eb2Smrg 	    dest[n * dstride] = 0;
257627f7eb2Smrg 	  return;
258627f7eb2Smrg 	}
259627f7eb2Smrg     }
260627f7eb2Smrg 
261627f7eb2Smrg   base = array->base_addr;
262627f7eb2Smrg 
263627f7eb2Smrg   /* Initialize the return value.  */
264627f7eb2Smrg   for (n = 0; n < rank; n++)
265627f7eb2Smrg     dest[n * dstride] = 0;
266627f7eb2Smrg   {
267627f7eb2Smrg 
268627f7eb2Smrg   GFC_INTEGER_2 minval;
269627f7eb2Smrg    int fast = 0;
270627f7eb2Smrg 
271627f7eb2Smrg #if defined(GFC_INTEGER_2_INFINITY)
272627f7eb2Smrg     minval = GFC_INTEGER_2_INFINITY;
273627f7eb2Smrg #else
274627f7eb2Smrg     minval = GFC_INTEGER_2_HUGE;
275627f7eb2Smrg #endif
276627f7eb2Smrg   while (base)
277627f7eb2Smrg     {
278627f7eb2Smrg 	  /* Implementation start.  */
279627f7eb2Smrg 
280627f7eb2Smrg       if (unlikely (!fast))
281627f7eb2Smrg 	{
282627f7eb2Smrg 	  do
283627f7eb2Smrg 	    {
284627f7eb2Smrg 	      if (*mbase)
285627f7eb2Smrg 		{
286627f7eb2Smrg #if defined(GFC_INTEGER_2_QUIET_NAN)
287627f7eb2Smrg 		  if (unlikely (dest[0] == 0))
288627f7eb2Smrg 		    for (n = 0; n < rank; n++)
289627f7eb2Smrg 		      dest[n * dstride] = count[n] + 1;
290627f7eb2Smrg 		  if (*base <= minval)
291627f7eb2Smrg #endif
292627f7eb2Smrg 		    {
293627f7eb2Smrg 		      fast = 1;
294627f7eb2Smrg 		      minval = *base;
295627f7eb2Smrg 		      for (n = 0; n < rank; n++)
296627f7eb2Smrg 			dest[n * dstride] = count[n] + 1;
297627f7eb2Smrg 		      break;
298627f7eb2Smrg 		    }
299627f7eb2Smrg 		}
300627f7eb2Smrg 	      base += sstride[0];
301627f7eb2Smrg 	      mbase += mstride[0];
302627f7eb2Smrg 	    }
303627f7eb2Smrg 	  while (++count[0] != extent[0]);
304627f7eb2Smrg 	  if (likely (fast))
305627f7eb2Smrg 	    continue;
306627f7eb2Smrg 	}
307627f7eb2Smrg         else
308627f7eb2Smrg         if (back)
309627f7eb2Smrg 	  do
310627f7eb2Smrg 	    {
311627f7eb2Smrg 	      if (unlikely (*mbase && (*base <= minval)))
312627f7eb2Smrg 	        {
313627f7eb2Smrg 	      	  minval = *base;
314627f7eb2Smrg 	      	  for (n = 0; n < rank; n++)
315627f7eb2Smrg 		    dest[n * dstride] = count[n] + 1;
316627f7eb2Smrg 	    	}
317627f7eb2Smrg 		base += sstride[0];
318627f7eb2Smrg 	    }
319627f7eb2Smrg 	    while (++count[0] != extent[0]);
320627f7eb2Smrg 	else
321627f7eb2Smrg 	  do
322627f7eb2Smrg 	    {
323627f7eb2Smrg 	      if (unlikely (*mbase && (*base < minval)))
324627f7eb2Smrg 		{
325627f7eb2Smrg 		  minval = *base;
326627f7eb2Smrg 		  for (n = 0; n < rank; n++)
327627f7eb2Smrg 		    dest[n * dstride] = count[n] + 1;
328627f7eb2Smrg 		}
329627f7eb2Smrg 	  /* Implementation end.  */
330627f7eb2Smrg 	  /* Advance to the next element.  */
331627f7eb2Smrg 	  base += sstride[0];
332627f7eb2Smrg 	  mbase += mstride[0];
333627f7eb2Smrg 	}
334627f7eb2Smrg       while (++count[0] != extent[0]);
335627f7eb2Smrg       n = 0;
336627f7eb2Smrg       do
337627f7eb2Smrg 	{
338627f7eb2Smrg 	  /* When we get to the end of a dimension, reset it and increment
339627f7eb2Smrg 	     the next dimension.  */
340627f7eb2Smrg 	  count[n] = 0;
341627f7eb2Smrg 	  /* We could precalculate these products, but this is a less
342627f7eb2Smrg 	     frequently used path so probably not worth it.  */
343627f7eb2Smrg 	  base -= sstride[n] * extent[n];
344627f7eb2Smrg 	  mbase -= mstride[n] * extent[n];
345627f7eb2Smrg 	  n++;
346627f7eb2Smrg 	  if (n >= rank)
347627f7eb2Smrg 	    {
348627f7eb2Smrg 	      /* Break out of the loop.  */
349627f7eb2Smrg 	      base = NULL;
350627f7eb2Smrg 	      break;
351627f7eb2Smrg 	    }
352627f7eb2Smrg 	  else
353627f7eb2Smrg 	    {
354627f7eb2Smrg 	      count[n]++;
355627f7eb2Smrg 	      base += sstride[n];
356627f7eb2Smrg 	      mbase += mstride[n];
357627f7eb2Smrg 	    }
358627f7eb2Smrg 	}
359627f7eb2Smrg       while (count[n] == extent[n]);
360627f7eb2Smrg     }
361627f7eb2Smrg   }
362627f7eb2Smrg }
363627f7eb2Smrg 
364627f7eb2Smrg extern void sminloc0_8_i2 (gfc_array_i8 * const restrict,
365627f7eb2Smrg 	gfc_array_i2 * const restrict, GFC_LOGICAL_4 *, GFC_LOGICAL_4);
366627f7eb2Smrg export_proto(sminloc0_8_i2);
367627f7eb2Smrg 
368627f7eb2Smrg void
sminloc0_8_i2(gfc_array_i8 * const restrict retarray,gfc_array_i2 * const restrict array,GFC_LOGICAL_4 * mask,GFC_LOGICAL_4 back)369627f7eb2Smrg sminloc0_8_i2 (gfc_array_i8 * const restrict retarray,
370627f7eb2Smrg 	gfc_array_i2 * const restrict array,
371627f7eb2Smrg 	GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
372627f7eb2Smrg {
373627f7eb2Smrg   index_type rank;
374627f7eb2Smrg   index_type dstride;
375627f7eb2Smrg   index_type n;
376627f7eb2Smrg   GFC_INTEGER_8 *dest;
377627f7eb2Smrg 
378627f7eb2Smrg   if (mask == NULL || *mask)
379627f7eb2Smrg     {
380627f7eb2Smrg       minloc0_8_i2 (retarray, array, back);
381627f7eb2Smrg       return;
382627f7eb2Smrg     }
383627f7eb2Smrg 
384627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
385627f7eb2Smrg 
386627f7eb2Smrg   if (rank <= 0)
387627f7eb2Smrg     runtime_error ("Rank of array needs to be > 0");
388627f7eb2Smrg 
389627f7eb2Smrg   if (retarray->base_addr == NULL)
390627f7eb2Smrg     {
391627f7eb2Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
392627f7eb2Smrg       retarray->dtype.rank = 1;
393627f7eb2Smrg       retarray->offset = 0;
394627f7eb2Smrg       retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
395627f7eb2Smrg     }
396627f7eb2Smrg   else if (unlikely (compile_options.bounds_check))
397627f7eb2Smrg     {
398627f7eb2Smrg        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
399627f7eb2Smrg 			       "MINLOC");
400627f7eb2Smrg     }
401627f7eb2Smrg 
402627f7eb2Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
403627f7eb2Smrg   dest = retarray->base_addr;
404627f7eb2Smrg   for (n = 0; n<rank; n++)
405627f7eb2Smrg     dest[n * dstride] = 0 ;
406627f7eb2Smrg }
407627f7eb2Smrg #endif
408