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