xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/maxval1_s1.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1181254a7Smrg /* Implementation of the MAXVAL 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 
28181254a7Smrg 
29181254a7Smrg #if defined (HAVE_GFC_UINTEGER_1) && defined (HAVE_GFC_UINTEGER_1)
30181254a7Smrg 
31181254a7Smrg #include <string.h>
32181254a7Smrg #include <assert.h>
33181254a7Smrg 
34181254a7Smrg static inline int
compare_fcn(const GFC_UINTEGER_1 * a,const GFC_UINTEGER_1 * b,gfc_charlen_type n)35181254a7Smrg compare_fcn (const GFC_UINTEGER_1 *a, const GFC_UINTEGER_1 *b, gfc_charlen_type n)
36181254a7Smrg {
37181254a7Smrg   if (sizeof (GFC_UINTEGER_1) == 1)
38181254a7Smrg     return memcmp (a, b, n);
39181254a7Smrg   else
40181254a7Smrg     return memcmp_char4 (a, b, n);
41181254a7Smrg }
42181254a7Smrg 
43181254a7Smrg extern void maxval1_s1 (gfc_array_s1 * const restrict,
44181254a7Smrg         gfc_charlen_type, gfc_array_s1 * const restrict,
45181254a7Smrg 	const index_type * const restrict, gfc_charlen_type);
46181254a7Smrg export_proto(maxval1_s1);
47181254a7Smrg 
48181254a7Smrg 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)49181254a7Smrg maxval1_s1 (gfc_array_s1 * const restrict retarray,
50181254a7Smrg 	gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
51181254a7Smrg 	const index_type * const restrict pdim, gfc_charlen_type string_len)
52181254a7Smrg {
53181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
54181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
55181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
56181254a7Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
57181254a7Smrg   const GFC_UINTEGER_1 * restrict base;
58181254a7Smrg   GFC_UINTEGER_1 * restrict dest;
59181254a7Smrg   index_type rank;
60181254a7Smrg   index_type n;
61181254a7Smrg   index_type len;
62181254a7Smrg   index_type delta;
63181254a7Smrg   index_type dim;
64181254a7Smrg   int continue_loop;
65181254a7Smrg 
66181254a7Smrg   assert (xlen == string_len);
67181254a7Smrg   /* Make dim zero based to avoid confusion.  */
68181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
69181254a7Smrg   dim = (*pdim) - 1;
70181254a7Smrg 
71181254a7Smrg   if (unlikely (dim < 0 || dim > rank))
72181254a7Smrg     {
73181254a7Smrg       runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
74181254a7Smrg  		     "is %ld, should be between 1 and %ld",
75181254a7Smrg 		     (long int) dim + 1, (long int) rank + 1);
76181254a7Smrg     }
77181254a7Smrg 
78181254a7Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
79181254a7Smrg   if (len < 0)
80181254a7Smrg     len = 0;
81181254a7Smrg 
82181254a7Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
83181254a7Smrg 
84181254a7Smrg   for (n = 0; n < dim; n++)
85181254a7Smrg     {
86181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
87181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
88181254a7Smrg 
89181254a7Smrg       if (extent[n] < 0)
90181254a7Smrg 	extent[n] = 0;
91181254a7Smrg     }
92181254a7Smrg   for (n = dim; n < rank; n++)
93181254a7Smrg     {
94181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
95181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
96181254a7Smrg 
97181254a7Smrg       if (extent[n] < 0)
98181254a7Smrg 	extent[n] = 0;
99181254a7Smrg     }
100181254a7Smrg 
101181254a7Smrg   if (retarray->base_addr == NULL)
102181254a7Smrg     {
103181254a7Smrg       size_t alloc_size, str;
104181254a7Smrg 
105181254a7Smrg       for (n = 0; n < rank; n++)
106181254a7Smrg 	{
107181254a7Smrg 	  if (n == 0)
108181254a7Smrg 	    str = 1;
109181254a7Smrg 	  else
110181254a7Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
111181254a7Smrg 
112181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
113181254a7Smrg 
114181254a7Smrg 	}
115181254a7Smrg 
116181254a7Smrg       retarray->offset = 0;
117181254a7Smrg       retarray->dtype.rank = rank;
118181254a7Smrg 
119181254a7Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
120181254a7Smrg       		 * string_len;
121181254a7Smrg 
122181254a7Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_UINTEGER_1));
123181254a7Smrg       if (alloc_size == 0)
124181254a7Smrg 	{
125181254a7Smrg 	  /* Make sure we have a zero-sized array.  */
126181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
127181254a7Smrg 	  return;
128181254a7Smrg 
129181254a7Smrg 	}
130181254a7Smrg     }
131181254a7Smrg   else
132181254a7Smrg     {
133181254a7Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
134181254a7Smrg 	runtime_error ("rank of return array incorrect in"
135181254a7Smrg 		       " MAXVAL intrinsic: is %ld, should be %ld",
136181254a7Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
137181254a7Smrg 		       (long int) rank);
138181254a7Smrg 
139181254a7Smrg       if (unlikely (compile_options.bounds_check))
140181254a7Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
141181254a7Smrg 				 "return value", "MAXVAL");
142181254a7Smrg     }
143181254a7Smrg 
144181254a7Smrg   for (n = 0; n < rank; n++)
145181254a7Smrg     {
146181254a7Smrg       count[n] = 0;
147181254a7Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
148181254a7Smrg       if (extent[n] <= 0)
149181254a7Smrg 	return;
150181254a7Smrg     }
151181254a7Smrg 
152181254a7Smrg   base = array->base_addr;
153181254a7Smrg   dest = retarray->base_addr;
154181254a7Smrg 
155181254a7Smrg   continue_loop = 1;
156181254a7Smrg   while (continue_loop)
157181254a7Smrg     {
158181254a7Smrg       const GFC_UINTEGER_1 * restrict src;
159181254a7Smrg       src = base;
160181254a7Smrg       {
161181254a7Smrg 
162181254a7Smrg 	const GFC_UINTEGER_1 *retval;
163181254a7Smrg 	retval = base;
164181254a7Smrg 	if (len <= 0)
165181254a7Smrg 	  memset (dest, 0, sizeof (*dest) * string_len);
166181254a7Smrg 	else
167181254a7Smrg 	  {
168181254a7Smrg 	    for (n = 0; n < len; n++, src += delta)
169181254a7Smrg 	      {
170181254a7Smrg 
171181254a7Smrg 		if (compare_fcn (src, retval, string_len) > 0)
172181254a7Smrg 		  {
173181254a7Smrg 		    retval = src;
174181254a7Smrg 		  }
175181254a7Smrg 	      }
176181254a7Smrg 
177181254a7Smrg 	    memcpy (dest, retval, sizeof (*dest) * string_len);
178181254a7Smrg 	  }
179181254a7Smrg       }
180181254a7Smrg       /* Advance to the next element.  */
181181254a7Smrg       count[0]++;
182181254a7Smrg       base += sstride[0];
183181254a7Smrg       dest += dstride[0];
184181254a7Smrg       n = 0;
185181254a7Smrg       while (count[n] == extent[n])
186181254a7Smrg 	{
187181254a7Smrg 	  /* When we get to the end of a dimension, reset it and increment
188181254a7Smrg 	     the next dimension.  */
189181254a7Smrg 	  count[n] = 0;
190181254a7Smrg 	  /* We could precalculate these products, but this is a less
191181254a7Smrg 	     frequently used path so probably not worth it.  */
192181254a7Smrg 	  base -= sstride[n] * extent[n];
193181254a7Smrg 	  dest -= dstride[n] * extent[n];
194181254a7Smrg 	  n++;
195181254a7Smrg 	  if (n >= rank)
196181254a7Smrg 	    {
197181254a7Smrg 	      /* Break out of the loop.  */
198181254a7Smrg 	      continue_loop = 0;
199181254a7Smrg 	      break;
200181254a7Smrg 	    }
201181254a7Smrg 	  else
202181254a7Smrg 	    {
203181254a7Smrg 	      count[n]++;
204181254a7Smrg 	      base += sstride[n];
205181254a7Smrg 	      dest += dstride[n];
206181254a7Smrg 	    }
207181254a7Smrg 	}
208181254a7Smrg     }
209181254a7Smrg }
210181254a7Smrg 
211181254a7Smrg 
212181254a7Smrg extern void mmaxval1_s1 (gfc_array_s1 * const restrict,
213181254a7Smrg         gfc_charlen_type, gfc_array_s1 * const restrict,
214181254a7Smrg 	const index_type * const restrict,
215181254a7Smrg 	gfc_array_l1 * const restrict, gfc_charlen_type);
216181254a7Smrg export_proto(mmaxval1_s1);
217181254a7Smrg 
218181254a7Smrg 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)219181254a7Smrg mmaxval1_s1 (gfc_array_s1 * const restrict retarray,
220181254a7Smrg 	gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
221181254a7Smrg 	const index_type * const restrict pdim,
222181254a7Smrg 	gfc_array_l1 * const restrict mask,
223181254a7Smrg 	gfc_charlen_type string_len)
224181254a7Smrg 
225181254a7Smrg {
226181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
227181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
228181254a7Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
229181254a7Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
230181254a7Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
231181254a7Smrg   GFC_UINTEGER_1 * restrict dest;
232181254a7Smrg   const GFC_UINTEGER_1 * restrict base;
233181254a7Smrg   const GFC_LOGICAL_1 * restrict mbase;
234181254a7Smrg   index_type rank;
235181254a7Smrg   index_type dim;
236181254a7Smrg   index_type n;
237181254a7Smrg   index_type len;
238181254a7Smrg   index_type delta;
239181254a7Smrg   index_type mdelta;
240181254a7Smrg   int mask_kind;
241181254a7Smrg 
242181254a7Smrg   if (mask == NULL)
243181254a7Smrg     {
244181254a7Smrg       maxval1_s1 (retarray, xlen, array, pdim, string_len);
245181254a7Smrg       return;
246181254a7Smrg     }
247181254a7Smrg 
248181254a7Smrg   assert (xlen == string_len);
249181254a7Smrg 
250181254a7Smrg   dim = (*pdim) - 1;
251181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
252181254a7Smrg 
253181254a7Smrg   if (unlikely (dim < 0 || dim > rank))
254181254a7Smrg     {
255181254a7Smrg       runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
256181254a7Smrg  		     "is %ld, should be between 1 and %ld",
257181254a7Smrg 		     (long int) dim + 1, (long int) rank + 1);
258181254a7Smrg     }
259181254a7Smrg 
260181254a7Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
261181254a7Smrg   if (len <= 0)
262181254a7Smrg     return;
263181254a7Smrg 
264181254a7Smrg   mbase = mask->base_addr;
265181254a7Smrg 
266181254a7Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
267181254a7Smrg 
268181254a7Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
269181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
270181254a7Smrg       || mask_kind == 16
271181254a7Smrg #endif
272181254a7Smrg       )
273181254a7Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
274181254a7Smrg   else
275181254a7Smrg     runtime_error ("Funny sized logical array");
276181254a7Smrg 
277181254a7Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
278181254a7Smrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
279181254a7Smrg 
280181254a7Smrg   for (n = 0; n < dim; n++)
281181254a7Smrg     {
282181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
283181254a7Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
284181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
285181254a7Smrg 
286181254a7Smrg       if (extent[n] < 0)
287181254a7Smrg 	extent[n] = 0;
288181254a7Smrg 
289181254a7Smrg     }
290181254a7Smrg   for (n = dim; n < rank; n++)
291181254a7Smrg     {
292181254a7Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
293181254a7Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
294181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
295181254a7Smrg 
296181254a7Smrg       if (extent[n] < 0)
297181254a7Smrg 	extent[n] = 0;
298181254a7Smrg     }
299181254a7Smrg 
300181254a7Smrg   if (retarray->base_addr == NULL)
301181254a7Smrg     {
302181254a7Smrg       size_t alloc_size, str;
303181254a7Smrg 
304181254a7Smrg       for (n = 0; n < rank; n++)
305181254a7Smrg 	{
306181254a7Smrg 	  if (n == 0)
307181254a7Smrg 	    str = 1;
308181254a7Smrg 	  else
309181254a7Smrg 	    str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
310181254a7Smrg 
311181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
312181254a7Smrg 
313181254a7Smrg 	}
314181254a7Smrg 
315181254a7Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
316181254a7Smrg       		 * string_len;
317181254a7Smrg 
318181254a7Smrg       retarray->offset = 0;
319181254a7Smrg       retarray->dtype.rank = rank;
320181254a7Smrg 
321181254a7Smrg       if (alloc_size == 0)
322181254a7Smrg 	{
323181254a7Smrg 	  /* Make sure we have a zero-sized array.  */
324181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
325181254a7Smrg 	  return;
326181254a7Smrg 	}
327181254a7Smrg       else
328181254a7Smrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_UINTEGER_1));
329181254a7Smrg 
330181254a7Smrg     }
331181254a7Smrg   else
332181254a7Smrg     {
333181254a7Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
334181254a7Smrg 	runtime_error ("rank of return array incorrect in MAXVAL intrinsic");
335181254a7Smrg 
336181254a7Smrg       if (unlikely (compile_options.bounds_check))
337181254a7Smrg 	{
338181254a7Smrg 	  bounds_ifunction_return ((array_t *) retarray, extent,
339181254a7Smrg 				   "return value", "MAXVAL");
340181254a7Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
341181254a7Smrg 	  			"MASK argument", "MAXVAL");
342181254a7Smrg 	}
343181254a7Smrg     }
344181254a7Smrg 
345181254a7Smrg   for (n = 0; n < rank; n++)
346181254a7Smrg     {
347181254a7Smrg       count[n] = 0;
348181254a7Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
349181254a7Smrg       if (extent[n] <= 0)
350181254a7Smrg 	return;
351181254a7Smrg     }
352181254a7Smrg 
353181254a7Smrg   dest = retarray->base_addr;
354181254a7Smrg   base = array->base_addr;
355181254a7Smrg 
356181254a7Smrg   while (base)
357181254a7Smrg     {
358181254a7Smrg       const GFC_UINTEGER_1 * restrict src;
359181254a7Smrg       const GFC_LOGICAL_1 * restrict msrc;
360181254a7Smrg 
361181254a7Smrg       src = base;
362181254a7Smrg       msrc = mbase;
363181254a7Smrg       {
364181254a7Smrg 
365181254a7Smrg 	const GFC_UINTEGER_1 *retval;
366181254a7Smrg 	memset (dest, 0, sizeof (*dest) * string_len);
367181254a7Smrg 	retval = dest;
368181254a7Smrg 	for (n = 0; n < len; n++, src += delta, msrc += mdelta)
369181254a7Smrg 	  {
370181254a7Smrg 
371181254a7Smrg 		if (*msrc)
372181254a7Smrg 		      {
373181254a7Smrg 			retval = src;
374181254a7Smrg 			break;
375181254a7Smrg 		      }
376181254a7Smrg 	    }
377181254a7Smrg 	    for (; n < len; n++, src += delta, msrc += mdelta)
378181254a7Smrg 	      {
379181254a7Smrg 		if (*msrc && compare_fcn (src, retval, string_len) > 0)
380181254a7Smrg 		  {
381181254a7Smrg 		    retval = src;
382181254a7Smrg 		  }
383181254a7Smrg 
384181254a7Smrg 	  }
385181254a7Smrg 	memcpy (dest, retval, sizeof (*dest) * string_len);
386181254a7Smrg       }
387181254a7Smrg       /* Advance to the next element.  */
388181254a7Smrg       count[0]++;
389181254a7Smrg       base += sstride[0];
390181254a7Smrg       mbase += mstride[0];
391181254a7Smrg       dest += dstride[0];
392181254a7Smrg       n = 0;
393181254a7Smrg       while (count[n] == extent[n])
394181254a7Smrg 	{
395181254a7Smrg 	  /* When we get to the end of a dimension, reset it and increment
396181254a7Smrg 	     the next dimension.  */
397181254a7Smrg 	  count[n] = 0;
398181254a7Smrg 	  /* We could precalculate these products, but this is a less
399181254a7Smrg 	     frequently used path so probably not worth it.  */
400181254a7Smrg 	  base -= sstride[n] * extent[n];
401181254a7Smrg 	  mbase -= mstride[n] * extent[n];
402181254a7Smrg 	  dest -= dstride[n] * extent[n];
403181254a7Smrg 	  n++;
404181254a7Smrg 	  if (n >= rank)
405181254a7Smrg 	    {
406181254a7Smrg 	      /* Break out of the loop.  */
407181254a7Smrg 	      base = NULL;
408181254a7Smrg 	      break;
409181254a7Smrg 	    }
410181254a7Smrg 	  else
411181254a7Smrg 	    {
412181254a7Smrg 	      count[n]++;
413181254a7Smrg 	      base += sstride[n];
414181254a7Smrg 	      mbase += mstride[n];
415181254a7Smrg 	      dest += dstride[n];
416181254a7Smrg 	    }
417181254a7Smrg 	}
418181254a7Smrg     }
419181254a7Smrg }
420181254a7Smrg 
421181254a7Smrg 
422181254a7Smrg void smaxval1_s1 (gfc_array_s1 * const restrict,
423181254a7Smrg         gfc_charlen_type, gfc_array_s1 * const restrict,
424181254a7Smrg 	const index_type * const restrict,
425181254a7Smrg 	GFC_LOGICAL_4 *, gfc_charlen_type);
426181254a7Smrg 
427181254a7Smrg export_proto(smaxval1_s1);
428181254a7Smrg 
429181254a7Smrg 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)430181254a7Smrg smaxval1_s1 (gfc_array_s1 * const restrict retarray,
431181254a7Smrg 	gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
432181254a7Smrg 	const index_type * const restrict pdim,
433181254a7Smrg 	GFC_LOGICAL_4 *mask, gfc_charlen_type string_len)
434181254a7Smrg 
435181254a7Smrg {
436181254a7Smrg   index_type count[GFC_MAX_DIMENSIONS];
437181254a7Smrg   index_type extent[GFC_MAX_DIMENSIONS];
438181254a7Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
439181254a7Smrg   GFC_UINTEGER_1 * restrict dest;
440181254a7Smrg   index_type rank;
441181254a7Smrg   index_type n;
442181254a7Smrg   index_type dim;
443181254a7Smrg 
444181254a7Smrg 
445181254a7Smrg   if (mask == NULL || *mask)
446181254a7Smrg     {
447181254a7Smrg       maxval1_s1 (retarray, xlen, array, pdim, string_len);
448181254a7Smrg       return;
449181254a7Smrg     }
450181254a7Smrg   /* Make dim zero based to avoid confusion.  */
451181254a7Smrg   dim = (*pdim) - 1;
452181254a7Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
453181254a7Smrg 
454181254a7Smrg   if (unlikely (dim < 0 || dim > rank))
455181254a7Smrg     {
456181254a7Smrg       runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
457181254a7Smrg  		     "is %ld, should be between 1 and %ld",
458181254a7Smrg 		     (long int) dim + 1, (long int) rank + 1);
459181254a7Smrg     }
460181254a7Smrg 
461181254a7Smrg   for (n = 0; n < dim; n++)
462181254a7Smrg     {
463181254a7Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
464181254a7Smrg 
465181254a7Smrg       if (extent[n] <= 0)
466181254a7Smrg 	extent[n] = 0;
467181254a7Smrg     }
468181254a7Smrg 
469181254a7Smrg   for (n = dim; n < rank; n++)
470181254a7Smrg     {
471181254a7Smrg       extent[n] =
472181254a7Smrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
473181254a7Smrg 
474181254a7Smrg       if (extent[n] <= 0)
475181254a7Smrg 	extent[n] = 0;
476181254a7Smrg     }
477181254a7Smrg 
478181254a7Smrg   if (retarray->base_addr == NULL)
479181254a7Smrg     {
480181254a7Smrg       size_t alloc_size, str;
481181254a7Smrg 
482181254a7Smrg       for (n = 0; n < rank; n++)
483181254a7Smrg 	{
484181254a7Smrg 	  if (n == 0)
485181254a7Smrg 	    str = 1;
486181254a7Smrg 	  else
487181254a7Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
488181254a7Smrg 
489181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
490181254a7Smrg 
491181254a7Smrg 	}
492181254a7Smrg 
493181254a7Smrg       retarray->offset = 0;
494181254a7Smrg       retarray->dtype.rank = rank;
495181254a7Smrg 
496181254a7Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
497181254a7Smrg       		 * string_len;
498181254a7Smrg 
499181254a7Smrg       if (alloc_size == 0)
500181254a7Smrg 	{
501181254a7Smrg 	  /* Make sure we have a zero-sized array.  */
502181254a7Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
503181254a7Smrg 	  return;
504181254a7Smrg 	}
505181254a7Smrg       else
506181254a7Smrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_UINTEGER_1));
507181254a7Smrg     }
508181254a7Smrg   else
509181254a7Smrg     {
510181254a7Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
511181254a7Smrg 	runtime_error ("rank of return array incorrect in"
512181254a7Smrg 		       " MAXVAL intrinsic: is %ld, should be %ld",
513181254a7Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
514181254a7Smrg 		       (long int) rank);
515181254a7Smrg 
516181254a7Smrg       if (unlikely (compile_options.bounds_check))
517181254a7Smrg 	{
518181254a7Smrg 	  for (n=0; n < rank; n++)
519181254a7Smrg 	    {
520181254a7Smrg 	      index_type ret_extent;
521181254a7Smrg 
522181254a7Smrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
523181254a7Smrg 	      if (extent[n] != ret_extent)
524181254a7Smrg 		runtime_error ("Incorrect extent in return value of"
525181254a7Smrg 			       " MAXVAL intrinsic in dimension %ld:"
526181254a7Smrg 			       " is %ld, should be %ld", (long int) n + 1,
527181254a7Smrg 			       (long int) ret_extent, (long int) extent[n]);
528181254a7Smrg 	    }
529181254a7Smrg 	}
530181254a7Smrg     }
531181254a7Smrg 
532181254a7Smrg   for (n = 0; n < rank; n++)
533181254a7Smrg     {
534181254a7Smrg       count[n] = 0;
535181254a7Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
536181254a7Smrg     }
537181254a7Smrg 
538181254a7Smrg   dest = retarray->base_addr;
539181254a7Smrg 
540181254a7Smrg   while(1)
541181254a7Smrg     {
542181254a7Smrg       memset (dest, 0, sizeof (*dest) * string_len);
543181254a7Smrg       count[0]++;
544181254a7Smrg       dest += dstride[0];
545181254a7Smrg       n = 0;
546181254a7Smrg       while (count[n] == extent[n])
547181254a7Smrg 	{
548181254a7Smrg 	  /* When we get to the end of a dimension, reset it and increment
549181254a7Smrg 	     the next dimension.  */
550181254a7Smrg 	  count[n] = 0;
551181254a7Smrg 	  /* We could precalculate these products, but this is a less
552181254a7Smrg 	     frequently used path so probably not worth it.  */
553181254a7Smrg 	  dest -= dstride[n] * extent[n];
554181254a7Smrg 	  n++;
555181254a7Smrg 	  if (n >= rank)
556181254a7Smrg 	    return;
557181254a7Smrg 	  else
558181254a7Smrg 	    {
559181254a7Smrg 	      count[n]++;
560181254a7Smrg 	      dest += dstride[n];
561181254a7Smrg 	    }
562181254a7Smrg       	}
563181254a7Smrg     }
564181254a7Smrg }
565181254a7Smrg 
566181254a7Smrg #endif
567