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