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