Home | History | Annotate | Line # | Download | only in generated
      1      1.1  mrg /* Implementation of the MINLOC intrinsic
      2  1.1.1.4  mrg    Copyright (C) 2002-2024 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 #include <assert.h>
     28      1.1  mrg 
     29      1.1  mrg 
     30      1.1  mrg #if defined (HAVE_GFC_REAL_10) && defined (HAVE_GFC_INTEGER_16)
     31      1.1  mrg 
     32      1.1  mrg #define HAVE_BACK_ARG 1
     33      1.1  mrg 
     34      1.1  mrg 
     35      1.1  mrg extern void minloc1_16_r10 (gfc_array_i16 * const restrict,
     36      1.1  mrg 	gfc_array_r10 * const restrict, const index_type * const restrict, GFC_LOGICAL_4 back);
     37      1.1  mrg export_proto(minloc1_16_r10);
     38      1.1  mrg 
     39      1.1  mrg void
     40      1.1  mrg minloc1_16_r10 (gfc_array_i16 * const restrict retarray,
     41      1.1  mrg 	gfc_array_r10 * const restrict array,
     42      1.1  mrg 	const index_type * const restrict pdim, GFC_LOGICAL_4 back)
     43      1.1  mrg {
     44      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     45      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     46      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     47      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
     48      1.1  mrg   const GFC_REAL_10 * restrict base;
     49      1.1  mrg   GFC_INTEGER_16 * restrict dest;
     50      1.1  mrg   index_type rank;
     51      1.1  mrg   index_type n;
     52      1.1  mrg   index_type len;
     53      1.1  mrg   index_type delta;
     54      1.1  mrg   index_type dim;
     55      1.1  mrg   int continue_loop;
     56      1.1  mrg 
     57      1.1  mrg   /* Make dim zero based to avoid confusion.  */
     58      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
     59      1.1  mrg   dim = (*pdim) - 1;
     60      1.1  mrg 
     61      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
     62      1.1  mrg     {
     63      1.1  mrg       runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
     64      1.1  mrg  		     "is %ld, should be between 1 and %ld",
     65      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
     66      1.1  mrg     }
     67      1.1  mrg 
     68      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
     69      1.1  mrg   if (len < 0)
     70      1.1  mrg     len = 0;
     71      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
     72      1.1  mrg 
     73      1.1  mrg   for (n = 0; n < dim; n++)
     74      1.1  mrg     {
     75      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
     76      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
     77      1.1  mrg 
     78      1.1  mrg       if (extent[n] < 0)
     79      1.1  mrg 	extent[n] = 0;
     80      1.1  mrg     }
     81      1.1  mrg   for (n = dim; n < rank; n++)
     82      1.1  mrg     {
     83      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
     84      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
     85      1.1  mrg 
     86      1.1  mrg       if (extent[n] < 0)
     87      1.1  mrg 	extent[n] = 0;
     88      1.1  mrg     }
     89      1.1  mrg 
     90      1.1  mrg   if (retarray->base_addr == NULL)
     91      1.1  mrg     {
     92      1.1  mrg       size_t alloc_size, str;
     93      1.1  mrg 
     94      1.1  mrg       for (n = 0; n < rank; n++)
     95      1.1  mrg 	{
     96      1.1  mrg 	  if (n == 0)
     97      1.1  mrg 	    str = 1;
     98      1.1  mrg 	  else
     99      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    100      1.1  mrg 
    101      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    102      1.1  mrg 
    103      1.1  mrg 	}
    104      1.1  mrg 
    105      1.1  mrg       retarray->offset = 0;
    106      1.1  mrg       retarray->dtype.rank = rank;
    107      1.1  mrg 
    108      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    109      1.1  mrg 
    110      1.1  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
    111      1.1  mrg       if (alloc_size == 0)
    112  1.1.1.4  mrg 	return;
    113      1.1  mrg     }
    114      1.1  mrg   else
    115      1.1  mrg     {
    116      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    117      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    118      1.1  mrg 		       " MINLOC intrinsic: is %ld, should be %ld",
    119      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    120      1.1  mrg 		       (long int) rank);
    121      1.1  mrg 
    122      1.1  mrg       if (unlikely (compile_options.bounds_check))
    123      1.1  mrg 	bounds_ifunction_return ((array_t *) retarray, extent,
    124      1.1  mrg 				 "return value", "MINLOC");
    125      1.1  mrg     }
    126      1.1  mrg 
    127      1.1  mrg   for (n = 0; n < rank; n++)
    128      1.1  mrg     {
    129      1.1  mrg       count[n] = 0;
    130      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    131      1.1  mrg       if (extent[n] <= 0)
    132      1.1  mrg 	return;
    133      1.1  mrg     }
    134      1.1  mrg 
    135      1.1  mrg   base = array->base_addr;
    136      1.1  mrg   dest = retarray->base_addr;
    137      1.1  mrg 
    138      1.1  mrg   continue_loop = 1;
    139      1.1  mrg   while (continue_loop)
    140      1.1  mrg     {
    141      1.1  mrg       const GFC_REAL_10 * restrict src;
    142      1.1  mrg       GFC_INTEGER_16 result;
    143      1.1  mrg       src = base;
    144      1.1  mrg       {
    145      1.1  mrg 
    146      1.1  mrg 	GFC_REAL_10 minval;
    147      1.1  mrg #if defined (GFC_REAL_10_INFINITY)
    148      1.1  mrg 	minval = GFC_REAL_10_INFINITY;
    149      1.1  mrg #else
    150      1.1  mrg 	minval = GFC_REAL_10_HUGE;
    151      1.1  mrg #endif
    152      1.1  mrg 	result = 1;
    153      1.1  mrg 	if (len <= 0)
    154      1.1  mrg 	  *dest = 0;
    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_10_QUIET_NAN)
    163      1.1  mrg      	   for (n = 0; n < len; n++, src += delta)
    164      1.1  mrg 	     {
    165      1.1  mrg 		if (*src <= minval)
    166      1.1  mrg 		  {
    167      1.1  mrg 		    minval = *src;
    168      1.1  mrg 		    result = (GFC_INTEGER_16)n + 1;
    169      1.1  mrg 		    break;
    170      1.1  mrg 		  }
    171      1.1  mrg 	      }
    172      1.1  mrg #else
    173      1.1  mrg 	    n = 0;
    174      1.1  mrg #endif
    175      1.1  mrg 	    if (back)
    176      1.1  mrg 	      for (; n < len; n++, src += delta)
    177      1.1  mrg 	        {
    178      1.1  mrg 		  if (unlikely (*src <= minval))
    179      1.1  mrg 		    {
    180      1.1  mrg 		      minval = *src;
    181      1.1  mrg 		      result = (GFC_INTEGER_16)n + 1;
    182      1.1  mrg 		    }
    183      1.1  mrg 		}
    184      1.1  mrg 	    else
    185      1.1  mrg 	      for (; n < len; n++, src += delta)
    186      1.1  mrg 	        {
    187      1.1  mrg 		  if (unlikely (*src < minval))
    188      1.1  mrg 		    {
    189      1.1  mrg 		      minval = *src;
    190      1.1  mrg 		      result = (GFC_INTEGER_16) n + 1;
    191      1.1  mrg 		    }
    192      1.1  mrg 	      }
    193      1.1  mrg 
    194      1.1  mrg 	    *dest = result;
    195      1.1  mrg 	  }
    196      1.1  mrg       }
    197      1.1  mrg       /* Advance to the next element.  */
    198      1.1  mrg       count[0]++;
    199      1.1  mrg       base += sstride[0];
    200      1.1  mrg       dest += dstride[0];
    201      1.1  mrg       n = 0;
    202      1.1  mrg       while (count[n] == extent[n])
    203      1.1  mrg 	{
    204      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    205      1.1  mrg 	     the next dimension.  */
    206      1.1  mrg 	  count[n] = 0;
    207      1.1  mrg 	  /* We could precalculate these products, but this is a less
    208      1.1  mrg 	     frequently used path so probably not worth it.  */
    209      1.1  mrg 	  base -= sstride[n] * extent[n];
    210      1.1  mrg 	  dest -= dstride[n] * extent[n];
    211      1.1  mrg 	  n++;
    212      1.1  mrg 	  if (n >= rank)
    213      1.1  mrg 	    {
    214      1.1  mrg 	      /* Break out of the loop.  */
    215      1.1  mrg 	      continue_loop = 0;
    216      1.1  mrg 	      break;
    217      1.1  mrg 	    }
    218      1.1  mrg 	  else
    219      1.1  mrg 	    {
    220      1.1  mrg 	      count[n]++;
    221      1.1  mrg 	      base += sstride[n];
    222      1.1  mrg 	      dest += dstride[n];
    223      1.1  mrg 	    }
    224      1.1  mrg 	}
    225      1.1  mrg     }
    226      1.1  mrg }
    227      1.1  mrg 
    228      1.1  mrg 
    229      1.1  mrg extern void mminloc1_16_r10 (gfc_array_i16 * const restrict,
    230      1.1  mrg 	gfc_array_r10 * const restrict, const index_type * const restrict,
    231      1.1  mrg 	gfc_array_l1 * const restrict, GFC_LOGICAL_4 back);
    232      1.1  mrg export_proto(mminloc1_16_r10);
    233      1.1  mrg 
    234      1.1  mrg void
    235      1.1  mrg mminloc1_16_r10 (gfc_array_i16 * const restrict retarray,
    236      1.1  mrg 	gfc_array_r10 * const restrict array,
    237      1.1  mrg 	const index_type * const restrict pdim,
    238      1.1  mrg 	gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back)
    239      1.1  mrg {
    240      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    241      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    242      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
    243      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    244      1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
    245      1.1  mrg   GFC_INTEGER_16 * restrict dest;
    246      1.1  mrg   const GFC_REAL_10 * restrict base;
    247      1.1  mrg   const GFC_LOGICAL_1 * restrict mbase;
    248      1.1  mrg   index_type rank;
    249      1.1  mrg   index_type dim;
    250      1.1  mrg   index_type n;
    251      1.1  mrg   index_type len;
    252      1.1  mrg   index_type delta;
    253      1.1  mrg   index_type mdelta;
    254      1.1  mrg   int mask_kind;
    255      1.1  mrg 
    256      1.1  mrg   if (mask == NULL)
    257      1.1  mrg     {
    258      1.1  mrg #ifdef HAVE_BACK_ARG
    259      1.1  mrg       minloc1_16_r10 (retarray, array, pdim, back);
    260      1.1  mrg #else
    261      1.1  mrg       minloc1_16_r10 (retarray, array, pdim);
    262      1.1  mrg #endif
    263      1.1  mrg       return;
    264      1.1  mrg     }
    265      1.1  mrg 
    266      1.1  mrg   dim = (*pdim) - 1;
    267      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    268      1.1  mrg 
    269      1.1  mrg 
    270      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    271      1.1  mrg     {
    272      1.1  mrg       runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
    273      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    274      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    275      1.1  mrg     }
    276      1.1  mrg 
    277      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
    278  1.1.1.4  mrg   if (len < 0)
    279  1.1.1.4  mrg     len = 0;
    280      1.1  mrg 
    281      1.1  mrg   mbase = mask->base_addr;
    282      1.1  mrg 
    283      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    284      1.1  mrg 
    285      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    286      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    287      1.1  mrg       || mask_kind == 16
    288      1.1  mrg #endif
    289      1.1  mrg       )
    290      1.1  mrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    291      1.1  mrg   else
    292      1.1  mrg     runtime_error ("Funny sized logical array");
    293      1.1  mrg 
    294      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
    295      1.1  mrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
    296      1.1  mrg 
    297      1.1  mrg   for (n = 0; n < dim; n++)
    298      1.1  mrg     {
    299      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
    300      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    301      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    302      1.1  mrg 
    303      1.1  mrg       if (extent[n] < 0)
    304      1.1  mrg 	extent[n] = 0;
    305      1.1  mrg 
    306      1.1  mrg     }
    307      1.1  mrg   for (n = dim; n < rank; n++)
    308      1.1  mrg     {
    309      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
    310      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
    311      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
    312      1.1  mrg 
    313      1.1  mrg       if (extent[n] < 0)
    314      1.1  mrg 	extent[n] = 0;
    315      1.1  mrg     }
    316      1.1  mrg 
    317      1.1  mrg   if (retarray->base_addr == NULL)
    318      1.1  mrg     {
    319      1.1  mrg       size_t alloc_size, str;
    320      1.1  mrg 
    321      1.1  mrg       for (n = 0; n < rank; n++)
    322      1.1  mrg 	{
    323      1.1  mrg 	  if (n == 0)
    324      1.1  mrg 	    str = 1;
    325      1.1  mrg 	  else
    326      1.1  mrg 	    str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    327      1.1  mrg 
    328      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    329      1.1  mrg 
    330      1.1  mrg 	}
    331      1.1  mrg 
    332      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    333      1.1  mrg 
    334      1.1  mrg       retarray->offset = 0;
    335      1.1  mrg       retarray->dtype.rank = rank;
    336      1.1  mrg 
    337  1.1.1.4  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
    338      1.1  mrg       if (alloc_size == 0)
    339  1.1.1.4  mrg 	return;
    340      1.1  mrg     }
    341      1.1  mrg   else
    342      1.1  mrg     {
    343      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    344      1.1  mrg 	runtime_error ("rank of return array incorrect in MINLOC intrinsic");
    345      1.1  mrg 
    346      1.1  mrg       if (unlikely (compile_options.bounds_check))
    347      1.1  mrg 	{
    348      1.1  mrg 	  bounds_ifunction_return ((array_t *) retarray, extent,
    349      1.1  mrg 				   "return value", "MINLOC");
    350      1.1  mrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
    351      1.1  mrg 	  			"MASK argument", "MINLOC");
    352      1.1  mrg 	}
    353      1.1  mrg     }
    354      1.1  mrg 
    355      1.1  mrg   for (n = 0; n < rank; n++)
    356      1.1  mrg     {
    357      1.1  mrg       count[n] = 0;
    358      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    359      1.1  mrg       if (extent[n] <= 0)
    360      1.1  mrg 	return;
    361      1.1  mrg     }
    362      1.1  mrg 
    363      1.1  mrg   dest = retarray->base_addr;
    364      1.1  mrg   base = array->base_addr;
    365      1.1  mrg 
    366      1.1  mrg   while (base)
    367      1.1  mrg     {
    368      1.1  mrg       const GFC_REAL_10 * restrict src;
    369      1.1  mrg       const GFC_LOGICAL_1 * restrict msrc;
    370      1.1  mrg       GFC_INTEGER_16 result;
    371      1.1  mrg       src = base;
    372      1.1  mrg       msrc = mbase;
    373      1.1  mrg       {
    374      1.1  mrg 
    375      1.1  mrg 	GFC_REAL_10 minval;
    376      1.1  mrg #if defined (GFC_REAL_10_INFINITY)
    377      1.1  mrg 	minval = GFC_REAL_10_INFINITY;
    378      1.1  mrg #else
    379      1.1  mrg 	minval = GFC_REAL_10_HUGE;
    380      1.1  mrg #endif
    381      1.1  mrg #if defined (GFC_REAL_10_QUIET_NAN)
    382      1.1  mrg 	GFC_INTEGER_16 result2 = 0;
    383      1.1  mrg #endif
    384      1.1  mrg 	result = 0;
    385      1.1  mrg 	for (n = 0; n < len; n++, src += delta, msrc += mdelta)
    386      1.1  mrg 	  {
    387      1.1  mrg 
    388      1.1  mrg 		if (*msrc)
    389      1.1  mrg 		  {
    390      1.1  mrg #if defined (GFC_REAL_10_QUIET_NAN)
    391      1.1  mrg 		    if (!result2)
    392      1.1  mrg 		      result2 = (GFC_INTEGER_16)n + 1;
    393      1.1  mrg 		    if (*src <= minval)
    394      1.1  mrg #endif
    395      1.1  mrg 		      {
    396      1.1  mrg 			minval = *src;
    397      1.1  mrg 			result = (GFC_INTEGER_16)n + 1;
    398      1.1  mrg 			break;
    399      1.1  mrg 		      }
    400      1.1  mrg 		  }
    401      1.1  mrg 	      }
    402      1.1  mrg #if defined (GFC_REAL_10_QUIET_NAN)
    403      1.1  mrg 	    if (unlikely (n >= len))
    404      1.1  mrg 	      result = result2;
    405      1.1  mrg 	    else
    406      1.1  mrg #endif
    407      1.1  mrg 	    if (back)
    408      1.1  mrg 	      for (; n < len; n++, src += delta, msrc += mdelta)
    409      1.1  mrg 	      	{
    410      1.1  mrg 		  if (*msrc && unlikely (*src <= minval))
    411      1.1  mrg 		    {
    412      1.1  mrg 		      minval = *src;
    413      1.1  mrg 		      result = (GFC_INTEGER_16)n + 1;
    414      1.1  mrg 		    }
    415      1.1  mrg 		}
    416      1.1  mrg 	      else
    417      1.1  mrg 	        for (; n < len; n++, src += delta, msrc += mdelta)
    418      1.1  mrg 		  {
    419      1.1  mrg 		    if (*msrc && unlikely (*src < minval))
    420      1.1  mrg 		      {
    421      1.1  mrg 		        minval = *src;
    422      1.1  mrg 			result = (GFC_INTEGER_16) n + 1;
    423      1.1  mrg 		      }
    424      1.1  mrg 	  }
    425      1.1  mrg 	*dest = result;
    426      1.1  mrg       }
    427      1.1  mrg       /* Advance to the next element.  */
    428      1.1  mrg       count[0]++;
    429      1.1  mrg       base += sstride[0];
    430      1.1  mrg       mbase += mstride[0];
    431      1.1  mrg       dest += dstride[0];
    432      1.1  mrg       n = 0;
    433      1.1  mrg       while (count[n] == extent[n])
    434      1.1  mrg 	{
    435      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    436      1.1  mrg 	     the next dimension.  */
    437      1.1  mrg 	  count[n] = 0;
    438      1.1  mrg 	  /* We could precalculate these products, but this is a less
    439      1.1  mrg 	     frequently used path so probably not worth it.  */
    440      1.1  mrg 	  base -= sstride[n] * extent[n];
    441      1.1  mrg 	  mbase -= mstride[n] * extent[n];
    442      1.1  mrg 	  dest -= dstride[n] * extent[n];
    443      1.1  mrg 	  n++;
    444      1.1  mrg 	  if (n >= rank)
    445      1.1  mrg 	    {
    446      1.1  mrg 	      /* Break out of the loop.  */
    447      1.1  mrg 	      base = NULL;
    448      1.1  mrg 	      break;
    449      1.1  mrg 	    }
    450      1.1  mrg 	  else
    451      1.1  mrg 	    {
    452      1.1  mrg 	      count[n]++;
    453      1.1  mrg 	      base += sstride[n];
    454      1.1  mrg 	      mbase += mstride[n];
    455      1.1  mrg 	      dest += dstride[n];
    456      1.1  mrg 	    }
    457      1.1  mrg 	}
    458      1.1  mrg     }
    459      1.1  mrg }
    460      1.1  mrg 
    461      1.1  mrg 
    462      1.1  mrg extern void sminloc1_16_r10 (gfc_array_i16 * const restrict,
    463      1.1  mrg 	gfc_array_r10 * const restrict, const index_type * const restrict,
    464      1.1  mrg 	GFC_LOGICAL_4 *, GFC_LOGICAL_4 back);
    465      1.1  mrg export_proto(sminloc1_16_r10);
    466      1.1  mrg 
    467      1.1  mrg void
    468      1.1  mrg sminloc1_16_r10 (gfc_array_i16 * const restrict retarray,
    469      1.1  mrg 	gfc_array_r10 * const restrict array,
    470      1.1  mrg 	const index_type * const restrict pdim,
    471      1.1  mrg 	GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
    472      1.1  mrg {
    473      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    474      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    475      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    476      1.1  mrg   GFC_INTEGER_16 * restrict dest;
    477      1.1  mrg   index_type rank;
    478      1.1  mrg   index_type n;
    479      1.1  mrg   index_type dim;
    480      1.1  mrg 
    481      1.1  mrg 
    482      1.1  mrg   if (mask == NULL || *mask)
    483      1.1  mrg     {
    484      1.1  mrg #ifdef HAVE_BACK_ARG
    485      1.1  mrg       minloc1_16_r10 (retarray, array, pdim, back);
    486      1.1  mrg #else
    487      1.1  mrg       minloc1_16_r10 (retarray, array, pdim);
    488      1.1  mrg #endif
    489      1.1  mrg       return;
    490      1.1  mrg     }
    491      1.1  mrg   /* Make dim zero based to avoid confusion.  */
    492      1.1  mrg   dim = (*pdim) - 1;
    493      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    494      1.1  mrg 
    495      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    496      1.1  mrg     {
    497      1.1  mrg       runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
    498      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    499      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    500      1.1  mrg     }
    501      1.1  mrg 
    502      1.1  mrg   for (n = 0; n < dim; n++)
    503      1.1  mrg     {
    504      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    505      1.1  mrg 
    506      1.1  mrg       if (extent[n] <= 0)
    507      1.1  mrg 	extent[n] = 0;
    508      1.1  mrg     }
    509      1.1  mrg 
    510      1.1  mrg   for (n = dim; n < rank; n++)
    511      1.1  mrg     {
    512      1.1  mrg       extent[n] =
    513      1.1  mrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
    514      1.1  mrg 
    515      1.1  mrg       if (extent[n] <= 0)
    516      1.1  mrg 	extent[n] = 0;
    517      1.1  mrg     }
    518      1.1  mrg 
    519      1.1  mrg   if (retarray->base_addr == NULL)
    520      1.1  mrg     {
    521      1.1  mrg       size_t alloc_size, str;
    522      1.1  mrg 
    523      1.1  mrg       for (n = 0; n < rank; n++)
    524      1.1  mrg 	{
    525      1.1  mrg 	  if (n == 0)
    526      1.1  mrg 	    str = 1;
    527      1.1  mrg 	  else
    528      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    529      1.1  mrg 
    530      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    531      1.1  mrg 
    532      1.1  mrg 	}
    533      1.1  mrg 
    534      1.1  mrg       retarray->offset = 0;
    535      1.1  mrg       retarray->dtype.rank = rank;
    536      1.1  mrg 
    537      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    538      1.1  mrg 
    539  1.1.1.4  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
    540      1.1  mrg       if (alloc_size == 0)
    541  1.1.1.4  mrg 	return;
    542      1.1  mrg     }
    543      1.1  mrg   else
    544      1.1  mrg     {
    545      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    546      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    547      1.1  mrg 		       " MINLOC intrinsic: is %ld, should be %ld",
    548      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    549      1.1  mrg 		       (long int) rank);
    550      1.1  mrg 
    551      1.1  mrg       if (unlikely (compile_options.bounds_check))
    552      1.1  mrg 	{
    553      1.1  mrg 	  for (n=0; n < rank; n++)
    554      1.1  mrg 	    {
    555      1.1  mrg 	      index_type ret_extent;
    556      1.1  mrg 
    557      1.1  mrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
    558      1.1  mrg 	      if (extent[n] != ret_extent)
    559      1.1  mrg 		runtime_error ("Incorrect extent in return value of"
    560      1.1  mrg 			       " MINLOC intrinsic in dimension %ld:"
    561      1.1  mrg 			       " is %ld, should be %ld", (long int) n + 1,
    562      1.1  mrg 			       (long int) ret_extent, (long int) extent[n]);
    563      1.1  mrg 	    }
    564      1.1  mrg 	}
    565      1.1  mrg     }
    566      1.1  mrg 
    567      1.1  mrg   for (n = 0; n < rank; n++)
    568      1.1  mrg     {
    569      1.1  mrg       count[n] = 0;
    570      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    571      1.1  mrg     }
    572      1.1  mrg 
    573      1.1  mrg   dest = retarray->base_addr;
    574      1.1  mrg 
    575      1.1  mrg   while(1)
    576      1.1  mrg     {
    577      1.1  mrg       *dest = 0;
    578      1.1  mrg       count[0]++;
    579      1.1  mrg       dest += dstride[0];
    580      1.1  mrg       n = 0;
    581      1.1  mrg       while (count[n] == extent[n])
    582      1.1  mrg 	{
    583      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    584      1.1  mrg 	     the next dimension.  */
    585      1.1  mrg 	  count[n] = 0;
    586      1.1  mrg 	  /* We could precalculate these products, but this is a less
    587      1.1  mrg 	     frequently used path so probably not worth it.  */
    588      1.1  mrg 	  dest -= dstride[n] * extent[n];
    589      1.1  mrg 	  n++;
    590      1.1  mrg 	  if (n >= rank)
    591      1.1  mrg 	    return;
    592      1.1  mrg 	  else
    593      1.1  mrg 	    {
    594      1.1  mrg 	      count[n]++;
    595      1.1  mrg 	      dest += dstride[n];
    596      1.1  mrg 	    }
    597      1.1  mrg       	}
    598      1.1  mrg     }
    599      1.1  mrg }
    600      1.1  mrg 
    601      1.1  mrg #endif
    602