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 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 
     30      1.1  mrg #if defined (HAVE_GFC_INTEGER_2) && defined (HAVE_GFC_INTEGER_8)
     31      1.1  mrg 
     32      1.1  mrg 
     33      1.1  mrg extern void minloc0_8_i2 (gfc_array_i8 * const restrict retarray,
     34      1.1  mrg 	gfc_array_i2 * const restrict array, GFC_LOGICAL_4);
     35      1.1  mrg export_proto(minloc0_8_i2);
     36      1.1  mrg 
     37      1.1  mrg void
     38      1.1  mrg minloc0_8_i2 (gfc_array_i8 * const restrict retarray,
     39      1.1  mrg 	gfc_array_i2 * const restrict array, GFC_LOGICAL_4 back)
     40      1.1  mrg {
     41      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     42      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     43      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     44      1.1  mrg   index_type dstride;
     45      1.1  mrg   const GFC_INTEGER_2 *base;
     46      1.1  mrg   GFC_INTEGER_8 * restrict dest;
     47      1.1  mrg   index_type rank;
     48      1.1  mrg   index_type n;
     49      1.1  mrg 
     50      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array);
     51      1.1  mrg   if (rank <= 0)
     52      1.1  mrg     runtime_error ("Rank of array needs to be > 0");
     53      1.1  mrg 
     54      1.1  mrg   if (retarray->base_addr == NULL)
     55      1.1  mrg     {
     56      1.1  mrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
     57      1.1  mrg       retarray->dtype.rank = 1;
     58      1.1  mrg       retarray->offset = 0;
     59      1.1  mrg       retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
     60      1.1  mrg     }
     61      1.1  mrg   else
     62      1.1  mrg     {
     63      1.1  mrg       if (unlikely (compile_options.bounds_check))
     64      1.1  mrg 	bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
     65      1.1  mrg 				"MINLOC");
     66      1.1  mrg     }
     67      1.1  mrg 
     68      1.1  mrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
     69      1.1  mrg   dest = retarray->base_addr;
     70      1.1  mrg   for (n = 0; n < rank; n++)
     71      1.1  mrg     {
     72      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
     73      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
     74      1.1  mrg       count[n] = 0;
     75      1.1  mrg       if (extent[n] <= 0)
     76      1.1  mrg 	{
     77      1.1  mrg 	  /* Set the return value.  */
     78      1.1  mrg 	  for (n = 0; n < rank; n++)
     79      1.1  mrg 	    dest[n * dstride] = 0;
     80      1.1  mrg 	  return;
     81      1.1  mrg 	}
     82      1.1  mrg     }
     83      1.1  mrg 
     84      1.1  mrg   base = array->base_addr;
     85      1.1  mrg 
     86      1.1  mrg   /* Initialize the return value.  */
     87      1.1  mrg   for (n = 0; n < rank; n++)
     88      1.1  mrg     dest[n * dstride] = 1;
     89      1.1  mrg   {
     90      1.1  mrg 
     91      1.1  mrg     GFC_INTEGER_2 minval;
     92      1.1  mrg #if defined(GFC_INTEGER_2_QUIET_NAN)
     93      1.1  mrg     int fast = 0;
     94      1.1  mrg #endif
     95      1.1  mrg 
     96      1.1  mrg #if defined(GFC_INTEGER_2_INFINITY)
     97      1.1  mrg     minval = GFC_INTEGER_2_INFINITY;
     98      1.1  mrg #else
     99      1.1  mrg     minval = GFC_INTEGER_2_HUGE;
    100      1.1  mrg #endif
    101      1.1  mrg   while (base)
    102      1.1  mrg     {
    103      1.1  mrg 	  /* Implementation start.  */
    104      1.1  mrg 
    105      1.1  mrg #if defined(GFC_INTEGER_2_QUIET_NAN)
    106      1.1  mrg       if (unlikely (!fast))
    107      1.1  mrg 	{
    108      1.1  mrg 	  do
    109      1.1  mrg 	    {
    110      1.1  mrg 	      if (*base <= minval)
    111      1.1  mrg 		{
    112      1.1  mrg 		  fast = 1;
    113      1.1  mrg 		  minval = *base;
    114      1.1  mrg 		  for (n = 0; n < rank; n++)
    115      1.1  mrg 		    dest[n * dstride] = count[n] + 1;
    116      1.1  mrg 		  break;
    117      1.1  mrg 		}
    118      1.1  mrg 	      base += sstride[0];
    119      1.1  mrg 	    }
    120      1.1  mrg 	  while (++count[0] != extent[0]);
    121      1.1  mrg 	  if (likely (fast))
    122      1.1  mrg 	    continue;
    123      1.1  mrg 	}
    124      1.1  mrg       else
    125      1.1  mrg #endif
    126      1.1  mrg       if (back)
    127      1.1  mrg 	do
    128      1.1  mrg 	  {
    129      1.1  mrg 	    if (unlikely (*base <= minval))
    130      1.1  mrg 	      {
    131      1.1  mrg 		minval = *base;
    132      1.1  mrg 		for (n = 0; n < rank; n++)
    133      1.1  mrg 		  dest[n * dstride] = count[n] + 1;
    134      1.1  mrg 	      }
    135      1.1  mrg 	    base += sstride[0];
    136      1.1  mrg 	  }
    137      1.1  mrg 	while (++count[0] != extent[0]);
    138      1.1  mrg       else
    139      1.1  mrg 	do
    140      1.1  mrg 	  {
    141      1.1  mrg 	    if (unlikely (*base < minval))
    142      1.1  mrg 	      {
    143      1.1  mrg 		minval = *base;
    144      1.1  mrg 		for (n = 0; n < rank; n++)
    145      1.1  mrg 		  dest[n * dstride] = count[n] + 1;
    146      1.1  mrg 	      }
    147      1.1  mrg 	  /* Implementation end.  */
    148      1.1  mrg 	  /* Advance to the next element.  */
    149      1.1  mrg 	  base += sstride[0];
    150      1.1  mrg 	}
    151      1.1  mrg       while (++count[0] != extent[0]);
    152      1.1  mrg       n = 0;
    153      1.1  mrg       do
    154      1.1  mrg 	{
    155      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    156      1.1  mrg 	     the next dimension.  */
    157      1.1  mrg 	  count[n] = 0;
    158      1.1  mrg 	  /* We could precalculate these products, but this is a less
    159      1.1  mrg 	     frequently used path so probably not worth it.  */
    160      1.1  mrg 	  base -= sstride[n] * extent[n];
    161      1.1  mrg 	  n++;
    162      1.1  mrg 	  if (n >= rank)
    163      1.1  mrg 	    {
    164      1.1  mrg 	      /* Break out of the loop.  */
    165      1.1  mrg 	      base = NULL;
    166      1.1  mrg 	      break;
    167      1.1  mrg 	    }
    168      1.1  mrg 	  else
    169      1.1  mrg 	    {
    170      1.1  mrg 	      count[n]++;
    171      1.1  mrg 	      base += sstride[n];
    172      1.1  mrg 	    }
    173      1.1  mrg 	}
    174      1.1  mrg       while (count[n] == extent[n]);
    175      1.1  mrg     }
    176      1.1  mrg   }
    177      1.1  mrg }
    178      1.1  mrg 
    179      1.1  mrg extern void mminloc0_8_i2 (gfc_array_i8 * const restrict,
    180      1.1  mrg 	gfc_array_i2 * const restrict, gfc_array_l1 * const restrict,
    181      1.1  mrg 	GFC_LOGICAL_4);
    182      1.1  mrg export_proto(mminloc0_8_i2);
    183      1.1  mrg 
    184      1.1  mrg void
    185      1.1  mrg mminloc0_8_i2 (gfc_array_i8 * const restrict retarray,
    186      1.1  mrg 	gfc_array_i2 * const restrict array,
    187      1.1  mrg 	gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back)
    188      1.1  mrg {
    189      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    190      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    191      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
    192      1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
    193      1.1  mrg   index_type dstride;
    194      1.1  mrg   GFC_INTEGER_8 *dest;
    195      1.1  mrg   const GFC_INTEGER_2 *base;
    196      1.1  mrg   GFC_LOGICAL_1 *mbase;
    197      1.1  mrg   int rank;
    198      1.1  mrg   index_type n;
    199      1.1  mrg   int mask_kind;
    200      1.1  mrg 
    201      1.1  mrg 
    202      1.1  mrg   if (mask == NULL)
    203      1.1  mrg     {
    204      1.1  mrg       minloc0_8_i2 (retarray, array, back);
    205      1.1  mrg       return;
    206      1.1  mrg     }
    207      1.1  mrg 
    208      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array);
    209      1.1  mrg   if (rank <= 0)
    210      1.1  mrg     runtime_error ("Rank of array needs to be > 0");
    211      1.1  mrg 
    212      1.1  mrg   if (retarray->base_addr == NULL)
    213      1.1  mrg     {
    214      1.1  mrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
    215      1.1  mrg       retarray->dtype.rank = 1;
    216      1.1  mrg       retarray->offset = 0;
    217      1.1  mrg       retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
    218      1.1  mrg     }
    219      1.1  mrg   else
    220      1.1  mrg     {
    221      1.1  mrg       if (unlikely (compile_options.bounds_check))
    222      1.1  mrg 	{
    223      1.1  mrg 
    224      1.1  mrg 	  bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
    225      1.1  mrg 				  "MINLOC");
    226      1.1  mrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
    227      1.1  mrg 				  "MASK argument", "MINLOC");
    228      1.1  mrg 	}
    229      1.1  mrg     }
    230      1.1  mrg 
    231      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    232      1.1  mrg 
    233      1.1  mrg   mbase = mask->base_addr;
    234      1.1  mrg 
    235      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    236      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    237      1.1  mrg       || mask_kind == 16
    238      1.1  mrg #endif
    239      1.1  mrg       )
    240      1.1  mrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    241      1.1  mrg   else
    242      1.1  mrg     runtime_error ("Funny sized logical array");
    243      1.1  mrg 
    244      1.1  mrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
    245      1.1  mrg   dest = retarray->base_addr;
    246      1.1  mrg   for (n = 0; n < rank; n++)
    247      1.1  mrg     {
    248      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
    249      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    250      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    251      1.1  mrg       count[n] = 0;
    252      1.1  mrg       if (extent[n] <= 0)
    253      1.1  mrg 	{
    254      1.1  mrg 	  /* Set the return value.  */
    255      1.1  mrg 	  for (n = 0; n < rank; n++)
    256      1.1  mrg 	    dest[n * dstride] = 0;
    257      1.1  mrg 	  return;
    258      1.1  mrg 	}
    259      1.1  mrg     }
    260      1.1  mrg 
    261      1.1  mrg   base = array->base_addr;
    262      1.1  mrg 
    263      1.1  mrg   /* Initialize the return value.  */
    264      1.1  mrg   for (n = 0; n < rank; n++)
    265      1.1  mrg     dest[n * dstride] = 0;
    266      1.1  mrg   {
    267      1.1  mrg 
    268      1.1  mrg   GFC_INTEGER_2 minval;
    269      1.1  mrg    int fast = 0;
    270      1.1  mrg 
    271      1.1  mrg #if defined(GFC_INTEGER_2_INFINITY)
    272      1.1  mrg     minval = GFC_INTEGER_2_INFINITY;
    273      1.1  mrg #else
    274      1.1  mrg     minval = GFC_INTEGER_2_HUGE;
    275      1.1  mrg #endif
    276      1.1  mrg   while (base)
    277      1.1  mrg     {
    278      1.1  mrg 	  /* Implementation start.  */
    279      1.1  mrg 
    280      1.1  mrg       if (unlikely (!fast))
    281      1.1  mrg 	{
    282      1.1  mrg 	  do
    283      1.1  mrg 	    {
    284      1.1  mrg 	      if (*mbase)
    285      1.1  mrg 		{
    286      1.1  mrg #if defined(GFC_INTEGER_2_QUIET_NAN)
    287      1.1  mrg 		  if (unlikely (dest[0] == 0))
    288      1.1  mrg 		    for (n = 0; n < rank; n++)
    289      1.1  mrg 		      dest[n * dstride] = count[n] + 1;
    290      1.1  mrg 		  if (*base <= minval)
    291      1.1  mrg #endif
    292      1.1  mrg 		    {
    293      1.1  mrg 		      fast = 1;
    294      1.1  mrg 		      minval = *base;
    295      1.1  mrg 		      for (n = 0; n < rank; n++)
    296      1.1  mrg 			dest[n * dstride] = count[n] + 1;
    297      1.1  mrg 		      break;
    298      1.1  mrg 		    }
    299      1.1  mrg 		}
    300      1.1  mrg 	      base += sstride[0];
    301      1.1  mrg 	      mbase += mstride[0];
    302      1.1  mrg 	    }
    303      1.1  mrg 	  while (++count[0] != extent[0]);
    304      1.1  mrg 	  if (likely (fast))
    305      1.1  mrg 	    continue;
    306      1.1  mrg 	}
    307      1.1  mrg         else
    308      1.1  mrg         if (back)
    309      1.1  mrg 	  do
    310      1.1  mrg 	    {
    311      1.1  mrg 	      if (unlikely (*mbase && (*base <= minval)))
    312      1.1  mrg 	        {
    313      1.1  mrg 	      	  minval = *base;
    314      1.1  mrg 	      	  for (n = 0; n < rank; n++)
    315      1.1  mrg 		    dest[n * dstride] = count[n] + 1;
    316      1.1  mrg 	    	}
    317      1.1  mrg 		base += sstride[0];
    318      1.1  mrg 	    }
    319      1.1  mrg 	    while (++count[0] != extent[0]);
    320      1.1  mrg 	else
    321      1.1  mrg 	  do
    322      1.1  mrg 	    {
    323      1.1  mrg 	      if (unlikely (*mbase && (*base < minval)))
    324      1.1  mrg 		{
    325      1.1  mrg 		  minval = *base;
    326      1.1  mrg 		  for (n = 0; n < rank; n++)
    327      1.1  mrg 		    dest[n * dstride] = count[n] + 1;
    328      1.1  mrg 		}
    329      1.1  mrg 	  /* Implementation end.  */
    330      1.1  mrg 	  /* Advance to the next element.  */
    331      1.1  mrg 	  base += sstride[0];
    332      1.1  mrg 	  mbase += mstride[0];
    333      1.1  mrg 	}
    334      1.1  mrg       while (++count[0] != extent[0]);
    335      1.1  mrg       n = 0;
    336      1.1  mrg       do
    337      1.1  mrg 	{
    338      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    339      1.1  mrg 	     the next dimension.  */
    340      1.1  mrg 	  count[n] = 0;
    341      1.1  mrg 	  /* We could precalculate these products, but this is a less
    342      1.1  mrg 	     frequently used path so probably not worth it.  */
    343      1.1  mrg 	  base -= sstride[n] * extent[n];
    344      1.1  mrg 	  mbase -= mstride[n] * extent[n];
    345      1.1  mrg 	  n++;
    346      1.1  mrg 	  if (n >= rank)
    347      1.1  mrg 	    {
    348      1.1  mrg 	      /* Break out of the loop.  */
    349      1.1  mrg 	      base = NULL;
    350      1.1  mrg 	      break;
    351      1.1  mrg 	    }
    352      1.1  mrg 	  else
    353      1.1  mrg 	    {
    354      1.1  mrg 	      count[n]++;
    355      1.1  mrg 	      base += sstride[n];
    356      1.1  mrg 	      mbase += mstride[n];
    357      1.1  mrg 	    }
    358      1.1  mrg 	}
    359      1.1  mrg       while (count[n] == extent[n]);
    360      1.1  mrg     }
    361      1.1  mrg   }
    362      1.1  mrg }
    363      1.1  mrg 
    364      1.1  mrg extern void sminloc0_8_i2 (gfc_array_i8 * const restrict,
    365      1.1  mrg 	gfc_array_i2 * const restrict, GFC_LOGICAL_4 *, GFC_LOGICAL_4);
    366      1.1  mrg export_proto(sminloc0_8_i2);
    367      1.1  mrg 
    368      1.1  mrg void
    369      1.1  mrg sminloc0_8_i2 (gfc_array_i8 * const restrict retarray,
    370      1.1  mrg 	gfc_array_i2 * const restrict array,
    371      1.1  mrg 	GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
    372      1.1  mrg {
    373      1.1  mrg   index_type rank;
    374      1.1  mrg   index_type dstride;
    375      1.1  mrg   index_type n;
    376      1.1  mrg   GFC_INTEGER_8 *dest;
    377      1.1  mrg 
    378      1.1  mrg   if (mask == NULL || *mask)
    379      1.1  mrg     {
    380      1.1  mrg       minloc0_8_i2 (retarray, array, back);
    381      1.1  mrg       return;
    382      1.1  mrg     }
    383      1.1  mrg 
    384      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array);
    385      1.1  mrg 
    386      1.1  mrg   if (rank <= 0)
    387      1.1  mrg     runtime_error ("Rank of array needs to be > 0");
    388      1.1  mrg 
    389      1.1  mrg   if (retarray->base_addr == NULL)
    390      1.1  mrg     {
    391      1.1  mrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
    392      1.1  mrg       retarray->dtype.rank = 1;
    393      1.1  mrg       retarray->offset = 0;
    394      1.1  mrg       retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
    395      1.1  mrg     }
    396      1.1  mrg   else if (unlikely (compile_options.bounds_check))
    397      1.1  mrg     {
    398      1.1  mrg        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
    399      1.1  mrg 			       "MINLOC");
    400      1.1  mrg     }
    401      1.1  mrg 
    402      1.1  mrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
    403      1.1  mrg   dest = retarray->base_addr;
    404      1.1  mrg   for (n = 0; n<rank; n++)
    405      1.1  mrg     dest[n * dstride] = 0 ;
    406      1.1  mrg }
    407      1.1  mrg #endif
    408