xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/minval0_s4.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1181254a7Smrg /* Implementation of the MAXLOC intrinsic
2*b1e83836Smrg    Copyright (C) 2017-2022 Free Software Foundation, Inc.
3181254a7Smrg    Contributed by Thomas Koenig
4181254a7Smrg 
5181254a7Smrg This file is part of the GNU Fortran 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 <stdlib.h>
28181254a7Smrg #include <string.h>
29181254a7Smrg #include <assert.h>
30181254a7Smrg #include <limits.h>
31181254a7Smrg 
32181254a7Smrg 
33181254a7Smrg #if defined (HAVE_GFC_UINTEGER_4) && defined (HAVE_GFC_UINTEGER_4)
34181254a7Smrg 
35181254a7Smrg static inline int
compare_fcn(const GFC_UINTEGER_4 * a,const GFC_UINTEGER_4 * b,gfc_charlen_type n)36181254a7Smrg compare_fcn (const GFC_UINTEGER_4 *a, const GFC_UINTEGER_4 *b, gfc_charlen_type n)
37181254a7Smrg {
38181254a7Smrg   if (sizeof (GFC_UINTEGER_4) == 1)
39181254a7Smrg     return memcmp (a, b, n);
40181254a7Smrg   else
41181254a7Smrg     return memcmp_char4 (a, b, n);
42181254a7Smrg 
43181254a7Smrg }
44181254a7Smrg 
45181254a7Smrg #define INITVAL 255
46181254a7Smrg 
47181254a7Smrg extern void minval0_s4 (GFC_UINTEGER_4 * restrict,
48181254a7Smrg         gfc_charlen_type,
49181254a7Smrg 	gfc_array_s4 * const restrict array, gfc_charlen_type);
50181254a7Smrg export_proto(minval0_s4);
51181254a7Smrg 
52181254a7Smrg void
minval0_s4(GFC_UINTEGER_4 * restrict ret,gfc_charlen_type xlen,gfc_array_s4 * const restrict array,gfc_charlen_type len)53181254a7Smrg minval0_s4 (GFC_UINTEGER_4 * restrict ret,
54181254a7Smrg         gfc_charlen_type xlen,
55181254a7Smrg 	gfc_array_s4 * const restrict array, gfc_charlen_type len)
56181254a7Smrg {
57181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
58181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
59181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
60181254a7Smrg   const GFC_UINTEGER_4 *base;
61181254a7Smrg   index_type rank;
62181254a7Smrg   index_type n;
63181254a7Smrg 
64181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
65181254a7Smrg   if (rank <= 0)
66181254a7Smrg     runtime_error ("Rank of array needs to be > 0");
67181254a7Smrg 
68181254a7Smrg   assert (xlen == len);
69181254a7Smrg 
70181254a7Smrg   /* Initialize return value.  */
71181254a7Smrg   memset (ret, INITVAL, sizeof(*ret) * len);
72181254a7Smrg 
73181254a7Smrg   for (n = 0; n < rank; n++)
74181254a7Smrg     {
75181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
76181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
77181254a7Smrg       count[n] = 0;
78181254a7Smrg       if (extent[n] <= 0)
79181254a7Smrg         return;
80181254a7Smrg     }
81181254a7Smrg 
82181254a7Smrg   base = array->base_addr;
83181254a7Smrg 
84181254a7Smrg   {
85181254a7Smrg 
86181254a7Smrg   const GFC_UINTEGER_4 *retval;
87181254a7Smrg    retval = ret;
88181254a7Smrg 
89181254a7Smrg   while (base)
90181254a7Smrg     {
91181254a7Smrg       do
92181254a7Smrg 	{
93181254a7Smrg 	  /* Implementation start.  */
94181254a7Smrg 
95181254a7Smrg   if (compare_fcn (base, retval, len) < 0)
96181254a7Smrg     {
97181254a7Smrg       retval = base;
98181254a7Smrg     }
99181254a7Smrg 	  /* Implementation end.  */
100181254a7Smrg 	  /* Advance to the next element.  */
101181254a7Smrg 	  base += sstride[0];
102181254a7Smrg 	}
103181254a7Smrg       while (++count[0] != extent[0]);
104181254a7Smrg       n = 0;
105181254a7Smrg       do
106181254a7Smrg 	{
107181254a7Smrg 	  /* When we get to the end of a dimension, reset it and increment
108181254a7Smrg 	     the next dimension.  */
109181254a7Smrg 	  count[n] = 0;
110181254a7Smrg 	  /* We could precalculate these products, but this is a less
111181254a7Smrg 	     frequently used path so probably not worth it.  */
112181254a7Smrg 	  base -= sstride[n] * extent[n];
113181254a7Smrg 	  n++;
114181254a7Smrg 	  if (n >= rank)
115181254a7Smrg 	    {
116181254a7Smrg 	      /* Break out of the loop.  */
117181254a7Smrg 	      base = NULL;
118181254a7Smrg 	      break;
119181254a7Smrg 	    }
120181254a7Smrg 	  else
121181254a7Smrg 	    {
122181254a7Smrg 	      count[n]++;
123181254a7Smrg 	      base += sstride[n];
124181254a7Smrg 	    }
125181254a7Smrg 	}
126181254a7Smrg       while (count[n] == extent[n]);
127181254a7Smrg     }
128181254a7Smrg    memcpy (ret, retval, len * sizeof (*ret));
129181254a7Smrg   }
130181254a7Smrg }
131181254a7Smrg 
132181254a7Smrg 
133181254a7Smrg extern void mminval0_s4 (GFC_UINTEGER_4 * restrict,
134181254a7Smrg        gfc_charlen_type, gfc_array_s4 * const restrict array,
135181254a7Smrg        gfc_array_l1 * const restrict mask, gfc_charlen_type len);
136181254a7Smrg export_proto(mminval0_s4);
137181254a7Smrg 
138181254a7Smrg void
mminval0_s4(GFC_UINTEGER_4 * const restrict ret,gfc_charlen_type xlen,gfc_array_s4 * const restrict array,gfc_array_l1 * const restrict mask,gfc_charlen_type len)139181254a7Smrg mminval0_s4 (GFC_UINTEGER_4 * const restrict ret,
140181254a7Smrg 	gfc_charlen_type xlen, gfc_array_s4 * const restrict array,
141181254a7Smrg 	gfc_array_l1 * const restrict mask, gfc_charlen_type len)
142181254a7Smrg {
143181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
144181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
145181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
146181254a7Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
147181254a7Smrg   const GFC_UINTEGER_4 *base;
148181254a7Smrg   GFC_LOGICAL_1 *mbase;
149181254a7Smrg   int rank;
150181254a7Smrg   index_type n;
151181254a7Smrg   int mask_kind;
152181254a7Smrg 
153181254a7Smrg   if (mask == NULL)
154181254a7Smrg     {
155181254a7Smrg       minval0_s4 (ret, xlen, array, len);
156181254a7Smrg       return;
157181254a7Smrg     }
158181254a7Smrg 
159181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array);
160181254a7Smrg   if (rank <= 0)
161181254a7Smrg     runtime_error ("Rank of array needs to be > 0");
162181254a7Smrg 
163181254a7Smrg   assert (xlen == len);
164181254a7Smrg 
165181254a7Smrg /* Initialize return value.  */
166181254a7Smrg   memset (ret, INITVAL, sizeof(*ret) * len);
167181254a7Smrg 
168181254a7Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
169181254a7Smrg 
170181254a7Smrg   mbase = mask->base_addr;
171181254a7Smrg 
172181254a7Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
173181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
174181254a7Smrg       || mask_kind == 16
175181254a7Smrg #endif
176181254a7Smrg       )
177181254a7Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
178181254a7Smrg   else
179181254a7Smrg     runtime_error ("Funny sized logical array");
180181254a7Smrg 
181181254a7Smrg   for (n = 0; n < rank; n++)
182181254a7Smrg     {
183181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
184181254a7Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
185181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
186181254a7Smrg       count[n] = 0;
187181254a7Smrg       if (extent[n] <= 0)
188181254a7Smrg 	return;
189181254a7Smrg     }
190181254a7Smrg 
191181254a7Smrg   base = array->base_addr;
192181254a7Smrg   {
193181254a7Smrg 
194181254a7Smrg   const GFC_UINTEGER_4 *retval;
195181254a7Smrg 
196181254a7Smrg   retval = ret;
197181254a7Smrg 
198181254a7Smrg   while (base)
199181254a7Smrg     {
200181254a7Smrg       do
201181254a7Smrg 	{
202181254a7Smrg 	  /* Implementation start.  */
203181254a7Smrg 
204181254a7Smrg   if (*mbase && compare_fcn (base, retval, len) < 0)
205181254a7Smrg     {
206181254a7Smrg       retval = base;
207181254a7Smrg     }
208181254a7Smrg 	  /* Implementation end.  */
209181254a7Smrg 	  /* Advance to the next element.  */
210181254a7Smrg 	  base += sstride[0];
211181254a7Smrg 	  mbase += mstride[0];
212181254a7Smrg 	}
213181254a7Smrg       while (++count[0] != extent[0]);
214181254a7Smrg       n = 0;
215181254a7Smrg       do
216181254a7Smrg 	{
217181254a7Smrg 	  /* When we get to the end of a dimension, reset it and increment
218181254a7Smrg 	     the next dimension.  */
219181254a7Smrg 	  count[n] = 0;
220181254a7Smrg 	  /* We could precalculate these products, but this is a less
221181254a7Smrg 	     frequently used path so probably not worth it.  */
222181254a7Smrg 	  base -= sstride[n] * extent[n];
223181254a7Smrg 	  mbase -= mstride[n] * extent[n];
224181254a7Smrg 	  n++;
225181254a7Smrg 	  if (n >= rank)
226181254a7Smrg 	    {
227181254a7Smrg 	      /* Break out of the loop.  */
228181254a7Smrg 	      base = NULL;
229181254a7Smrg 	      break;
230181254a7Smrg 	    }
231181254a7Smrg 	  else
232181254a7Smrg 	    {
233181254a7Smrg 	      count[n]++;
234181254a7Smrg 	      base += sstride[n];
235181254a7Smrg 	      mbase += mstride[n];
236181254a7Smrg 	    }
237181254a7Smrg 	}
238181254a7Smrg       while (count[n] == extent[n]);
239181254a7Smrg     }
240181254a7Smrg     memcpy (ret, retval, len * sizeof (*ret));
241181254a7Smrg   }
242181254a7Smrg }
243181254a7Smrg 
244181254a7Smrg 
245181254a7Smrg extern void sminval0_s4 (GFC_UINTEGER_4 * restrict,
246181254a7Smrg         gfc_charlen_type,
247181254a7Smrg 	gfc_array_s4 * const restrict array, GFC_LOGICAL_4 *, gfc_charlen_type);
248181254a7Smrg export_proto(sminval0_s4);
249181254a7Smrg 
250181254a7Smrg void
sminval0_s4(GFC_UINTEGER_4 * restrict ret,gfc_charlen_type xlen,gfc_array_s4 * const restrict array,GFC_LOGICAL_4 * mask,gfc_charlen_type len)251181254a7Smrg sminval0_s4 (GFC_UINTEGER_4 * restrict ret,
252181254a7Smrg         gfc_charlen_type xlen, gfc_array_s4 * const restrict array,
253181254a7Smrg 	GFC_LOGICAL_4 *mask, gfc_charlen_type len)
254181254a7Smrg 
255181254a7Smrg {
256181254a7Smrg   if (mask == NULL || *mask)
257181254a7Smrg     {
258181254a7Smrg       minval0_s4 (ret, xlen, array, len);
259181254a7Smrg       return;
260181254a7Smrg     }
261181254a7Smrg   memset (ret, INITVAL, sizeof (*ret) * len);
262181254a7Smrg }
263181254a7Smrg 
264181254a7Smrg #endif
265