xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/generated/minval0_s1.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg /* Implementation of the MAXLOC intrinsic
2*4c3eb207Smrg    Copyright (C) 2017-2020 Free Software Foundation, Inc.
3627f7eb2Smrg    Contributed by Thomas Koenig
4627f7eb2Smrg 
5627f7eb2Smrg This file is part of the GNU Fortran 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 <stdlib.h>
28627f7eb2Smrg #include <string.h>
29627f7eb2Smrg #include <assert.h>
30627f7eb2Smrg #include <limits.h>
31627f7eb2Smrg 
32627f7eb2Smrg 
33627f7eb2Smrg #if defined (HAVE_GFC_UINTEGER_1) && defined (HAVE_GFC_UINTEGER_1)
34627f7eb2Smrg 
35627f7eb2Smrg static inline int
compare_fcn(const GFC_UINTEGER_1 * a,const GFC_UINTEGER_1 * b,gfc_charlen_type n)36627f7eb2Smrg compare_fcn (const GFC_UINTEGER_1 *a, const GFC_UINTEGER_1 *b, gfc_charlen_type n)
37627f7eb2Smrg {
38627f7eb2Smrg   if (sizeof (GFC_UINTEGER_1) == 1)
39627f7eb2Smrg     return memcmp (a, b, n);
40627f7eb2Smrg   else
41627f7eb2Smrg     return memcmp_char4 (a, b, n);
42627f7eb2Smrg 
43627f7eb2Smrg }
44627f7eb2Smrg 
45627f7eb2Smrg #define INITVAL 255
46627f7eb2Smrg 
47627f7eb2Smrg extern void minval0_s1 (GFC_UINTEGER_1 * restrict,
48627f7eb2Smrg         gfc_charlen_type,
49627f7eb2Smrg 	gfc_array_s1 * const restrict array, gfc_charlen_type);
50627f7eb2Smrg export_proto(minval0_s1);
51627f7eb2Smrg 
52627f7eb2Smrg void
minval0_s1(GFC_UINTEGER_1 * restrict ret,gfc_charlen_type xlen,gfc_array_s1 * const restrict array,gfc_charlen_type len)53627f7eb2Smrg minval0_s1 (GFC_UINTEGER_1 * restrict ret,
54627f7eb2Smrg         gfc_charlen_type xlen,
55627f7eb2Smrg 	gfc_array_s1 * const restrict array, gfc_charlen_type len)
56627f7eb2Smrg {
57627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
58627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
59627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
60627f7eb2Smrg   const GFC_UINTEGER_1 *base;
61627f7eb2Smrg   index_type rank;
62627f7eb2Smrg   index_type n;
63627f7eb2Smrg 
64627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
65627f7eb2Smrg   if (rank <= 0)
66627f7eb2Smrg     runtime_error ("Rank of array needs to be > 0");
67627f7eb2Smrg 
68627f7eb2Smrg   assert (xlen == len);
69627f7eb2Smrg 
70627f7eb2Smrg   /* Initialize return value.  */
71627f7eb2Smrg   memset (ret, INITVAL, sizeof(*ret) * len);
72627f7eb2Smrg 
73627f7eb2Smrg   for (n = 0; n < rank; n++)
74627f7eb2Smrg     {
75627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
76627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
77627f7eb2Smrg       count[n] = 0;
78627f7eb2Smrg       if (extent[n] <= 0)
79627f7eb2Smrg         return;
80627f7eb2Smrg     }
81627f7eb2Smrg 
82627f7eb2Smrg   base = array->base_addr;
83627f7eb2Smrg 
84627f7eb2Smrg   {
85627f7eb2Smrg 
86627f7eb2Smrg   const GFC_UINTEGER_1 *retval;
87627f7eb2Smrg    retval = ret;
88627f7eb2Smrg 
89627f7eb2Smrg   while (base)
90627f7eb2Smrg     {
91627f7eb2Smrg       do
92627f7eb2Smrg 	{
93627f7eb2Smrg 	  /* Implementation start.  */
94627f7eb2Smrg 
95627f7eb2Smrg   if (compare_fcn (base, retval, len) < 0)
96627f7eb2Smrg     {
97627f7eb2Smrg       retval = base;
98627f7eb2Smrg     }
99627f7eb2Smrg 	  /* Implementation end.  */
100627f7eb2Smrg 	  /* Advance to the next element.  */
101627f7eb2Smrg 	  base += sstride[0];
102627f7eb2Smrg 	}
103627f7eb2Smrg       while (++count[0] != extent[0]);
104627f7eb2Smrg       n = 0;
105627f7eb2Smrg       do
106627f7eb2Smrg 	{
107627f7eb2Smrg 	  /* When we get to the end of a dimension, reset it and increment
108627f7eb2Smrg 	     the next dimension.  */
109627f7eb2Smrg 	  count[n] = 0;
110627f7eb2Smrg 	  /* We could precalculate these products, but this is a less
111627f7eb2Smrg 	     frequently used path so probably not worth it.  */
112627f7eb2Smrg 	  base -= sstride[n] * extent[n];
113627f7eb2Smrg 	  n++;
114627f7eb2Smrg 	  if (n >= rank)
115627f7eb2Smrg 	    {
116627f7eb2Smrg 	      /* Break out of the loop.  */
117627f7eb2Smrg 	      base = NULL;
118627f7eb2Smrg 	      break;
119627f7eb2Smrg 	    }
120627f7eb2Smrg 	  else
121627f7eb2Smrg 	    {
122627f7eb2Smrg 	      count[n]++;
123627f7eb2Smrg 	      base += sstride[n];
124627f7eb2Smrg 	    }
125627f7eb2Smrg 	}
126627f7eb2Smrg       while (count[n] == extent[n]);
127627f7eb2Smrg     }
128627f7eb2Smrg    memcpy (ret, retval, len * sizeof (*ret));
129627f7eb2Smrg   }
130627f7eb2Smrg }
131627f7eb2Smrg 
132627f7eb2Smrg 
133627f7eb2Smrg extern void mminval0_s1 (GFC_UINTEGER_1 * restrict,
134627f7eb2Smrg        gfc_charlen_type, gfc_array_s1 * const restrict array,
135627f7eb2Smrg        gfc_array_l1 * const restrict mask, gfc_charlen_type len);
136627f7eb2Smrg export_proto(mminval0_s1);
137627f7eb2Smrg 
138627f7eb2Smrg void
mminval0_s1(GFC_UINTEGER_1 * const restrict ret,gfc_charlen_type xlen,gfc_array_s1 * const restrict array,gfc_array_l1 * const restrict mask,gfc_charlen_type len)139627f7eb2Smrg mminval0_s1 (GFC_UINTEGER_1 * const restrict ret,
140627f7eb2Smrg 	gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
141627f7eb2Smrg 	gfc_array_l1 * const restrict mask, gfc_charlen_type len)
142627f7eb2Smrg {
143627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
144627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
145627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
146627f7eb2Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
147627f7eb2Smrg   const GFC_UINTEGER_1 *base;
148627f7eb2Smrg   GFC_LOGICAL_1 *mbase;
149627f7eb2Smrg   int rank;
150627f7eb2Smrg   index_type n;
151627f7eb2Smrg   int mask_kind;
152627f7eb2Smrg 
153627f7eb2Smrg   if (mask == NULL)
154627f7eb2Smrg     {
155627f7eb2Smrg       minval0_s1 (ret, xlen, array, len);
156627f7eb2Smrg       return;
157627f7eb2Smrg     }
158627f7eb2Smrg 
159627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array);
160627f7eb2Smrg   if (rank <= 0)
161627f7eb2Smrg     runtime_error ("Rank of array needs to be > 0");
162627f7eb2Smrg 
163627f7eb2Smrg   assert (xlen == len);
164627f7eb2Smrg 
165627f7eb2Smrg /* Initialize return value.  */
166627f7eb2Smrg   memset (ret, INITVAL, sizeof(*ret) * len);
167627f7eb2Smrg 
168627f7eb2Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
169627f7eb2Smrg 
170627f7eb2Smrg   mbase = mask->base_addr;
171627f7eb2Smrg 
172627f7eb2Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
173627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
174627f7eb2Smrg       || mask_kind == 16
175627f7eb2Smrg #endif
176627f7eb2Smrg       )
177627f7eb2Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
178627f7eb2Smrg   else
179627f7eb2Smrg     runtime_error ("Funny sized logical array");
180627f7eb2Smrg 
181627f7eb2Smrg   for (n = 0; n < rank; n++)
182627f7eb2Smrg     {
183627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
184627f7eb2Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
185627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
186627f7eb2Smrg       count[n] = 0;
187627f7eb2Smrg       if (extent[n] <= 0)
188627f7eb2Smrg 	return;
189627f7eb2Smrg     }
190627f7eb2Smrg 
191627f7eb2Smrg   base = array->base_addr;
192627f7eb2Smrg   {
193627f7eb2Smrg 
194627f7eb2Smrg   const GFC_UINTEGER_1 *retval;
195627f7eb2Smrg 
196627f7eb2Smrg   retval = ret;
197627f7eb2Smrg 
198627f7eb2Smrg   while (base)
199627f7eb2Smrg     {
200627f7eb2Smrg       do
201627f7eb2Smrg 	{
202627f7eb2Smrg 	  /* Implementation start.  */
203627f7eb2Smrg 
204627f7eb2Smrg   if (*mbase && compare_fcn (base, retval, len) < 0)
205627f7eb2Smrg     {
206627f7eb2Smrg       retval = base;
207627f7eb2Smrg     }
208627f7eb2Smrg 	  /* Implementation end.  */
209627f7eb2Smrg 	  /* Advance to the next element.  */
210627f7eb2Smrg 	  base += sstride[0];
211627f7eb2Smrg 	  mbase += mstride[0];
212627f7eb2Smrg 	}
213627f7eb2Smrg       while (++count[0] != extent[0]);
214627f7eb2Smrg       n = 0;
215627f7eb2Smrg       do
216627f7eb2Smrg 	{
217627f7eb2Smrg 	  /* When we get to the end of a dimension, reset it and increment
218627f7eb2Smrg 	     the next dimension.  */
219627f7eb2Smrg 	  count[n] = 0;
220627f7eb2Smrg 	  /* We could precalculate these products, but this is a less
221627f7eb2Smrg 	     frequently used path so probably not worth it.  */
222627f7eb2Smrg 	  base -= sstride[n] * extent[n];
223627f7eb2Smrg 	  mbase -= mstride[n] * extent[n];
224627f7eb2Smrg 	  n++;
225627f7eb2Smrg 	  if (n >= rank)
226627f7eb2Smrg 	    {
227627f7eb2Smrg 	      /* Break out of the loop.  */
228627f7eb2Smrg 	      base = NULL;
229627f7eb2Smrg 	      break;
230627f7eb2Smrg 	    }
231627f7eb2Smrg 	  else
232627f7eb2Smrg 	    {
233627f7eb2Smrg 	      count[n]++;
234627f7eb2Smrg 	      base += sstride[n];
235627f7eb2Smrg 	      mbase += mstride[n];
236627f7eb2Smrg 	    }
237627f7eb2Smrg 	}
238627f7eb2Smrg       while (count[n] == extent[n]);
239627f7eb2Smrg     }
240627f7eb2Smrg     memcpy (ret, retval, len * sizeof (*ret));
241627f7eb2Smrg   }
242627f7eb2Smrg }
243627f7eb2Smrg 
244627f7eb2Smrg 
245627f7eb2Smrg extern void sminval0_s1 (GFC_UINTEGER_1 * restrict,
246627f7eb2Smrg         gfc_charlen_type,
247627f7eb2Smrg 	gfc_array_s1 * const restrict array, GFC_LOGICAL_4 *, gfc_charlen_type);
248627f7eb2Smrg export_proto(sminval0_s1);
249627f7eb2Smrg 
250627f7eb2Smrg void
sminval0_s1(GFC_UINTEGER_1 * restrict ret,gfc_charlen_type xlen,gfc_array_s1 * const restrict array,GFC_LOGICAL_4 * mask,gfc_charlen_type len)251627f7eb2Smrg sminval0_s1 (GFC_UINTEGER_1 * restrict ret,
252627f7eb2Smrg         gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
253627f7eb2Smrg 	GFC_LOGICAL_4 *mask, gfc_charlen_type len)
254627f7eb2Smrg 
255627f7eb2Smrg {
256627f7eb2Smrg   if (mask == NULL || *mask)
257627f7eb2Smrg     {
258627f7eb2Smrg       minval0_s1 (ret, xlen, array, len);
259627f7eb2Smrg       return;
260627f7eb2Smrg     }
261627f7eb2Smrg   memset (ret, INITVAL, sizeof (*ret) * len);
262627f7eb2Smrg }
263627f7eb2Smrg 
264627f7eb2Smrg #endif
265