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