xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/minloc0_8_i1.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1181254a7Smrg /* Implementation of the MINLOC intrinsic
2*b1e83836Smrg    Copyright (C) 2002-2022 Free Software Foundation, Inc.
3181254a7Smrg    Contributed by Paul Brook <paul@nowt.org>
4181254a7Smrg 
5181254a7Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
6181254a7Smrg 
7181254a7Smrg Libgfortran is free software; you can redistribute it and/or
8181254a7Smrg modify it under the terms of the GNU General Public
9181254a7Smrg License as published by the Free Software Foundation; either
10181254a7Smrg version 3 of the License, or (at your option) any later version.
11181254a7Smrg 
12181254a7Smrg Libgfortran is distributed in the hope that it will be useful,
13181254a7Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14181254a7Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15181254a7Smrg GNU General Public License for more details.
16181254a7Smrg 
17181254a7Smrg Under Section 7 of GPL version 3, you are granted additional
18181254a7Smrg permissions described in the GCC Runtime Library Exception, version
19181254a7Smrg 3.1, as published by the Free Software Foundation.
20181254a7Smrg 
21181254a7Smrg You should have received a copy of the GNU General Public License and
22181254a7Smrg a copy of the GCC Runtime Library Exception along with this program;
23181254a7Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24181254a7Smrg <http://www.gnu.org/licenses/>.  */
25181254a7Smrg 
26181254a7Smrg #include "libgfortran.h"
27181254a7Smrg #include <assert.h>
28181254a7Smrg 
29181254a7Smrg 
30181254a7Smrg #if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_8)
31181254a7Smrg 
32181254a7Smrg 
33181254a7Smrg extern void minloc0_8_i1 (gfc_array_i8 * const restrict retarray,
34181254a7Smrg 	gfc_array_i1 * const restrict array, GFC_LOGICAL_4);
35181254a7Smrg export_proto(minloc0_8_i1);
36181254a7Smrg 
37181254a7Smrg void
minloc0_8_i1(gfc_array_i8 * const restrict retarray,gfc_array_i1 * const restrict array,GFC_LOGICAL_4 back)38181254a7Smrg minloc0_8_i1 (gfc_array_i8 * const restrict retarray,
39181254a7Smrg 	gfc_array_i1 * const restrict array, GFC_LOGICAL_4 back)
40181254a7Smrg {
41181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
42181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
43181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
44181254a7Smrg   index_type dstride;
45181254a7Smrg   const GFC_INTEGER_1 *base;
46181254a7Smrg   GFC_INTEGER_8 * restrict dest;
47181254a7Smrg   index_type rank;
48181254a7Smrg   index_type n;
49181254a7Smrg 
50181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
51181254a7Smrg   if (rank <= 0)
52181254a7Smrg     runtime_error ("Rank of array needs to be > 0");
53181254a7Smrg 
54181254a7Smrg   if (retarray->base_addr == NULL)
55181254a7Smrg     {
56181254a7Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
57181254a7Smrg       retarray->dtype.rank = 1;
58181254a7Smrg       retarray->offset = 0;
59181254a7Smrg       retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
60181254a7Smrg     }
61181254a7Smrg   else
62181254a7Smrg     {
63181254a7Smrg       if (unlikely (compile_options.bounds_check))
64181254a7Smrg 	bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
65181254a7Smrg 				"MINLOC");
66181254a7Smrg     }
67181254a7Smrg 
68181254a7Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
69181254a7Smrg   dest = retarray->base_addr;
70181254a7Smrg   for (n = 0; n < rank; n++)
71181254a7Smrg     {
72181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
73181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
74181254a7Smrg       count[n] = 0;
75181254a7Smrg       if (extent[n] <= 0)
76181254a7Smrg 	{
77181254a7Smrg 	  /* Set the return value.  */
78181254a7Smrg 	  for (n = 0; n < rank; n++)
79181254a7Smrg 	    dest[n * dstride] = 0;
80181254a7Smrg 	  return;
81181254a7Smrg 	}
82181254a7Smrg     }
83181254a7Smrg 
84181254a7Smrg   base = array->base_addr;
85181254a7Smrg 
86181254a7Smrg   /* Initialize the return value.  */
87181254a7Smrg   for (n = 0; n < rank; n++)
88181254a7Smrg     dest[n * dstride] = 1;
89181254a7Smrg   {
90181254a7Smrg 
91181254a7Smrg     GFC_INTEGER_1 minval;
92181254a7Smrg #if defined(GFC_INTEGER_1_QUIET_NAN)
93181254a7Smrg     int fast = 0;
94181254a7Smrg #endif
95181254a7Smrg 
96181254a7Smrg #if defined(GFC_INTEGER_1_INFINITY)
97181254a7Smrg     minval = GFC_INTEGER_1_INFINITY;
98181254a7Smrg #else
99181254a7Smrg     minval = GFC_INTEGER_1_HUGE;
100181254a7Smrg #endif
101181254a7Smrg   while (base)
102181254a7Smrg     {
103181254a7Smrg 	  /* Implementation start.  */
104181254a7Smrg 
105181254a7Smrg #if defined(GFC_INTEGER_1_QUIET_NAN)
106181254a7Smrg       if (unlikely (!fast))
107181254a7Smrg 	{
108181254a7Smrg 	  do
109181254a7Smrg 	    {
110181254a7Smrg 	      if (*base <= minval)
111181254a7Smrg 		{
112181254a7Smrg 		  fast = 1;
113181254a7Smrg 		  minval = *base;
114181254a7Smrg 		  for (n = 0; n < rank; n++)
115181254a7Smrg 		    dest[n * dstride] = count[n] + 1;
116181254a7Smrg 		  break;
117181254a7Smrg 		}
118181254a7Smrg 	      base += sstride[0];
119181254a7Smrg 	    }
120181254a7Smrg 	  while (++count[0] != extent[0]);
121181254a7Smrg 	  if (likely (fast))
122181254a7Smrg 	    continue;
123181254a7Smrg 	}
124181254a7Smrg       else
125181254a7Smrg #endif
126181254a7Smrg       if (back)
127181254a7Smrg 	do
128181254a7Smrg 	  {
129181254a7Smrg 	    if (unlikely (*base <= minval))
130181254a7Smrg 	      {
131181254a7Smrg 		minval = *base;
132181254a7Smrg 		for (n = 0; n < rank; n++)
133181254a7Smrg 		  dest[n * dstride] = count[n] + 1;
134181254a7Smrg 	      }
135181254a7Smrg 	    base += sstride[0];
136181254a7Smrg 	  }
137181254a7Smrg 	while (++count[0] != extent[0]);
138181254a7Smrg       else
139181254a7Smrg 	do
140181254a7Smrg 	  {
141181254a7Smrg 	    if (unlikely (*base < minval))
142181254a7Smrg 	      {
143181254a7Smrg 		minval = *base;
144181254a7Smrg 		for (n = 0; n < rank; n++)
145181254a7Smrg 		  dest[n * dstride] = count[n] + 1;
146181254a7Smrg 	      }
147181254a7Smrg 	  /* Implementation end.  */
148181254a7Smrg 	  /* Advance to the next element.  */
149181254a7Smrg 	  base += sstride[0];
150181254a7Smrg 	}
151181254a7Smrg       while (++count[0] != extent[0]);
152181254a7Smrg       n = 0;
153181254a7Smrg       do
154181254a7Smrg 	{
155181254a7Smrg 	  /* When we get to the end of a dimension, reset it and increment
156181254a7Smrg 	     the next dimension.  */
157181254a7Smrg 	  count[n] = 0;
158181254a7Smrg 	  /* We could precalculate these products, but this is a less
159181254a7Smrg 	     frequently used path so probably not worth it.  */
160181254a7Smrg 	  base -= sstride[n] * extent[n];
161181254a7Smrg 	  n++;
162181254a7Smrg 	  if (n >= rank)
163181254a7Smrg 	    {
164181254a7Smrg 	      /* Break out of the loop.  */
165181254a7Smrg 	      base = NULL;
166181254a7Smrg 	      break;
167181254a7Smrg 	    }
168181254a7Smrg 	  else
169181254a7Smrg 	    {
170181254a7Smrg 	      count[n]++;
171181254a7Smrg 	      base += sstride[n];
172181254a7Smrg 	    }
173181254a7Smrg 	}
174181254a7Smrg       while (count[n] == extent[n]);
175181254a7Smrg     }
176181254a7Smrg   }
177181254a7Smrg }
178181254a7Smrg 
179181254a7Smrg extern void mminloc0_8_i1 (gfc_array_i8 * const restrict,
180181254a7Smrg 	gfc_array_i1 * const restrict, gfc_array_l1 * const restrict,
181181254a7Smrg 	GFC_LOGICAL_4);
182181254a7Smrg export_proto(mminloc0_8_i1);
183181254a7Smrg 
184181254a7Smrg void
mminloc0_8_i1(gfc_array_i8 * const restrict retarray,gfc_array_i1 * const restrict array,gfc_array_l1 * const restrict mask,GFC_LOGICAL_4 back)185181254a7Smrg mminloc0_8_i1 (gfc_array_i8 * const restrict retarray,
186181254a7Smrg 	gfc_array_i1 * const restrict array,
187181254a7Smrg 	gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back)
188181254a7Smrg {
189181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
190181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
191181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
192181254a7Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
193181254a7Smrg   index_type dstride;
194181254a7Smrg   GFC_INTEGER_8 *dest;
195181254a7Smrg   const GFC_INTEGER_1 *base;
196181254a7Smrg   GFC_LOGICAL_1 *mbase;
197181254a7Smrg   int rank;
198181254a7Smrg   index_type n;
199181254a7Smrg   int mask_kind;
200181254a7Smrg 
201181254a7Smrg 
202181254a7Smrg   if (mask == NULL)
203181254a7Smrg     {
204181254a7Smrg       minloc0_8_i1 (retarray, array, back);
205181254a7Smrg       return;
206181254a7Smrg     }
207181254a7Smrg 
208181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
209181254a7Smrg   if (rank <= 0)
210181254a7Smrg     runtime_error ("Rank of array needs to be > 0");
211181254a7Smrg 
212181254a7Smrg   if (retarray->base_addr == NULL)
213181254a7Smrg     {
214181254a7Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
215181254a7Smrg       retarray->dtype.rank = 1;
216181254a7Smrg       retarray->offset = 0;
217181254a7Smrg       retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
218181254a7Smrg     }
219181254a7Smrg   else
220181254a7Smrg     {
221181254a7Smrg       if (unlikely (compile_options.bounds_check))
222181254a7Smrg 	{
223181254a7Smrg 
224181254a7Smrg 	  bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
225181254a7Smrg 				  "MINLOC");
226181254a7Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
227181254a7Smrg 				  "MASK argument", "MINLOC");
228181254a7Smrg 	}
229181254a7Smrg     }
230181254a7Smrg 
231181254a7Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
232181254a7Smrg 
233181254a7Smrg   mbase = mask->base_addr;
234181254a7Smrg 
235181254a7Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
236181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
237181254a7Smrg       || mask_kind == 16
238181254a7Smrg #endif
239181254a7Smrg       )
240181254a7Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
241181254a7Smrg   else
242181254a7Smrg     runtime_error ("Funny sized logical array");
243181254a7Smrg 
244181254a7Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
245181254a7Smrg   dest = retarray->base_addr;
246181254a7Smrg   for (n = 0; n < rank; n++)
247181254a7Smrg     {
248181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
249181254a7Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
250181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
251181254a7Smrg       count[n] = 0;
252181254a7Smrg       if (extent[n] <= 0)
253181254a7Smrg 	{
254181254a7Smrg 	  /* Set the return value.  */
255181254a7Smrg 	  for (n = 0; n < rank; n++)
256181254a7Smrg 	    dest[n * dstride] = 0;
257181254a7Smrg 	  return;
258181254a7Smrg 	}
259181254a7Smrg     }
260181254a7Smrg 
261181254a7Smrg   base = array->base_addr;
262181254a7Smrg 
263181254a7Smrg   /* Initialize the return value.  */
264181254a7Smrg   for (n = 0; n < rank; n++)
265181254a7Smrg     dest[n * dstride] = 0;
266181254a7Smrg   {
267181254a7Smrg 
268181254a7Smrg   GFC_INTEGER_1 minval;
269181254a7Smrg    int fast = 0;
270181254a7Smrg 
271181254a7Smrg #if defined(GFC_INTEGER_1_INFINITY)
272181254a7Smrg     minval = GFC_INTEGER_1_INFINITY;
273181254a7Smrg #else
274181254a7Smrg     minval = GFC_INTEGER_1_HUGE;
275181254a7Smrg #endif
276181254a7Smrg   while (base)
277181254a7Smrg     {
278181254a7Smrg 	  /* Implementation start.  */
279181254a7Smrg 
280181254a7Smrg       if (unlikely (!fast))
281181254a7Smrg 	{
282181254a7Smrg 	  do
283181254a7Smrg 	    {
284181254a7Smrg 	      if (*mbase)
285181254a7Smrg 		{
286181254a7Smrg #if defined(GFC_INTEGER_1_QUIET_NAN)
287181254a7Smrg 		  if (unlikely (dest[0] == 0))
288181254a7Smrg 		    for (n = 0; n < rank; n++)
289181254a7Smrg 		      dest[n * dstride] = count[n] + 1;
290181254a7Smrg 		  if (*base <= minval)
291181254a7Smrg #endif
292181254a7Smrg 		    {
293181254a7Smrg 		      fast = 1;
294181254a7Smrg 		      minval = *base;
295181254a7Smrg 		      for (n = 0; n < rank; n++)
296181254a7Smrg 			dest[n * dstride] = count[n] + 1;
297181254a7Smrg 		      break;
298181254a7Smrg 		    }
299181254a7Smrg 		}
300181254a7Smrg 	      base += sstride[0];
301181254a7Smrg 	      mbase += mstride[0];
302181254a7Smrg 	    }
303181254a7Smrg 	  while (++count[0] != extent[0]);
304181254a7Smrg 	  if (likely (fast))
305181254a7Smrg 	    continue;
306181254a7Smrg 	}
307181254a7Smrg         else
308181254a7Smrg         if (back)
309181254a7Smrg 	  do
310181254a7Smrg 	    {
311181254a7Smrg 	      if (unlikely (*mbase && (*base <= minval)))
312181254a7Smrg 	        {
313181254a7Smrg 	      	  minval = *base;
314181254a7Smrg 	      	  for (n = 0; n < rank; n++)
315181254a7Smrg 		    dest[n * dstride] = count[n] + 1;
316181254a7Smrg 	    	}
317181254a7Smrg 		base += sstride[0];
318181254a7Smrg 	    }
319181254a7Smrg 	    while (++count[0] != extent[0]);
320181254a7Smrg 	else
321181254a7Smrg 	  do
322181254a7Smrg 	    {
323181254a7Smrg 	      if (unlikely (*mbase && (*base < minval)))
324181254a7Smrg 		{
325181254a7Smrg 		  minval = *base;
326181254a7Smrg 		  for (n = 0; n < rank; n++)
327181254a7Smrg 		    dest[n * dstride] = count[n] + 1;
328181254a7Smrg 		}
329181254a7Smrg 	  /* Implementation end.  */
330181254a7Smrg 	  /* Advance to the next element.  */
331181254a7Smrg 	  base += sstride[0];
332181254a7Smrg 	  mbase += mstride[0];
333181254a7Smrg 	}
334181254a7Smrg       while (++count[0] != extent[0]);
335181254a7Smrg       n = 0;
336181254a7Smrg       do
337181254a7Smrg 	{
338181254a7Smrg 	  /* When we get to the end of a dimension, reset it and increment
339181254a7Smrg 	     the next dimension.  */
340181254a7Smrg 	  count[n] = 0;
341181254a7Smrg 	  /* We could precalculate these products, but this is a less
342181254a7Smrg 	     frequently used path so probably not worth it.  */
343181254a7Smrg 	  base -= sstride[n] * extent[n];
344181254a7Smrg 	  mbase -= mstride[n] * extent[n];
345181254a7Smrg 	  n++;
346181254a7Smrg 	  if (n >= rank)
347181254a7Smrg 	    {
348181254a7Smrg 	      /* Break out of the loop.  */
349181254a7Smrg 	      base = NULL;
350181254a7Smrg 	      break;
351181254a7Smrg 	    }
352181254a7Smrg 	  else
353181254a7Smrg 	    {
354181254a7Smrg 	      count[n]++;
355181254a7Smrg 	      base += sstride[n];
356181254a7Smrg 	      mbase += mstride[n];
357181254a7Smrg 	    }
358181254a7Smrg 	}
359181254a7Smrg       while (count[n] == extent[n]);
360181254a7Smrg     }
361181254a7Smrg   }
362181254a7Smrg }
363181254a7Smrg 
364181254a7Smrg extern void sminloc0_8_i1 (gfc_array_i8 * const restrict,
365181254a7Smrg 	gfc_array_i1 * const restrict, GFC_LOGICAL_4 *, GFC_LOGICAL_4);
366181254a7Smrg export_proto(sminloc0_8_i1);
367181254a7Smrg 
368181254a7Smrg void
sminloc0_8_i1(gfc_array_i8 * const restrict retarray,gfc_array_i1 * const restrict array,GFC_LOGICAL_4 * mask,GFC_LOGICAL_4 back)369181254a7Smrg sminloc0_8_i1 (gfc_array_i8 * const restrict retarray,
370181254a7Smrg 	gfc_array_i1 * const restrict array,
371181254a7Smrg 	GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
372181254a7Smrg {
373181254a7Smrg   index_type rank;
374181254a7Smrg   index_type dstride;
375181254a7Smrg   index_type n;
376181254a7Smrg   GFC_INTEGER_8 *dest;
377181254a7Smrg 
378181254a7Smrg   if (mask == NULL || *mask)
379181254a7Smrg     {
380181254a7Smrg       minloc0_8_i1 (retarray, array, back);
381181254a7Smrg       return;
382181254a7Smrg     }
383181254a7Smrg 
384181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
385181254a7Smrg 
386181254a7Smrg   if (rank <= 0)
387181254a7Smrg     runtime_error ("Rank of array needs to be > 0");
388181254a7Smrg 
389181254a7Smrg   if (retarray->base_addr == NULL)
390181254a7Smrg     {
391181254a7Smrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
392181254a7Smrg       retarray->dtype.rank = 1;
393181254a7Smrg       retarray->offset = 0;
394181254a7Smrg       retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
395181254a7Smrg     }
396181254a7Smrg   else if (unlikely (compile_options.bounds_check))
397181254a7Smrg     {
398181254a7Smrg        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
399181254a7Smrg 			       "MINLOC");
400181254a7Smrg     }
401181254a7Smrg 
402181254a7Smrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
403181254a7Smrg   dest = retarray->base_addr;
404181254a7Smrg   for (n = 0; n<rank; n++)
405181254a7Smrg     dest[n * dstride] = 0 ;
406181254a7Smrg }
407181254a7Smrg #endif
408