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