xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/generated/maxval1_s1.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg /* Implementation of the MAXVAL 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 
28627f7eb2Smrg 
29627f7eb2Smrg #if defined (HAVE_GFC_UINTEGER_1) && defined (HAVE_GFC_UINTEGER_1)
30627f7eb2Smrg 
31627f7eb2Smrg #include <string.h>
32627f7eb2Smrg #include <assert.h>
33627f7eb2Smrg 
34627f7eb2Smrg static inline int
compare_fcn(const GFC_UINTEGER_1 * a,const GFC_UINTEGER_1 * b,gfc_charlen_type n)35627f7eb2Smrg compare_fcn (const GFC_UINTEGER_1 *a, const GFC_UINTEGER_1 *b, gfc_charlen_type n)
36627f7eb2Smrg {
37627f7eb2Smrg   if (sizeof (GFC_UINTEGER_1) == 1)
38627f7eb2Smrg     return memcmp (a, b, n);
39627f7eb2Smrg   else
40627f7eb2Smrg     return memcmp_char4 (a, b, n);
41627f7eb2Smrg }
42627f7eb2Smrg 
43627f7eb2Smrg extern void maxval1_s1 (gfc_array_s1 * const restrict,
44627f7eb2Smrg         gfc_charlen_type, gfc_array_s1 * const restrict,
45627f7eb2Smrg 	const index_type * const restrict, gfc_charlen_type);
46627f7eb2Smrg export_proto(maxval1_s1);
47627f7eb2Smrg 
48627f7eb2Smrg void
maxval1_s1(gfc_array_s1 * const restrict retarray,gfc_charlen_type xlen,gfc_array_s1 * const restrict array,const index_type * const restrict pdim,gfc_charlen_type string_len)49627f7eb2Smrg maxval1_s1 (gfc_array_s1 * const restrict retarray,
50627f7eb2Smrg 	gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
51627f7eb2Smrg 	const index_type * const restrict pdim, gfc_charlen_type string_len)
52627f7eb2Smrg {
53627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
54627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
55627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
56627f7eb2Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
57627f7eb2Smrg   const GFC_UINTEGER_1 * restrict base;
58627f7eb2Smrg   GFC_UINTEGER_1 * restrict dest;
59627f7eb2Smrg   index_type rank;
60627f7eb2Smrg   index_type n;
61627f7eb2Smrg   index_type len;
62627f7eb2Smrg   index_type delta;
63627f7eb2Smrg   index_type dim;
64627f7eb2Smrg   int continue_loop;
65627f7eb2Smrg 
66627f7eb2Smrg   assert (xlen == string_len);
67627f7eb2Smrg   /* Make dim zero based to avoid confusion.  */
68627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
69627f7eb2Smrg   dim = (*pdim) - 1;
70627f7eb2Smrg 
71627f7eb2Smrg   if (unlikely (dim < 0 || dim > rank))
72627f7eb2Smrg     {
73627f7eb2Smrg       runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
74627f7eb2Smrg  		     "is %ld, should be between 1 and %ld",
75627f7eb2Smrg 		     (long int) dim + 1, (long int) rank + 1);
76627f7eb2Smrg     }
77627f7eb2Smrg 
78627f7eb2Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
79627f7eb2Smrg   if (len < 0)
80627f7eb2Smrg     len = 0;
81627f7eb2Smrg 
82627f7eb2Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
83627f7eb2Smrg 
84627f7eb2Smrg   for (n = 0; n < dim; n++)
85627f7eb2Smrg     {
86627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
87627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
88627f7eb2Smrg 
89627f7eb2Smrg       if (extent[n] < 0)
90627f7eb2Smrg 	extent[n] = 0;
91627f7eb2Smrg     }
92627f7eb2Smrg   for (n = dim; n < rank; n++)
93627f7eb2Smrg     {
94627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
95627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
96627f7eb2Smrg 
97627f7eb2Smrg       if (extent[n] < 0)
98627f7eb2Smrg 	extent[n] = 0;
99627f7eb2Smrg     }
100627f7eb2Smrg 
101627f7eb2Smrg   if (retarray->base_addr == NULL)
102627f7eb2Smrg     {
103627f7eb2Smrg       size_t alloc_size, str;
104627f7eb2Smrg 
105627f7eb2Smrg       for (n = 0; n < rank; n++)
106627f7eb2Smrg 	{
107627f7eb2Smrg 	  if (n == 0)
108627f7eb2Smrg 	    str = 1;
109627f7eb2Smrg 	  else
110627f7eb2Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
111627f7eb2Smrg 
112627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
113627f7eb2Smrg 
114627f7eb2Smrg 	}
115627f7eb2Smrg 
116627f7eb2Smrg       retarray->offset = 0;
117627f7eb2Smrg       retarray->dtype.rank = rank;
118627f7eb2Smrg 
119627f7eb2Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
120627f7eb2Smrg       		 * string_len;
121627f7eb2Smrg 
122627f7eb2Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_UINTEGER_1));
123627f7eb2Smrg       if (alloc_size == 0)
124627f7eb2Smrg 	{
125627f7eb2Smrg 	  /* Make sure we have a zero-sized array.  */
126627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
127627f7eb2Smrg 	  return;
128627f7eb2Smrg 
129627f7eb2Smrg 	}
130627f7eb2Smrg     }
131627f7eb2Smrg   else
132627f7eb2Smrg     {
133627f7eb2Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
134627f7eb2Smrg 	runtime_error ("rank of return array incorrect in"
135627f7eb2Smrg 		       " MAXVAL intrinsic: is %ld, should be %ld",
136627f7eb2Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
137627f7eb2Smrg 		       (long int) rank);
138627f7eb2Smrg 
139627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
140627f7eb2Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
141627f7eb2Smrg 				 "return value", "MAXVAL");
142627f7eb2Smrg     }
143627f7eb2Smrg 
144627f7eb2Smrg   for (n = 0; n < rank; n++)
145627f7eb2Smrg     {
146627f7eb2Smrg       count[n] = 0;
147627f7eb2Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
148627f7eb2Smrg       if (extent[n] <= 0)
149627f7eb2Smrg 	return;
150627f7eb2Smrg     }
151627f7eb2Smrg 
152627f7eb2Smrg   base = array->base_addr;
153627f7eb2Smrg   dest = retarray->base_addr;
154627f7eb2Smrg 
155627f7eb2Smrg   continue_loop = 1;
156627f7eb2Smrg   while (continue_loop)
157627f7eb2Smrg     {
158627f7eb2Smrg       const GFC_UINTEGER_1 * restrict src;
159627f7eb2Smrg       src = base;
160627f7eb2Smrg       {
161627f7eb2Smrg 
162627f7eb2Smrg 	const GFC_UINTEGER_1 *retval;
163627f7eb2Smrg 	retval = base;
164627f7eb2Smrg 	if (len <= 0)
165627f7eb2Smrg 	  memset (dest, 0, sizeof (*dest) * string_len);
166627f7eb2Smrg 	else
167627f7eb2Smrg 	  {
168627f7eb2Smrg 	    for (n = 0; n < len; n++, src += delta)
169627f7eb2Smrg 	      {
170627f7eb2Smrg 
171627f7eb2Smrg 		if (compare_fcn (src, retval, string_len) > 0)
172627f7eb2Smrg 		  {
173627f7eb2Smrg 		    retval = src;
174627f7eb2Smrg 		  }
175627f7eb2Smrg 	      }
176627f7eb2Smrg 
177627f7eb2Smrg 	    memcpy (dest, retval, sizeof (*dest) * string_len);
178627f7eb2Smrg 	  }
179627f7eb2Smrg       }
180627f7eb2Smrg       /* Advance to the next element.  */
181627f7eb2Smrg       count[0]++;
182627f7eb2Smrg       base += sstride[0];
183627f7eb2Smrg       dest += dstride[0];
184627f7eb2Smrg       n = 0;
185627f7eb2Smrg       while (count[n] == extent[n])
186627f7eb2Smrg 	{
187627f7eb2Smrg 	  /* When we get to the end of a dimension, reset it and increment
188627f7eb2Smrg 	     the next dimension.  */
189627f7eb2Smrg 	  count[n] = 0;
190627f7eb2Smrg 	  /* We could precalculate these products, but this is a less
191627f7eb2Smrg 	     frequently used path so probably not worth it.  */
192627f7eb2Smrg 	  base -= sstride[n] * extent[n];
193627f7eb2Smrg 	  dest -= dstride[n] * extent[n];
194627f7eb2Smrg 	  n++;
195627f7eb2Smrg 	  if (n >= rank)
196627f7eb2Smrg 	    {
197627f7eb2Smrg 	      /* Break out of the loop.  */
198627f7eb2Smrg 	      continue_loop = 0;
199627f7eb2Smrg 	      break;
200627f7eb2Smrg 	    }
201627f7eb2Smrg 	  else
202627f7eb2Smrg 	    {
203627f7eb2Smrg 	      count[n]++;
204627f7eb2Smrg 	      base += sstride[n];
205627f7eb2Smrg 	      dest += dstride[n];
206627f7eb2Smrg 	    }
207627f7eb2Smrg 	}
208627f7eb2Smrg     }
209627f7eb2Smrg }
210627f7eb2Smrg 
211627f7eb2Smrg 
212627f7eb2Smrg extern void mmaxval1_s1 (gfc_array_s1 * const restrict,
213627f7eb2Smrg         gfc_charlen_type, gfc_array_s1 * const restrict,
214627f7eb2Smrg 	const index_type * const restrict,
215627f7eb2Smrg 	gfc_array_l1 * const restrict, gfc_charlen_type);
216627f7eb2Smrg export_proto(mmaxval1_s1);
217627f7eb2Smrg 
218627f7eb2Smrg void
mmaxval1_s1(gfc_array_s1 * const restrict retarray,gfc_charlen_type xlen,gfc_array_s1 * const restrict array,const index_type * const restrict pdim,gfc_array_l1 * const restrict mask,gfc_charlen_type string_len)219627f7eb2Smrg mmaxval1_s1 (gfc_array_s1 * const restrict retarray,
220627f7eb2Smrg 	gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
221627f7eb2Smrg 	const index_type * const restrict pdim,
222627f7eb2Smrg 	gfc_array_l1 * const restrict mask,
223627f7eb2Smrg 	gfc_charlen_type string_len)
224627f7eb2Smrg 
225627f7eb2Smrg {
226627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
227627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
228627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
229627f7eb2Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
230627f7eb2Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
231627f7eb2Smrg   GFC_UINTEGER_1 * restrict dest;
232627f7eb2Smrg   const GFC_UINTEGER_1 * restrict base;
233627f7eb2Smrg   const GFC_LOGICAL_1 * restrict mbase;
234627f7eb2Smrg   index_type rank;
235627f7eb2Smrg   index_type dim;
236627f7eb2Smrg   index_type n;
237627f7eb2Smrg   index_type len;
238627f7eb2Smrg   index_type delta;
239627f7eb2Smrg   index_type mdelta;
240627f7eb2Smrg   int mask_kind;
241627f7eb2Smrg 
242627f7eb2Smrg   if (mask == NULL)
243627f7eb2Smrg     {
244627f7eb2Smrg       maxval1_s1 (retarray, xlen, array, pdim, string_len);
245627f7eb2Smrg       return;
246627f7eb2Smrg     }
247627f7eb2Smrg 
248627f7eb2Smrg   assert (xlen == string_len);
249627f7eb2Smrg 
250627f7eb2Smrg   dim = (*pdim) - 1;
251627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
252627f7eb2Smrg 
253627f7eb2Smrg   if (unlikely (dim < 0 || dim > rank))
254627f7eb2Smrg     {
255627f7eb2Smrg       runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
256627f7eb2Smrg  		     "is %ld, should be between 1 and %ld",
257627f7eb2Smrg 		     (long int) dim + 1, (long int) rank + 1);
258627f7eb2Smrg     }
259627f7eb2Smrg 
260627f7eb2Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
261627f7eb2Smrg   if (len <= 0)
262627f7eb2Smrg     return;
263627f7eb2Smrg 
264627f7eb2Smrg   mbase = mask->base_addr;
265627f7eb2Smrg 
266627f7eb2Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
267627f7eb2Smrg 
268627f7eb2Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
269627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
270627f7eb2Smrg       || mask_kind == 16
271627f7eb2Smrg #endif
272627f7eb2Smrg       )
273627f7eb2Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
274627f7eb2Smrg   else
275627f7eb2Smrg     runtime_error ("Funny sized logical array");
276627f7eb2Smrg 
277627f7eb2Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
278627f7eb2Smrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
279627f7eb2Smrg 
280627f7eb2Smrg   for (n = 0; n < dim; n++)
281627f7eb2Smrg     {
282627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
283627f7eb2Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
284627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
285627f7eb2Smrg 
286627f7eb2Smrg       if (extent[n] < 0)
287627f7eb2Smrg 	extent[n] = 0;
288627f7eb2Smrg 
289627f7eb2Smrg     }
290627f7eb2Smrg   for (n = dim; n < rank; n++)
291627f7eb2Smrg     {
292627f7eb2Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
293627f7eb2Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
294627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
295627f7eb2Smrg 
296627f7eb2Smrg       if (extent[n] < 0)
297627f7eb2Smrg 	extent[n] = 0;
298627f7eb2Smrg     }
299627f7eb2Smrg 
300627f7eb2Smrg   if (retarray->base_addr == NULL)
301627f7eb2Smrg     {
302627f7eb2Smrg       size_t alloc_size, str;
303627f7eb2Smrg 
304627f7eb2Smrg       for (n = 0; n < rank; n++)
305627f7eb2Smrg 	{
306627f7eb2Smrg 	  if (n == 0)
307627f7eb2Smrg 	    str = 1;
308627f7eb2Smrg 	  else
309627f7eb2Smrg 	    str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
310627f7eb2Smrg 
311627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
312627f7eb2Smrg 
313627f7eb2Smrg 	}
314627f7eb2Smrg 
315627f7eb2Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
316627f7eb2Smrg       		 * string_len;
317627f7eb2Smrg 
318627f7eb2Smrg       retarray->offset = 0;
319627f7eb2Smrg       retarray->dtype.rank = rank;
320627f7eb2Smrg 
321627f7eb2Smrg       if (alloc_size == 0)
322627f7eb2Smrg 	{
323627f7eb2Smrg 	  /* Make sure we have a zero-sized array.  */
324627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
325627f7eb2Smrg 	  return;
326627f7eb2Smrg 	}
327627f7eb2Smrg       else
328627f7eb2Smrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_UINTEGER_1));
329627f7eb2Smrg 
330627f7eb2Smrg     }
331627f7eb2Smrg   else
332627f7eb2Smrg     {
333627f7eb2Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
334627f7eb2Smrg 	runtime_error ("rank of return array incorrect in MAXVAL intrinsic");
335627f7eb2Smrg 
336627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
337627f7eb2Smrg 	{
338627f7eb2Smrg 	  bounds_ifunction_return ((array_t *) retarray, extent,
339627f7eb2Smrg 				   "return value", "MAXVAL");
340627f7eb2Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
341627f7eb2Smrg 	  			"MASK argument", "MAXVAL");
342627f7eb2Smrg 	}
343627f7eb2Smrg     }
344627f7eb2Smrg 
345627f7eb2Smrg   for (n = 0; n < rank; n++)
346627f7eb2Smrg     {
347627f7eb2Smrg       count[n] = 0;
348627f7eb2Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
349627f7eb2Smrg       if (extent[n] <= 0)
350627f7eb2Smrg 	return;
351627f7eb2Smrg     }
352627f7eb2Smrg 
353627f7eb2Smrg   dest = retarray->base_addr;
354627f7eb2Smrg   base = array->base_addr;
355627f7eb2Smrg 
356627f7eb2Smrg   while (base)
357627f7eb2Smrg     {
358627f7eb2Smrg       const GFC_UINTEGER_1 * restrict src;
359627f7eb2Smrg       const GFC_LOGICAL_1 * restrict msrc;
360627f7eb2Smrg 
361627f7eb2Smrg       src = base;
362627f7eb2Smrg       msrc = mbase;
363627f7eb2Smrg       {
364627f7eb2Smrg 
365627f7eb2Smrg 	const GFC_UINTEGER_1 *retval;
366627f7eb2Smrg 	memset (dest, 0, sizeof (*dest) * string_len);
367627f7eb2Smrg 	retval = dest;
368627f7eb2Smrg 	for (n = 0; n < len; n++, src += delta, msrc += mdelta)
369627f7eb2Smrg 	  {
370627f7eb2Smrg 
371627f7eb2Smrg 		if (*msrc)
372627f7eb2Smrg 		      {
373627f7eb2Smrg 			retval = src;
374627f7eb2Smrg 			break;
375627f7eb2Smrg 		      }
376627f7eb2Smrg 	    }
377627f7eb2Smrg 	    for (; n < len; n++, src += delta, msrc += mdelta)
378627f7eb2Smrg 	      {
379627f7eb2Smrg 		if (*msrc && compare_fcn (src, retval, string_len) > 0)
380627f7eb2Smrg 		  {
381627f7eb2Smrg 		    retval = src;
382627f7eb2Smrg 		  }
383627f7eb2Smrg 
384627f7eb2Smrg 	  }
385627f7eb2Smrg 	memcpy (dest, retval, sizeof (*dest) * string_len);
386627f7eb2Smrg       }
387627f7eb2Smrg       /* Advance to the next element.  */
388627f7eb2Smrg       count[0]++;
389627f7eb2Smrg       base += sstride[0];
390627f7eb2Smrg       mbase += mstride[0];
391627f7eb2Smrg       dest += dstride[0];
392627f7eb2Smrg       n = 0;
393627f7eb2Smrg       while (count[n] == extent[n])
394627f7eb2Smrg 	{
395627f7eb2Smrg 	  /* When we get to the end of a dimension, reset it and increment
396627f7eb2Smrg 	     the next dimension.  */
397627f7eb2Smrg 	  count[n] = 0;
398627f7eb2Smrg 	  /* We could precalculate these products, but this is a less
399627f7eb2Smrg 	     frequently used path so probably not worth it.  */
400627f7eb2Smrg 	  base -= sstride[n] * extent[n];
401627f7eb2Smrg 	  mbase -= mstride[n] * extent[n];
402627f7eb2Smrg 	  dest -= dstride[n] * extent[n];
403627f7eb2Smrg 	  n++;
404627f7eb2Smrg 	  if (n >= rank)
405627f7eb2Smrg 	    {
406627f7eb2Smrg 	      /* Break out of the loop.  */
407627f7eb2Smrg 	      base = NULL;
408627f7eb2Smrg 	      break;
409627f7eb2Smrg 	    }
410627f7eb2Smrg 	  else
411627f7eb2Smrg 	    {
412627f7eb2Smrg 	      count[n]++;
413627f7eb2Smrg 	      base += sstride[n];
414627f7eb2Smrg 	      mbase += mstride[n];
415627f7eb2Smrg 	      dest += dstride[n];
416627f7eb2Smrg 	    }
417627f7eb2Smrg 	}
418627f7eb2Smrg     }
419627f7eb2Smrg }
420627f7eb2Smrg 
421627f7eb2Smrg 
422627f7eb2Smrg void smaxval1_s1 (gfc_array_s1 * const restrict,
423627f7eb2Smrg         gfc_charlen_type, gfc_array_s1 * const restrict,
424627f7eb2Smrg 	const index_type * const restrict,
425627f7eb2Smrg 	GFC_LOGICAL_4 *, gfc_charlen_type);
426627f7eb2Smrg 
427627f7eb2Smrg export_proto(smaxval1_s1);
428627f7eb2Smrg 
429627f7eb2Smrg void
smaxval1_s1(gfc_array_s1 * const restrict retarray,gfc_charlen_type xlen,gfc_array_s1 * const restrict array,const index_type * const restrict pdim,GFC_LOGICAL_4 * mask,gfc_charlen_type string_len)430627f7eb2Smrg smaxval1_s1 (gfc_array_s1 * const restrict retarray,
431627f7eb2Smrg 	gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
432627f7eb2Smrg 	const index_type * const restrict pdim,
433627f7eb2Smrg 	GFC_LOGICAL_4 *mask, gfc_charlen_type string_len)
434627f7eb2Smrg 
435627f7eb2Smrg {
436627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
437627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
438627f7eb2Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
439627f7eb2Smrg   GFC_UINTEGER_1 * restrict dest;
440627f7eb2Smrg   index_type rank;
441627f7eb2Smrg   index_type n;
442627f7eb2Smrg   index_type dim;
443627f7eb2Smrg 
444627f7eb2Smrg 
445627f7eb2Smrg   if (mask == NULL || *mask)
446627f7eb2Smrg     {
447627f7eb2Smrg       maxval1_s1 (retarray, xlen, array, pdim, string_len);
448627f7eb2Smrg       return;
449627f7eb2Smrg     }
450627f7eb2Smrg   /* Make dim zero based to avoid confusion.  */
451627f7eb2Smrg   dim = (*pdim) - 1;
452627f7eb2Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
453627f7eb2Smrg 
454627f7eb2Smrg   if (unlikely (dim < 0 || dim > rank))
455627f7eb2Smrg     {
456627f7eb2Smrg       runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
457627f7eb2Smrg  		     "is %ld, should be between 1 and %ld",
458627f7eb2Smrg 		     (long int) dim + 1, (long int) rank + 1);
459627f7eb2Smrg     }
460627f7eb2Smrg 
461627f7eb2Smrg   for (n = 0; n < dim; n++)
462627f7eb2Smrg     {
463627f7eb2Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
464627f7eb2Smrg 
465627f7eb2Smrg       if (extent[n] <= 0)
466627f7eb2Smrg 	extent[n] = 0;
467627f7eb2Smrg     }
468627f7eb2Smrg 
469627f7eb2Smrg   for (n = dim; n < rank; n++)
470627f7eb2Smrg     {
471627f7eb2Smrg       extent[n] =
472627f7eb2Smrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
473627f7eb2Smrg 
474627f7eb2Smrg       if (extent[n] <= 0)
475627f7eb2Smrg 	extent[n] = 0;
476627f7eb2Smrg     }
477627f7eb2Smrg 
478627f7eb2Smrg   if (retarray->base_addr == NULL)
479627f7eb2Smrg     {
480627f7eb2Smrg       size_t alloc_size, str;
481627f7eb2Smrg 
482627f7eb2Smrg       for (n = 0; n < rank; n++)
483627f7eb2Smrg 	{
484627f7eb2Smrg 	  if (n == 0)
485627f7eb2Smrg 	    str = 1;
486627f7eb2Smrg 	  else
487627f7eb2Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
488627f7eb2Smrg 
489627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
490627f7eb2Smrg 
491627f7eb2Smrg 	}
492627f7eb2Smrg 
493627f7eb2Smrg       retarray->offset = 0;
494627f7eb2Smrg       retarray->dtype.rank = rank;
495627f7eb2Smrg 
496627f7eb2Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
497627f7eb2Smrg       		 * string_len;
498627f7eb2Smrg 
499627f7eb2Smrg       if (alloc_size == 0)
500627f7eb2Smrg 	{
501627f7eb2Smrg 	  /* Make sure we have a zero-sized array.  */
502627f7eb2Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
503627f7eb2Smrg 	  return;
504627f7eb2Smrg 	}
505627f7eb2Smrg       else
506627f7eb2Smrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_UINTEGER_1));
507627f7eb2Smrg     }
508627f7eb2Smrg   else
509627f7eb2Smrg     {
510627f7eb2Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
511627f7eb2Smrg 	runtime_error ("rank of return array incorrect in"
512627f7eb2Smrg 		       " MAXVAL intrinsic: is %ld, should be %ld",
513627f7eb2Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
514627f7eb2Smrg 		       (long int) rank);
515627f7eb2Smrg 
516627f7eb2Smrg       if (unlikely (compile_options.bounds_check))
517627f7eb2Smrg 	{
518627f7eb2Smrg 	  for (n=0; n < rank; n++)
519627f7eb2Smrg 	    {
520627f7eb2Smrg 	      index_type ret_extent;
521627f7eb2Smrg 
522627f7eb2Smrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
523627f7eb2Smrg 	      if (extent[n] != ret_extent)
524627f7eb2Smrg 		runtime_error ("Incorrect extent in return value of"
525627f7eb2Smrg 			       " MAXVAL intrinsic in dimension %ld:"
526627f7eb2Smrg 			       " is %ld, should be %ld", (long int) n + 1,
527627f7eb2Smrg 			       (long int) ret_extent, (long int) extent[n]);
528627f7eb2Smrg 	    }
529627f7eb2Smrg 	}
530627f7eb2Smrg     }
531627f7eb2Smrg 
532627f7eb2Smrg   for (n = 0; n < rank; n++)
533627f7eb2Smrg     {
534627f7eb2Smrg       count[n] = 0;
535627f7eb2Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
536627f7eb2Smrg     }
537627f7eb2Smrg 
538627f7eb2Smrg   dest = retarray->base_addr;
539627f7eb2Smrg 
540627f7eb2Smrg   while(1)
541627f7eb2Smrg     {
542627f7eb2Smrg       memset (dest, 0, sizeof (*dest) * string_len);
543627f7eb2Smrg       count[0]++;
544627f7eb2Smrg       dest += dstride[0];
545627f7eb2Smrg       n = 0;
546627f7eb2Smrg       while (count[n] == extent[n])
547627f7eb2Smrg 	{
548627f7eb2Smrg 	  /* When we get to the end of a dimension, reset it and increment
549627f7eb2Smrg 	     the next dimension.  */
550627f7eb2Smrg 	  count[n] = 0;
551627f7eb2Smrg 	  /* We could precalculate these products, but this is a less
552627f7eb2Smrg 	     frequently used path so probably not worth it.  */
553627f7eb2Smrg 	  dest -= dstride[n] * extent[n];
554627f7eb2Smrg 	  n++;
555627f7eb2Smrg 	  if (n >= rank)
556627f7eb2Smrg 	    return;
557627f7eb2Smrg 	  else
558627f7eb2Smrg 	    {
559627f7eb2Smrg 	      count[n]++;
560627f7eb2Smrg 	      dest += dstride[n];
561627f7eb2Smrg 	    }
562627f7eb2Smrg       	}
563627f7eb2Smrg     }
564627f7eb2Smrg }
565627f7eb2Smrg 
566627f7eb2Smrg #endif
567