xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/maxval_r17.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1*b1e83836Smrg /* Implementation of the MAXVAL intrinsic
2*b1e83836Smrg    Copyright (C) 2002-2022 Free Software Foundation, Inc.
3*b1e83836Smrg    Contributed by Paul Brook <paul@nowt.org>
4*b1e83836Smrg 
5*b1e83836Smrg This file is part of the GNU Fortran runtime library (libgfortran).
6*b1e83836Smrg 
7*b1e83836Smrg Libgfortran is free software; you can redistribute it and/or
8*b1e83836Smrg modify it under the terms of the GNU General Public
9*b1e83836Smrg License as published by the Free Software Foundation; either
10*b1e83836Smrg version 3 of the License, or (at your option) any later version.
11*b1e83836Smrg 
12*b1e83836Smrg Libgfortran is distributed in the hope that it will be useful,
13*b1e83836Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14*b1e83836Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*b1e83836Smrg GNU General Public License for more details.
16*b1e83836Smrg 
17*b1e83836Smrg Under Section 7 of GPL version 3, you are granted additional
18*b1e83836Smrg permissions described in the GCC Runtime Library Exception, version
19*b1e83836Smrg 3.1, as published by the Free Software Foundation.
20*b1e83836Smrg 
21*b1e83836Smrg You should have received a copy of the GNU General Public License and
22*b1e83836Smrg a copy of the GCC Runtime Library Exception along with this program;
23*b1e83836Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24*b1e83836Smrg <http://www.gnu.org/licenses/>.  */
25*b1e83836Smrg 
26*b1e83836Smrg #include "libgfortran.h"
27*b1e83836Smrg 
28*b1e83836Smrg 
29*b1e83836Smrg #if defined (HAVE_GFC_REAL_17) && defined (HAVE_GFC_REAL_17)
30*b1e83836Smrg 
31*b1e83836Smrg 
32*b1e83836Smrg extern void maxval_r17 (gfc_array_r17 * const restrict,
33*b1e83836Smrg 	gfc_array_r17 * const restrict, const index_type * const restrict);
34*b1e83836Smrg export_proto(maxval_r17);
35*b1e83836Smrg 
36*b1e83836Smrg void
maxval_r17(gfc_array_r17 * const restrict retarray,gfc_array_r17 * const restrict array,const index_type * const restrict pdim)37*b1e83836Smrg maxval_r17 (gfc_array_r17 * const restrict retarray,
38*b1e83836Smrg 	gfc_array_r17 * const restrict array,
39*b1e83836Smrg 	const index_type * const restrict pdim)
40*b1e83836Smrg {
41*b1e83836Smrg   index_type count[GFC_MAX_DIMENSIONS];
42*b1e83836Smrg   index_type extent[GFC_MAX_DIMENSIONS];
43*b1e83836Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
44*b1e83836Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
45*b1e83836Smrg   const GFC_REAL_17 * restrict base;
46*b1e83836Smrg   GFC_REAL_17 * restrict dest;
47*b1e83836Smrg   index_type rank;
48*b1e83836Smrg   index_type n;
49*b1e83836Smrg   index_type len;
50*b1e83836Smrg   index_type delta;
51*b1e83836Smrg   index_type dim;
52*b1e83836Smrg   int continue_loop;
53*b1e83836Smrg 
54*b1e83836Smrg   /* Make dim zero based to avoid confusion.  */
55*b1e83836Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
56*b1e83836Smrg   dim = (*pdim) - 1;
57*b1e83836Smrg 
58*b1e83836Smrg   if (unlikely (dim < 0 || dim > rank))
59*b1e83836Smrg     {
60*b1e83836Smrg       runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
61*b1e83836Smrg  		     "is %ld, should be between 1 and %ld",
62*b1e83836Smrg 		     (long int) dim + 1, (long int) rank + 1);
63*b1e83836Smrg     }
64*b1e83836Smrg 
65*b1e83836Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
66*b1e83836Smrg   if (len < 0)
67*b1e83836Smrg     len = 0;
68*b1e83836Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
69*b1e83836Smrg 
70*b1e83836Smrg   for (n = 0; n < dim; n++)
71*b1e83836Smrg     {
72*b1e83836Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
73*b1e83836Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
74*b1e83836Smrg 
75*b1e83836Smrg       if (extent[n] < 0)
76*b1e83836Smrg 	extent[n] = 0;
77*b1e83836Smrg     }
78*b1e83836Smrg   for (n = dim; n < rank; n++)
79*b1e83836Smrg     {
80*b1e83836Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
81*b1e83836Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
82*b1e83836Smrg 
83*b1e83836Smrg       if (extent[n] < 0)
84*b1e83836Smrg 	extent[n] = 0;
85*b1e83836Smrg     }
86*b1e83836Smrg 
87*b1e83836Smrg   if (retarray->base_addr == NULL)
88*b1e83836Smrg     {
89*b1e83836Smrg       size_t alloc_size, str;
90*b1e83836Smrg 
91*b1e83836Smrg       for (n = 0; n < rank; n++)
92*b1e83836Smrg 	{
93*b1e83836Smrg 	  if (n == 0)
94*b1e83836Smrg 	    str = 1;
95*b1e83836Smrg 	  else
96*b1e83836Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
97*b1e83836Smrg 
98*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
99*b1e83836Smrg 
100*b1e83836Smrg 	}
101*b1e83836Smrg 
102*b1e83836Smrg       retarray->offset = 0;
103*b1e83836Smrg       retarray->dtype.rank = rank;
104*b1e83836Smrg 
105*b1e83836Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
106*b1e83836Smrg 
107*b1e83836Smrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_REAL_17));
108*b1e83836Smrg       if (alloc_size == 0)
109*b1e83836Smrg 	{
110*b1e83836Smrg 	  /* Make sure we have a zero-sized array.  */
111*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
112*b1e83836Smrg 	  return;
113*b1e83836Smrg 
114*b1e83836Smrg 	}
115*b1e83836Smrg     }
116*b1e83836Smrg   else
117*b1e83836Smrg     {
118*b1e83836Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
119*b1e83836Smrg 	runtime_error ("rank of return array incorrect in"
120*b1e83836Smrg 		       " MAXVAL intrinsic: is %ld, should be %ld",
121*b1e83836Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
122*b1e83836Smrg 		       (long int) rank);
123*b1e83836Smrg 
124*b1e83836Smrg       if (unlikely (compile_options.bounds_check))
125*b1e83836Smrg 	bounds_ifunction_return ((array_t *) retarray, extent,
126*b1e83836Smrg 				 "return value", "MAXVAL");
127*b1e83836Smrg     }
128*b1e83836Smrg 
129*b1e83836Smrg   for (n = 0; n < rank; n++)
130*b1e83836Smrg     {
131*b1e83836Smrg       count[n] = 0;
132*b1e83836Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
133*b1e83836Smrg       if (extent[n] <= 0)
134*b1e83836Smrg 	return;
135*b1e83836Smrg     }
136*b1e83836Smrg 
137*b1e83836Smrg   base = array->base_addr;
138*b1e83836Smrg   dest = retarray->base_addr;
139*b1e83836Smrg 
140*b1e83836Smrg   continue_loop = 1;
141*b1e83836Smrg   while (continue_loop)
142*b1e83836Smrg     {
143*b1e83836Smrg       const GFC_REAL_17 * restrict src;
144*b1e83836Smrg       GFC_REAL_17 result;
145*b1e83836Smrg       src = base;
146*b1e83836Smrg       {
147*b1e83836Smrg 
148*b1e83836Smrg #if defined (GFC_REAL_17_INFINITY)
149*b1e83836Smrg 	result = -GFC_REAL_17_INFINITY;
150*b1e83836Smrg #else
151*b1e83836Smrg 	result = -GFC_REAL_17_HUGE;
152*b1e83836Smrg #endif
153*b1e83836Smrg 	if (len <= 0)
154*b1e83836Smrg 	  *dest = -GFC_REAL_17_HUGE;
155*b1e83836Smrg 	else
156*b1e83836Smrg 	  {
157*b1e83836Smrg #if ! defined HAVE_BACK_ARG
158*b1e83836Smrg 	    for (n = 0; n < len; n++, src += delta)
159*b1e83836Smrg 	      {
160*b1e83836Smrg #endif
161*b1e83836Smrg 
162*b1e83836Smrg #if defined (GFC_REAL_17_QUIET_NAN)
163*b1e83836Smrg 		if (*src >= result)
164*b1e83836Smrg 		  break;
165*b1e83836Smrg 	      }
166*b1e83836Smrg 	    if (unlikely (n >= len))
167*b1e83836Smrg 	      result = GFC_REAL_17_QUIET_NAN;
168*b1e83836Smrg 	    else for (; n < len; n++, src += delta)
169*b1e83836Smrg 	      {
170*b1e83836Smrg #endif
171*b1e83836Smrg 		if (*src > result)
172*b1e83836Smrg 		  result = *src;
173*b1e83836Smrg 	      }
174*b1e83836Smrg 
175*b1e83836Smrg 	    *dest = result;
176*b1e83836Smrg 	  }
177*b1e83836Smrg       }
178*b1e83836Smrg       /* Advance to the next element.  */
179*b1e83836Smrg       count[0]++;
180*b1e83836Smrg       base += sstride[0];
181*b1e83836Smrg       dest += dstride[0];
182*b1e83836Smrg       n = 0;
183*b1e83836Smrg       while (count[n] == extent[n])
184*b1e83836Smrg 	{
185*b1e83836Smrg 	  /* When we get to the end of a dimension, reset it and increment
186*b1e83836Smrg 	     the next dimension.  */
187*b1e83836Smrg 	  count[n] = 0;
188*b1e83836Smrg 	  /* We could precalculate these products, but this is a less
189*b1e83836Smrg 	     frequently used path so probably not worth it.  */
190*b1e83836Smrg 	  base -= sstride[n] * extent[n];
191*b1e83836Smrg 	  dest -= dstride[n] * extent[n];
192*b1e83836Smrg 	  n++;
193*b1e83836Smrg 	  if (n >= rank)
194*b1e83836Smrg 	    {
195*b1e83836Smrg 	      /* Break out of the loop.  */
196*b1e83836Smrg 	      continue_loop = 0;
197*b1e83836Smrg 	      break;
198*b1e83836Smrg 	    }
199*b1e83836Smrg 	  else
200*b1e83836Smrg 	    {
201*b1e83836Smrg 	      count[n]++;
202*b1e83836Smrg 	      base += sstride[n];
203*b1e83836Smrg 	      dest += dstride[n];
204*b1e83836Smrg 	    }
205*b1e83836Smrg 	}
206*b1e83836Smrg     }
207*b1e83836Smrg }
208*b1e83836Smrg 
209*b1e83836Smrg 
210*b1e83836Smrg extern void mmaxval_r17 (gfc_array_r17 * const restrict,
211*b1e83836Smrg 	gfc_array_r17 * const restrict, const index_type * const restrict,
212*b1e83836Smrg 	gfc_array_l1 * const restrict);
213*b1e83836Smrg export_proto(mmaxval_r17);
214*b1e83836Smrg 
215*b1e83836Smrg void
mmaxval_r17(gfc_array_r17 * const restrict retarray,gfc_array_r17 * const restrict array,const index_type * const restrict pdim,gfc_array_l1 * const restrict mask)216*b1e83836Smrg mmaxval_r17 (gfc_array_r17 * const restrict retarray,
217*b1e83836Smrg 	gfc_array_r17 * const restrict array,
218*b1e83836Smrg 	const index_type * const restrict pdim,
219*b1e83836Smrg 	gfc_array_l1 * const restrict mask)
220*b1e83836Smrg {
221*b1e83836Smrg   index_type count[GFC_MAX_DIMENSIONS];
222*b1e83836Smrg   index_type extent[GFC_MAX_DIMENSIONS];
223*b1e83836Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
224*b1e83836Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
225*b1e83836Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
226*b1e83836Smrg   GFC_REAL_17 * restrict dest;
227*b1e83836Smrg   const GFC_REAL_17 * restrict base;
228*b1e83836Smrg   const GFC_LOGICAL_1 * restrict mbase;
229*b1e83836Smrg   index_type rank;
230*b1e83836Smrg   index_type dim;
231*b1e83836Smrg   index_type n;
232*b1e83836Smrg   index_type len;
233*b1e83836Smrg   index_type delta;
234*b1e83836Smrg   index_type mdelta;
235*b1e83836Smrg   int mask_kind;
236*b1e83836Smrg 
237*b1e83836Smrg   if (mask == NULL)
238*b1e83836Smrg     {
239*b1e83836Smrg #ifdef HAVE_BACK_ARG
240*b1e83836Smrg       maxval_r17 (retarray, array, pdim, back);
241*b1e83836Smrg #else
242*b1e83836Smrg       maxval_r17 (retarray, array, pdim);
243*b1e83836Smrg #endif
244*b1e83836Smrg       return;
245*b1e83836Smrg     }
246*b1e83836Smrg 
247*b1e83836Smrg   dim = (*pdim) - 1;
248*b1e83836Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
249*b1e83836Smrg 
250*b1e83836Smrg 
251*b1e83836Smrg   if (unlikely (dim < 0 || dim > rank))
252*b1e83836Smrg     {
253*b1e83836Smrg       runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
254*b1e83836Smrg  		     "is %ld, should be between 1 and %ld",
255*b1e83836Smrg 		     (long int) dim + 1, (long int) rank + 1);
256*b1e83836Smrg     }
257*b1e83836Smrg 
258*b1e83836Smrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
259*b1e83836Smrg   if (len <= 0)
260*b1e83836Smrg     return;
261*b1e83836Smrg 
262*b1e83836Smrg   mbase = mask->base_addr;
263*b1e83836Smrg 
264*b1e83836Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
265*b1e83836Smrg 
266*b1e83836Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
267*b1e83836Smrg #ifdef HAVE_GFC_LOGICAL_16
268*b1e83836Smrg       || mask_kind == 16
269*b1e83836Smrg #endif
270*b1e83836Smrg       )
271*b1e83836Smrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
272*b1e83836Smrg   else
273*b1e83836Smrg     runtime_error ("Funny sized logical array");
274*b1e83836Smrg 
275*b1e83836Smrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
276*b1e83836Smrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
277*b1e83836Smrg 
278*b1e83836Smrg   for (n = 0; n < dim; n++)
279*b1e83836Smrg     {
280*b1e83836Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
281*b1e83836Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
282*b1e83836Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
283*b1e83836Smrg 
284*b1e83836Smrg       if (extent[n] < 0)
285*b1e83836Smrg 	extent[n] = 0;
286*b1e83836Smrg 
287*b1e83836Smrg     }
288*b1e83836Smrg   for (n = dim; n < rank; n++)
289*b1e83836Smrg     {
290*b1e83836Smrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
291*b1e83836Smrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
292*b1e83836Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
293*b1e83836Smrg 
294*b1e83836Smrg       if (extent[n] < 0)
295*b1e83836Smrg 	extent[n] = 0;
296*b1e83836Smrg     }
297*b1e83836Smrg 
298*b1e83836Smrg   if (retarray->base_addr == NULL)
299*b1e83836Smrg     {
300*b1e83836Smrg       size_t alloc_size, str;
301*b1e83836Smrg 
302*b1e83836Smrg       for (n = 0; n < rank; n++)
303*b1e83836Smrg 	{
304*b1e83836Smrg 	  if (n == 0)
305*b1e83836Smrg 	    str = 1;
306*b1e83836Smrg 	  else
307*b1e83836Smrg 	    str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
308*b1e83836Smrg 
309*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
310*b1e83836Smrg 
311*b1e83836Smrg 	}
312*b1e83836Smrg 
313*b1e83836Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
314*b1e83836Smrg 
315*b1e83836Smrg       retarray->offset = 0;
316*b1e83836Smrg       retarray->dtype.rank = rank;
317*b1e83836Smrg 
318*b1e83836Smrg       if (alloc_size == 0)
319*b1e83836Smrg 	{
320*b1e83836Smrg 	  /* Make sure we have a zero-sized array.  */
321*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
322*b1e83836Smrg 	  return;
323*b1e83836Smrg 	}
324*b1e83836Smrg       else
325*b1e83836Smrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_REAL_17));
326*b1e83836Smrg 
327*b1e83836Smrg     }
328*b1e83836Smrg   else
329*b1e83836Smrg     {
330*b1e83836Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
331*b1e83836Smrg 	runtime_error ("rank of return array incorrect in MAXVAL intrinsic");
332*b1e83836Smrg 
333*b1e83836Smrg       if (unlikely (compile_options.bounds_check))
334*b1e83836Smrg 	{
335*b1e83836Smrg 	  bounds_ifunction_return ((array_t *) retarray, extent,
336*b1e83836Smrg 				   "return value", "MAXVAL");
337*b1e83836Smrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
338*b1e83836Smrg 	  			"MASK argument", "MAXVAL");
339*b1e83836Smrg 	}
340*b1e83836Smrg     }
341*b1e83836Smrg 
342*b1e83836Smrg   for (n = 0; n < rank; n++)
343*b1e83836Smrg     {
344*b1e83836Smrg       count[n] = 0;
345*b1e83836Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
346*b1e83836Smrg       if (extent[n] <= 0)
347*b1e83836Smrg 	return;
348*b1e83836Smrg     }
349*b1e83836Smrg 
350*b1e83836Smrg   dest = retarray->base_addr;
351*b1e83836Smrg   base = array->base_addr;
352*b1e83836Smrg 
353*b1e83836Smrg   while (base)
354*b1e83836Smrg     {
355*b1e83836Smrg       const GFC_REAL_17 * restrict src;
356*b1e83836Smrg       const GFC_LOGICAL_1 * restrict msrc;
357*b1e83836Smrg       GFC_REAL_17 result;
358*b1e83836Smrg       src = base;
359*b1e83836Smrg       msrc = mbase;
360*b1e83836Smrg       {
361*b1e83836Smrg 
362*b1e83836Smrg #if defined (GFC_REAL_17_INFINITY)
363*b1e83836Smrg 	result = -GFC_REAL_17_INFINITY;
364*b1e83836Smrg #else
365*b1e83836Smrg 	result = -GFC_REAL_17_HUGE;
366*b1e83836Smrg #endif
367*b1e83836Smrg #if defined (GFC_REAL_17_QUIET_NAN)
368*b1e83836Smrg 	int non_empty_p = 0;
369*b1e83836Smrg #endif
370*b1e83836Smrg 	for (n = 0; n < len; n++, src += delta, msrc += mdelta)
371*b1e83836Smrg 	  {
372*b1e83836Smrg 
373*b1e83836Smrg #if defined (GFC_REAL_17_INFINITY) || defined (GFC_REAL_17_QUIET_NAN)
374*b1e83836Smrg 		if (*msrc)
375*b1e83836Smrg 		  {
376*b1e83836Smrg #if defined (GFC_REAL_17_QUIET_NAN)
377*b1e83836Smrg 		    non_empty_p = 1;
378*b1e83836Smrg 		    if (*src >= result)
379*b1e83836Smrg #endif
380*b1e83836Smrg 		      break;
381*b1e83836Smrg 		  }
382*b1e83836Smrg 	      }
383*b1e83836Smrg 	    if (unlikely (n >= len))
384*b1e83836Smrg 	      {
385*b1e83836Smrg #if defined (GFC_REAL_17_QUIET_NAN)
386*b1e83836Smrg 		result = non_empty_p ? GFC_REAL_17_QUIET_NAN : -GFC_REAL_17_HUGE;
387*b1e83836Smrg #else
388*b1e83836Smrg 		result = -GFC_REAL_17_HUGE;
389*b1e83836Smrg #endif
390*b1e83836Smrg 	      }
391*b1e83836Smrg 	    else for (; n < len; n++, src += delta, msrc += mdelta)
392*b1e83836Smrg 	      {
393*b1e83836Smrg #endif
394*b1e83836Smrg 		if (*msrc && *src > result)
395*b1e83836Smrg 		  result = *src;
396*b1e83836Smrg 	  }
397*b1e83836Smrg 	*dest = result;
398*b1e83836Smrg       }
399*b1e83836Smrg       /* Advance to the next element.  */
400*b1e83836Smrg       count[0]++;
401*b1e83836Smrg       base += sstride[0];
402*b1e83836Smrg       mbase += mstride[0];
403*b1e83836Smrg       dest += dstride[0];
404*b1e83836Smrg       n = 0;
405*b1e83836Smrg       while (count[n] == extent[n])
406*b1e83836Smrg 	{
407*b1e83836Smrg 	  /* When we get to the end of a dimension, reset it and increment
408*b1e83836Smrg 	     the next dimension.  */
409*b1e83836Smrg 	  count[n] = 0;
410*b1e83836Smrg 	  /* We could precalculate these products, but this is a less
411*b1e83836Smrg 	     frequently used path so probably not worth it.  */
412*b1e83836Smrg 	  base -= sstride[n] * extent[n];
413*b1e83836Smrg 	  mbase -= mstride[n] * extent[n];
414*b1e83836Smrg 	  dest -= dstride[n] * extent[n];
415*b1e83836Smrg 	  n++;
416*b1e83836Smrg 	  if (n >= rank)
417*b1e83836Smrg 	    {
418*b1e83836Smrg 	      /* Break out of the loop.  */
419*b1e83836Smrg 	      base = NULL;
420*b1e83836Smrg 	      break;
421*b1e83836Smrg 	    }
422*b1e83836Smrg 	  else
423*b1e83836Smrg 	    {
424*b1e83836Smrg 	      count[n]++;
425*b1e83836Smrg 	      base += sstride[n];
426*b1e83836Smrg 	      mbase += mstride[n];
427*b1e83836Smrg 	      dest += dstride[n];
428*b1e83836Smrg 	    }
429*b1e83836Smrg 	}
430*b1e83836Smrg     }
431*b1e83836Smrg }
432*b1e83836Smrg 
433*b1e83836Smrg 
434*b1e83836Smrg extern void smaxval_r17 (gfc_array_r17 * const restrict,
435*b1e83836Smrg 	gfc_array_r17 * const restrict, const index_type * const restrict,
436*b1e83836Smrg 	GFC_LOGICAL_4 *);
437*b1e83836Smrg export_proto(smaxval_r17);
438*b1e83836Smrg 
439*b1e83836Smrg void
smaxval_r17(gfc_array_r17 * const restrict retarray,gfc_array_r17 * const restrict array,const index_type * const restrict pdim,GFC_LOGICAL_4 * mask)440*b1e83836Smrg smaxval_r17 (gfc_array_r17 * const restrict retarray,
441*b1e83836Smrg 	gfc_array_r17 * const restrict array,
442*b1e83836Smrg 	const index_type * const restrict pdim,
443*b1e83836Smrg 	GFC_LOGICAL_4 * mask)
444*b1e83836Smrg {
445*b1e83836Smrg   index_type count[GFC_MAX_DIMENSIONS];
446*b1e83836Smrg   index_type extent[GFC_MAX_DIMENSIONS];
447*b1e83836Smrg   index_type dstride[GFC_MAX_DIMENSIONS];
448*b1e83836Smrg   GFC_REAL_17 * restrict dest;
449*b1e83836Smrg   index_type rank;
450*b1e83836Smrg   index_type n;
451*b1e83836Smrg   index_type dim;
452*b1e83836Smrg 
453*b1e83836Smrg 
454*b1e83836Smrg   if (mask == NULL || *mask)
455*b1e83836Smrg     {
456*b1e83836Smrg #ifdef HAVE_BACK_ARG
457*b1e83836Smrg       maxval_r17 (retarray, array, pdim, back);
458*b1e83836Smrg #else
459*b1e83836Smrg       maxval_r17 (retarray, array, pdim);
460*b1e83836Smrg #endif
461*b1e83836Smrg       return;
462*b1e83836Smrg     }
463*b1e83836Smrg   /* Make dim zero based to avoid confusion.  */
464*b1e83836Smrg   dim = (*pdim) - 1;
465*b1e83836Smrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
466*b1e83836Smrg 
467*b1e83836Smrg   if (unlikely (dim < 0 || dim > rank))
468*b1e83836Smrg     {
469*b1e83836Smrg       runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
470*b1e83836Smrg  		     "is %ld, should be between 1 and %ld",
471*b1e83836Smrg 		     (long int) dim + 1, (long int) rank + 1);
472*b1e83836Smrg     }
473*b1e83836Smrg 
474*b1e83836Smrg   for (n = 0; n < dim; n++)
475*b1e83836Smrg     {
476*b1e83836Smrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
477*b1e83836Smrg 
478*b1e83836Smrg       if (extent[n] <= 0)
479*b1e83836Smrg 	extent[n] = 0;
480*b1e83836Smrg     }
481*b1e83836Smrg 
482*b1e83836Smrg   for (n = dim; n < rank; n++)
483*b1e83836Smrg     {
484*b1e83836Smrg       extent[n] =
485*b1e83836Smrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
486*b1e83836Smrg 
487*b1e83836Smrg       if (extent[n] <= 0)
488*b1e83836Smrg 	extent[n] = 0;
489*b1e83836Smrg     }
490*b1e83836Smrg 
491*b1e83836Smrg   if (retarray->base_addr == NULL)
492*b1e83836Smrg     {
493*b1e83836Smrg       size_t alloc_size, str;
494*b1e83836Smrg 
495*b1e83836Smrg       for (n = 0; n < rank; n++)
496*b1e83836Smrg 	{
497*b1e83836Smrg 	  if (n == 0)
498*b1e83836Smrg 	    str = 1;
499*b1e83836Smrg 	  else
500*b1e83836Smrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
501*b1e83836Smrg 
502*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
503*b1e83836Smrg 
504*b1e83836Smrg 	}
505*b1e83836Smrg 
506*b1e83836Smrg       retarray->offset = 0;
507*b1e83836Smrg       retarray->dtype.rank = rank;
508*b1e83836Smrg 
509*b1e83836Smrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
510*b1e83836Smrg 
511*b1e83836Smrg       if (alloc_size == 0)
512*b1e83836Smrg 	{
513*b1e83836Smrg 	  /* Make sure we have a zero-sized array.  */
514*b1e83836Smrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
515*b1e83836Smrg 	  return;
516*b1e83836Smrg 	}
517*b1e83836Smrg       else
518*b1e83836Smrg 	retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_REAL_17));
519*b1e83836Smrg     }
520*b1e83836Smrg   else
521*b1e83836Smrg     {
522*b1e83836Smrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
523*b1e83836Smrg 	runtime_error ("rank of return array incorrect in"
524*b1e83836Smrg 		       " MAXVAL intrinsic: is %ld, should be %ld",
525*b1e83836Smrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
526*b1e83836Smrg 		       (long int) rank);
527*b1e83836Smrg 
528*b1e83836Smrg       if (unlikely (compile_options.bounds_check))
529*b1e83836Smrg 	{
530*b1e83836Smrg 	  for (n=0; n < rank; n++)
531*b1e83836Smrg 	    {
532*b1e83836Smrg 	      index_type ret_extent;
533*b1e83836Smrg 
534*b1e83836Smrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
535*b1e83836Smrg 	      if (extent[n] != ret_extent)
536*b1e83836Smrg 		runtime_error ("Incorrect extent in return value of"
537*b1e83836Smrg 			       " MAXVAL intrinsic in dimension %ld:"
538*b1e83836Smrg 			       " is %ld, should be %ld", (long int) n + 1,
539*b1e83836Smrg 			       (long int) ret_extent, (long int) extent[n]);
540*b1e83836Smrg 	    }
541*b1e83836Smrg 	}
542*b1e83836Smrg     }
543*b1e83836Smrg 
544*b1e83836Smrg   for (n = 0; n < rank; n++)
545*b1e83836Smrg     {
546*b1e83836Smrg       count[n] = 0;
547*b1e83836Smrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
548*b1e83836Smrg     }
549*b1e83836Smrg 
550*b1e83836Smrg   dest = retarray->base_addr;
551*b1e83836Smrg 
552*b1e83836Smrg   while(1)
553*b1e83836Smrg     {
554*b1e83836Smrg       *dest = -GFC_REAL_17_HUGE;
555*b1e83836Smrg       count[0]++;
556*b1e83836Smrg       dest += dstride[0];
557*b1e83836Smrg       n = 0;
558*b1e83836Smrg       while (count[n] == extent[n])
559*b1e83836Smrg 	{
560*b1e83836Smrg 	  /* When we get to the end of a dimension, reset it and increment
561*b1e83836Smrg 	     the next dimension.  */
562*b1e83836Smrg 	  count[n] = 0;
563*b1e83836Smrg 	  /* We could precalculate these products, but this is a less
564*b1e83836Smrg 	     frequently used path so probably not worth it.  */
565*b1e83836Smrg 	  dest -= dstride[n] * extent[n];
566*b1e83836Smrg 	  n++;
567*b1e83836Smrg 	  if (n >= rank)
568*b1e83836Smrg 	    return;
569*b1e83836Smrg 	  else
570*b1e83836Smrg 	    {
571*b1e83836Smrg 	      count[n]++;
572*b1e83836Smrg 	      dest += dstride[n];
573*b1e83836Smrg 	    }
574*b1e83836Smrg       	}
575*b1e83836Smrg     }
576*b1e83836Smrg }
577*b1e83836Smrg 
578*b1e83836Smrg #endif
579