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