Home | History | Annotate | Line # | Download | only in generated
      1      1.1  mrg /* Implementation of the FINDLOC intrinsic
      2  1.1.1.3  mrg    Copyright (C) 2018-2022 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Thomas Knig <tk (at) tkoenig.net>
      4      1.1  mrg 
      5      1.1  mrg This file is part of the GNU Fortran 95 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 #if defined (HAVE_GFC_UINTEGER_4)
     30      1.1  mrg extern void findloc1_s4 (gfc_array_index_type * const restrict retarray,
     31      1.1  mrg 		         gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
     32      1.1  mrg 			 const index_type * restrict pdim, GFC_LOGICAL_4 back,
     33      1.1  mrg 			 gfc_charlen_type len_array, gfc_charlen_type len_value);
     34      1.1  mrg export_proto(findloc1_s4);
     35      1.1  mrg 
     36      1.1  mrg extern void
     37      1.1  mrg findloc1_s4 (gfc_array_index_type * const restrict retarray,
     38      1.1  mrg 	    gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
     39      1.1  mrg 	    const index_type * restrict pdim, GFC_LOGICAL_4 back,
     40      1.1  mrg 	    gfc_charlen_type len_array, gfc_charlen_type len_value)
     41      1.1  mrg {
     42      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     43      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     44      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     45      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
     46      1.1  mrg   const GFC_UINTEGER_4 * restrict base;
     47      1.1  mrg   index_type * restrict dest;
     48      1.1  mrg   index_type rank;
     49      1.1  mrg   index_type n;
     50      1.1  mrg   index_type len;
     51      1.1  mrg   index_type delta;
     52      1.1  mrg   index_type dim;
     53      1.1  mrg   int continue_loop;
     54      1.1  mrg 
     55      1.1  mrg   /* Make dim zero based to avoid confusion.  */
     56      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
     57      1.1  mrg   dim = (*pdim) - 1;
     58      1.1  mrg 
     59      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
     60      1.1  mrg     {
     61      1.1  mrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
     62      1.1  mrg  		     "is %ld, should be between 1 and %ld",
     63      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
     64      1.1  mrg     }
     65      1.1  mrg 
     66      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
     67      1.1  mrg   if (len < 0)
     68      1.1  mrg     len = 0;
     69      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
     70      1.1  mrg 
     71      1.1  mrg   for (n = 0; n < dim; n++)
     72      1.1  mrg     {
     73      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
     74      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
     75      1.1  mrg 
     76      1.1  mrg       if (extent[n] < 0)
     77      1.1  mrg 	extent[n] = 0;
     78      1.1  mrg     }
     79      1.1  mrg   for (n = dim; n < rank; n++)
     80      1.1  mrg     {
     81      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
     82      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
     83      1.1  mrg 
     84      1.1  mrg       if (extent[n] < 0)
     85      1.1  mrg 	extent[n] = 0;
     86      1.1  mrg     }
     87      1.1  mrg 
     88      1.1  mrg   if (retarray->base_addr == NULL)
     89      1.1  mrg     {
     90      1.1  mrg       size_t alloc_size, str;
     91      1.1  mrg 
     92      1.1  mrg       for (n = 0; n < rank; n++)
     93      1.1  mrg 	{
     94      1.1  mrg 	  if (n == 0)
     95      1.1  mrg 	    str = 1;
     96      1.1  mrg 	  else
     97      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
     98      1.1  mrg 
     99      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    100      1.1  mrg 
    101      1.1  mrg 	}
    102      1.1  mrg 
    103      1.1  mrg       retarray->offset = 0;
    104      1.1  mrg       retarray->dtype.rank = rank;
    105      1.1  mrg 
    106      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    107      1.1  mrg 
    108      1.1  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
    109      1.1  mrg       if (alloc_size == 0)
    110      1.1  mrg 	{
    111      1.1  mrg 	  /* Make sure we have a zero-sized array.  */
    112      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
    113      1.1  mrg 	  return;
    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 		       " FINDLOC 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", "FINDLOC");
    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   dest = retarray->base_addr;
    138      1.1  mrg   continue_loop = 1;
    139      1.1  mrg 
    140      1.1  mrg   base = array->base_addr;
    141      1.1  mrg   while (continue_loop)
    142      1.1  mrg     {
    143      1.1  mrg       const GFC_UINTEGER_4 * restrict src;
    144      1.1  mrg       index_type result;
    145      1.1  mrg 
    146      1.1  mrg       result = 0;
    147      1.1  mrg       if (back)
    148      1.1  mrg 	{
    149      1.1  mrg 	  src = base + (len - 1) * delta * len_array;
    150      1.1  mrg 	  for (n = len; n > 0; n--, src -= delta * len_array)
    151      1.1  mrg 	    {
    152      1.1  mrg 	      if (compare_string_char4 (len_array, src, len_value, value) == 0)
    153      1.1  mrg 		{
    154      1.1  mrg 		  result = n;
    155      1.1  mrg 		  break;
    156      1.1  mrg 		}
    157      1.1  mrg 	    }
    158      1.1  mrg 	}
    159      1.1  mrg       else
    160      1.1  mrg 	{
    161      1.1  mrg 	  src = base;
    162      1.1  mrg 	  for (n = 1; n <= len; n++, src += delta * len_array)
    163      1.1  mrg 	    {
    164      1.1  mrg 	      if (compare_string_char4 (len_array, src, len_value, value) == 0)
    165      1.1  mrg 		{
    166      1.1  mrg 		  result = n;
    167      1.1  mrg 		  break;
    168      1.1  mrg 		}
    169      1.1  mrg 	    }
    170      1.1  mrg 	}
    171      1.1  mrg       *dest = result;
    172      1.1  mrg 
    173      1.1  mrg       count[0]++;
    174      1.1  mrg       base += sstride[0] * len_array;
    175      1.1  mrg       dest += dstride[0];
    176      1.1  mrg       n = 0;
    177      1.1  mrg       while (count[n] == extent[n])
    178      1.1  mrg 	{
    179      1.1  mrg 	  count[n] = 0;
    180      1.1  mrg 	  base -= sstride[n] * extent[n] * len_array;
    181      1.1  mrg 	  dest -= dstride[n] * extent[n];
    182      1.1  mrg 	  n++;
    183      1.1  mrg 	  if (n >= rank)
    184      1.1  mrg 	    {
    185      1.1  mrg 	      continue_loop = 0;
    186      1.1  mrg 	      break;
    187      1.1  mrg 	    }
    188      1.1  mrg 	  else
    189      1.1  mrg 	    {
    190      1.1  mrg 	      count[n]++;
    191      1.1  mrg 	      base += sstride[n] * len_array;
    192      1.1  mrg 	      dest += dstride[n];
    193      1.1  mrg 	    }
    194      1.1  mrg 	}
    195      1.1  mrg     }
    196      1.1  mrg }
    197      1.1  mrg extern void mfindloc1_s4 (gfc_array_index_type * const restrict retarray,
    198      1.1  mrg 		         gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
    199      1.1  mrg 			 const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
    200      1.1  mrg 			 GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value);
    201      1.1  mrg export_proto(mfindloc1_s4);
    202      1.1  mrg 
    203      1.1  mrg extern void
    204      1.1  mrg mfindloc1_s4 (gfc_array_index_type * const restrict retarray,
    205      1.1  mrg 	    gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
    206      1.1  mrg 	    const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
    207      1.1  mrg 	    GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value)
    208      1.1  mrg {
    209      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    210      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    211      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
    212      1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
    213      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    214      1.1  mrg   const GFC_UINTEGER_4 * restrict base;
    215      1.1  mrg   const GFC_LOGICAL_1 * restrict mbase;
    216      1.1  mrg   index_type * restrict dest;
    217      1.1  mrg   index_type rank;
    218      1.1  mrg   index_type n;
    219      1.1  mrg   index_type len;
    220      1.1  mrg   index_type delta;
    221      1.1  mrg   index_type mdelta;
    222      1.1  mrg   index_type dim;
    223      1.1  mrg   int mask_kind;
    224      1.1  mrg   int continue_loop;
    225      1.1  mrg 
    226      1.1  mrg   /* Make dim zero based to avoid confusion.  */
    227      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    228      1.1  mrg   dim = (*pdim) - 1;
    229      1.1  mrg 
    230      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    231      1.1  mrg     {
    232      1.1  mrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
    233      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    234      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    235      1.1  mrg     }
    236      1.1  mrg 
    237      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
    238      1.1  mrg   if (len < 0)
    239      1.1  mrg     len = 0;
    240      1.1  mrg 
    241      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim);
    242      1.1  mrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
    243      1.1  mrg 
    244      1.1  mrg   mbase = mask->base_addr;
    245      1.1  mrg 
    246      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    247      1.1  mrg 
    248      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    249      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    250      1.1  mrg       || mask_kind == 16
    251      1.1  mrg #endif
    252      1.1  mrg       )
    253      1.1  mrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    254      1.1  mrg   else
    255      1.1  mrg     internal_error (NULL, "Funny sized logical array");
    256      1.1  mrg 
    257      1.1  mrg   for (n = 0; n < dim; n++)
    258      1.1  mrg     {
    259      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
    260      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    261      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    262      1.1  mrg 
    263      1.1  mrg       if (extent[n] < 0)
    264      1.1  mrg 	extent[n] = 0;
    265      1.1  mrg     }
    266      1.1  mrg   for (n = dim; n < rank; n++)
    267      1.1  mrg     {
    268      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
    269      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
    270      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
    271      1.1  mrg 
    272      1.1  mrg       if (extent[n] < 0)
    273      1.1  mrg 	extent[n] = 0;
    274      1.1  mrg     }
    275      1.1  mrg 
    276      1.1  mrg   if (retarray->base_addr == NULL)
    277      1.1  mrg     {
    278      1.1  mrg       size_t alloc_size, str;
    279      1.1  mrg 
    280      1.1  mrg       for (n = 0; n < rank; n++)
    281      1.1  mrg 	{
    282      1.1  mrg 	  if (n == 0)
    283      1.1  mrg 	    str = 1;
    284      1.1  mrg 	  else
    285      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    286      1.1  mrg 
    287      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    288      1.1  mrg 
    289      1.1  mrg 	}
    290      1.1  mrg 
    291      1.1  mrg       retarray->offset = 0;
    292      1.1  mrg       retarray->dtype.rank = rank;
    293      1.1  mrg 
    294      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    295      1.1  mrg 
    296      1.1  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
    297      1.1  mrg       if (alloc_size == 0)
    298      1.1  mrg 	{
    299      1.1  mrg 	  /* Make sure we have a zero-sized array.  */
    300      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
    301      1.1  mrg 	  return;
    302      1.1  mrg 	}
    303      1.1  mrg     }
    304      1.1  mrg   else
    305      1.1  mrg     {
    306      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    307      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    308      1.1  mrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
    309      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    310      1.1  mrg 		       (long int) rank);
    311      1.1  mrg 
    312      1.1  mrg       if (unlikely (compile_options.bounds_check))
    313      1.1  mrg 	bounds_ifunction_return ((array_t *) retarray, extent,
    314      1.1  mrg 				 "return value", "FINDLOC");
    315      1.1  mrg     }
    316      1.1  mrg 
    317      1.1  mrg   for (n = 0; n < rank; n++)
    318      1.1  mrg     {
    319      1.1  mrg       count[n] = 0;
    320      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    321      1.1  mrg       if (extent[n] <= 0)
    322      1.1  mrg 	return;
    323      1.1  mrg     }
    324      1.1  mrg 
    325      1.1  mrg   dest = retarray->base_addr;
    326      1.1  mrg   continue_loop = 1;
    327      1.1  mrg 
    328      1.1  mrg   base = array->base_addr;
    329      1.1  mrg   while (continue_loop)
    330      1.1  mrg     {
    331      1.1  mrg       const GFC_UINTEGER_4 * restrict src;
    332      1.1  mrg       const GFC_LOGICAL_1 * restrict msrc;
    333      1.1  mrg       index_type result;
    334      1.1  mrg 
    335      1.1  mrg       result = 0;
    336      1.1  mrg       if (back)
    337      1.1  mrg 	{
    338      1.1  mrg 	  src = base + (len - 1) * delta * len_array;
    339      1.1  mrg 	  msrc = mbase + (len - 1) * mdelta;
    340      1.1  mrg 	  for (n = len; n > 0; n--, src -= delta * len_array, msrc -= mdelta)
    341      1.1  mrg 	    {
    342      1.1  mrg 	      if (*msrc && compare_string_char4 (len_array, src, len_value, value) == 0)
    343      1.1  mrg 		{
    344      1.1  mrg 		  result = n;
    345      1.1  mrg 		  break;
    346      1.1  mrg 		}
    347      1.1  mrg 	    }
    348      1.1  mrg 	}
    349      1.1  mrg       else
    350      1.1  mrg 	{
    351      1.1  mrg 	  src = base;
    352      1.1  mrg 	  msrc = mbase;
    353      1.1  mrg 	  for (n = 1; n <= len; n++, src += delta * len_array, msrc += mdelta)
    354      1.1  mrg 	    {
    355      1.1  mrg 	      if (*msrc && compare_string_char4 (len_array, src, len_value, value) == 0)
    356      1.1  mrg 		{
    357      1.1  mrg 		  result = n;
    358      1.1  mrg 		  break;
    359      1.1  mrg 		}
    360      1.1  mrg 	    }
    361      1.1  mrg 	}
    362      1.1  mrg       *dest = result;
    363      1.1  mrg 
    364      1.1  mrg       count[0]++;
    365      1.1  mrg       base += sstride[0] * len_array;
    366      1.1  mrg       mbase += mstride[0];
    367      1.1  mrg       dest += dstride[0];
    368      1.1  mrg       n = 0;
    369      1.1  mrg       while (count[n] == extent[n])
    370      1.1  mrg 	{
    371      1.1  mrg 	  count[n] = 0;
    372      1.1  mrg 	  base -= sstride[n] * extent[n] * len_array;
    373      1.1  mrg 	  mbase -= mstride[n] * extent[n];
    374      1.1  mrg 	  dest -= dstride[n] * extent[n];
    375      1.1  mrg 	  n++;
    376      1.1  mrg 	  if (n >= rank)
    377      1.1  mrg 	    {
    378      1.1  mrg 	      continue_loop = 0;
    379      1.1  mrg 	      break;
    380      1.1  mrg 	    }
    381      1.1  mrg 	  else
    382      1.1  mrg 	    {
    383      1.1  mrg 	      count[n]++;
    384      1.1  mrg 	      base += sstride[n] * len_array;
    385      1.1  mrg 	      dest += dstride[n];
    386      1.1  mrg 	    }
    387      1.1  mrg 	}
    388      1.1  mrg     }
    389      1.1  mrg }
    390      1.1  mrg extern void sfindloc1_s4 (gfc_array_index_type * const restrict retarray,
    391      1.1  mrg 		         gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
    392      1.1  mrg 			 const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
    393      1.1  mrg 			 GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value);
    394      1.1  mrg export_proto(sfindloc1_s4);
    395      1.1  mrg 
    396      1.1  mrg extern void
    397      1.1  mrg sfindloc1_s4 (gfc_array_index_type * const restrict retarray,
    398      1.1  mrg 	    gfc_array_s4 * const restrict array, GFC_UINTEGER_4 *const restrict value,
    399      1.1  mrg 	    const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict  mask,
    400      1.1  mrg 	    GFC_LOGICAL_4 back, gfc_charlen_type len_array, gfc_charlen_type len_value)
    401      1.1  mrg {
    402      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    403      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    404      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    405      1.1  mrg   index_type * restrict dest;
    406      1.1  mrg   index_type rank;
    407      1.1  mrg   index_type n;
    408      1.1  mrg   index_type len;
    409      1.1  mrg   index_type dim;
    410      1.1  mrg   bool continue_loop;
    411      1.1  mrg 
    412      1.1  mrg   if (mask == NULL || *mask)
    413      1.1  mrg     {
    414      1.1  mrg       findloc1_s4 (retarray, array, value, pdim, back, len_array, len_value);
    415      1.1  mrg       return;
    416      1.1  mrg     }
    417      1.1  mrg     /* Make dim zero based to avoid confusion.  */
    418      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    419      1.1  mrg   dim = (*pdim) - 1;
    420      1.1  mrg 
    421      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    422      1.1  mrg     {
    423      1.1  mrg       runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
    424      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    425      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    426      1.1  mrg     }
    427      1.1  mrg 
    428      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
    429      1.1  mrg   if (len < 0)
    430      1.1  mrg     len = 0;
    431      1.1  mrg 
    432      1.1  mrg   for (n = 0; n < dim; n++)
    433      1.1  mrg     {
    434      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    435      1.1  mrg 
    436      1.1  mrg       if (extent[n] <= 0)
    437      1.1  mrg 	extent[n] = 0;
    438      1.1  mrg     }
    439      1.1  mrg 
    440      1.1  mrg   for (n = dim; n < rank; n++)
    441      1.1  mrg     {
    442      1.1  mrg       extent[n] =
    443      1.1  mrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
    444      1.1  mrg 
    445      1.1  mrg       if (extent[n] <= 0)
    446      1.1  mrg 	extent[n] = 0;
    447      1.1  mrg     }
    448      1.1  mrg 
    449      1.1  mrg 
    450      1.1  mrg   if (retarray->base_addr == NULL)
    451      1.1  mrg     {
    452      1.1  mrg       size_t alloc_size, str;
    453      1.1  mrg 
    454      1.1  mrg       for (n = 0; n < rank; n++)
    455      1.1  mrg 	{
    456      1.1  mrg 	  if (n == 0)
    457      1.1  mrg 	    str = 1;
    458      1.1  mrg 	  else
    459      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    460      1.1  mrg 
    461      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    462      1.1  mrg 	}
    463      1.1  mrg 
    464      1.1  mrg       retarray->offset = 0;
    465      1.1  mrg       retarray->dtype.rank = rank;
    466      1.1  mrg 
    467      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    468      1.1  mrg 
    469      1.1  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
    470      1.1  mrg       if (alloc_size == 0)
    471      1.1  mrg 	{
    472      1.1  mrg 	  /* Make sure we have a zero-sized array.  */
    473      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
    474      1.1  mrg 	  return;
    475      1.1  mrg 	}
    476      1.1  mrg     }
    477      1.1  mrg   else
    478      1.1  mrg     {
    479      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    480      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    481      1.1  mrg 		       " FINDLOC intrinsic: is %ld, should be %ld",
    482      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    483      1.1  mrg 		       (long int) rank);
    484      1.1  mrg 
    485      1.1  mrg       if (unlikely (compile_options.bounds_check))
    486      1.1  mrg 	bounds_ifunction_return ((array_t *) retarray, extent,
    487      1.1  mrg 				 "return value", "FINDLOC");
    488      1.1  mrg     }
    489      1.1  mrg 
    490      1.1  mrg   for (n = 0; n < rank; n++)
    491      1.1  mrg     {
    492      1.1  mrg       count[n] = 0;
    493      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    494      1.1  mrg       if (extent[n] <= 0)
    495      1.1  mrg 	return;
    496      1.1  mrg     }
    497      1.1  mrg   dest = retarray->base_addr;
    498      1.1  mrg   continue_loop = 1;
    499      1.1  mrg 
    500      1.1  mrg   while (continue_loop)
    501      1.1  mrg     {
    502      1.1  mrg       *dest = 0;
    503      1.1  mrg 
    504      1.1  mrg       count[0]++;
    505      1.1  mrg       dest += dstride[0];
    506      1.1  mrg       n = 0;
    507      1.1  mrg       while (count[n] == extent[n])
    508      1.1  mrg 	{
    509      1.1  mrg 	  count[n] = 0;
    510      1.1  mrg 	  dest -= dstride[n] * extent[n];
    511      1.1  mrg 	  n++;
    512      1.1  mrg 	  if (n >= rank)
    513      1.1  mrg 	    {
    514      1.1  mrg 	      continue_loop = 0;
    515      1.1  mrg 	      break;
    516      1.1  mrg 	    }
    517      1.1  mrg 	  else
    518      1.1  mrg 	    {
    519      1.1  mrg 	      count[n]++;
    520      1.1  mrg 	      dest += dstride[n];
    521      1.1  mrg 	    }
    522      1.1  mrg 	}
    523      1.1  mrg     }
    524      1.1  mrg }
    525      1.1  mrg #endif
    526