Home | History | Annotate | Line # | Download | only in generated
      1      1.1  mrg /* Implementation of the MAXLOC intrinsic
      2  1.1.1.3  mrg    Copyright (C) 2017-2022 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Thomas Koenig
      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 <stdlib.h>
     28      1.1  mrg #include <string.h>
     29      1.1  mrg #include <assert.h>
     30      1.1  mrg #include <limits.h>
     31      1.1  mrg 
     32      1.1  mrg 
     33      1.1  mrg #if defined (HAVE_GFC_UINTEGER_4) && defined (HAVE_GFC_UINTEGER_4)
     34      1.1  mrg 
     35      1.1  mrg static inline int
     36      1.1  mrg compare_fcn (const GFC_UINTEGER_4 *a, const GFC_UINTEGER_4 *b, gfc_charlen_type n)
     37      1.1  mrg {
     38      1.1  mrg   if (sizeof (GFC_UINTEGER_4) == 1)
     39      1.1  mrg     return memcmp (a, b, n);
     40      1.1  mrg   else
     41      1.1  mrg     return memcmp_char4 (a, b, n);
     42      1.1  mrg 
     43      1.1  mrg }
     44      1.1  mrg 
     45      1.1  mrg #define INITVAL 255
     46      1.1  mrg 
     47      1.1  mrg extern void minval0_s4 (GFC_UINTEGER_4 * restrict,
     48      1.1  mrg         gfc_charlen_type,
     49      1.1  mrg 	gfc_array_s4 * const restrict array, gfc_charlen_type);
     50      1.1  mrg export_proto(minval0_s4);
     51      1.1  mrg 
     52      1.1  mrg void
     53      1.1  mrg minval0_s4 (GFC_UINTEGER_4 * restrict ret,
     54      1.1  mrg         gfc_charlen_type xlen,
     55      1.1  mrg 	gfc_array_s4 * const restrict array, gfc_charlen_type len)
     56      1.1  mrg {
     57      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     58      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     59      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     60      1.1  mrg   const GFC_UINTEGER_4 *base;
     61      1.1  mrg   index_type rank;
     62      1.1  mrg   index_type n;
     63      1.1  mrg 
     64      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array);
     65      1.1  mrg   if (rank <= 0)
     66      1.1  mrg     runtime_error ("Rank of array needs to be > 0");
     67      1.1  mrg 
     68      1.1  mrg   assert (xlen == len);
     69      1.1  mrg 
     70      1.1  mrg   /* Initialize return value.  */
     71      1.1  mrg   memset (ret, INITVAL, sizeof(*ret) * len);
     72      1.1  mrg 
     73      1.1  mrg   for (n = 0; n < rank; n++)
     74      1.1  mrg     {
     75      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
     76      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
     77      1.1  mrg       count[n] = 0;
     78      1.1  mrg       if (extent[n] <= 0)
     79      1.1  mrg         return;
     80      1.1  mrg     }
     81      1.1  mrg 
     82      1.1  mrg   base = array->base_addr;
     83      1.1  mrg 
     84      1.1  mrg   {
     85      1.1  mrg 
     86      1.1  mrg   const GFC_UINTEGER_4 *retval;
     87      1.1  mrg    retval = ret;
     88      1.1  mrg 
     89      1.1  mrg   while (base)
     90      1.1  mrg     {
     91      1.1  mrg       do
     92      1.1  mrg 	{
     93      1.1  mrg 	  /* Implementation start.  */
     94      1.1  mrg 
     95      1.1  mrg   if (compare_fcn (base, retval, len) < 0)
     96      1.1  mrg     {
     97      1.1  mrg       retval = base;
     98      1.1  mrg     }
     99      1.1  mrg 	  /* Implementation end.  */
    100      1.1  mrg 	  /* Advance to the next element.  */
    101      1.1  mrg 	  base += sstride[0];
    102      1.1  mrg 	}
    103      1.1  mrg       while (++count[0] != extent[0]);
    104      1.1  mrg       n = 0;
    105      1.1  mrg       do
    106      1.1  mrg 	{
    107      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    108      1.1  mrg 	     the next dimension.  */
    109      1.1  mrg 	  count[n] = 0;
    110      1.1  mrg 	  /* We could precalculate these products, but this is a less
    111      1.1  mrg 	     frequently used path so probably not worth it.  */
    112      1.1  mrg 	  base -= sstride[n] * extent[n];
    113      1.1  mrg 	  n++;
    114      1.1  mrg 	  if (n >= rank)
    115      1.1  mrg 	    {
    116      1.1  mrg 	      /* Break out of the loop.  */
    117      1.1  mrg 	      base = NULL;
    118      1.1  mrg 	      break;
    119      1.1  mrg 	    }
    120      1.1  mrg 	  else
    121      1.1  mrg 	    {
    122      1.1  mrg 	      count[n]++;
    123      1.1  mrg 	      base += sstride[n];
    124      1.1  mrg 	    }
    125      1.1  mrg 	}
    126      1.1  mrg       while (count[n] == extent[n]);
    127      1.1  mrg     }
    128      1.1  mrg    memcpy (ret, retval, len * sizeof (*ret));
    129      1.1  mrg   }
    130      1.1  mrg }
    131      1.1  mrg 
    132      1.1  mrg 
    133      1.1  mrg extern void mminval0_s4 (GFC_UINTEGER_4 * restrict,
    134      1.1  mrg        gfc_charlen_type, gfc_array_s4 * const restrict array,
    135      1.1  mrg        gfc_array_l1 * const restrict mask, gfc_charlen_type len);
    136      1.1  mrg export_proto(mminval0_s4);
    137      1.1  mrg 
    138      1.1  mrg void
    139      1.1  mrg mminval0_s4 (GFC_UINTEGER_4 * const restrict ret,
    140      1.1  mrg 	gfc_charlen_type xlen, gfc_array_s4 * const restrict array,
    141      1.1  mrg 	gfc_array_l1 * const restrict mask, gfc_charlen_type len)
    142      1.1  mrg {
    143      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    144      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    145      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
    146      1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
    147      1.1  mrg   const GFC_UINTEGER_4 *base;
    148      1.1  mrg   GFC_LOGICAL_1 *mbase;
    149      1.1  mrg   int rank;
    150      1.1  mrg   index_type n;
    151      1.1  mrg   int mask_kind;
    152      1.1  mrg 
    153      1.1  mrg   if (mask == NULL)
    154      1.1  mrg     {
    155      1.1  mrg       minval0_s4 (ret, xlen, array, len);
    156      1.1  mrg       return;
    157      1.1  mrg     }
    158      1.1  mrg 
    159      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array);
    160      1.1  mrg   if (rank <= 0)
    161      1.1  mrg     runtime_error ("Rank of array needs to be > 0");
    162      1.1  mrg 
    163      1.1  mrg   assert (xlen == len);
    164      1.1  mrg 
    165      1.1  mrg /* Initialize return value.  */
    166      1.1  mrg   memset (ret, INITVAL, sizeof(*ret) * len);
    167      1.1  mrg 
    168      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    169      1.1  mrg 
    170      1.1  mrg   mbase = mask->base_addr;
    171      1.1  mrg 
    172      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    173      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    174      1.1  mrg       || mask_kind == 16
    175      1.1  mrg #endif
    176      1.1  mrg       )
    177      1.1  mrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    178      1.1  mrg   else
    179      1.1  mrg     runtime_error ("Funny sized logical array");
    180      1.1  mrg 
    181      1.1  mrg   for (n = 0; n < rank; n++)
    182      1.1  mrg     {
    183      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
    184      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    185      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    186      1.1  mrg       count[n] = 0;
    187      1.1  mrg       if (extent[n] <= 0)
    188      1.1  mrg 	return;
    189      1.1  mrg     }
    190      1.1  mrg 
    191      1.1  mrg   base = array->base_addr;
    192      1.1  mrg   {
    193      1.1  mrg 
    194      1.1  mrg   const GFC_UINTEGER_4 *retval;
    195      1.1  mrg 
    196      1.1  mrg   retval = ret;
    197      1.1  mrg 
    198      1.1  mrg   while (base)
    199      1.1  mrg     {
    200      1.1  mrg       do
    201      1.1  mrg 	{
    202      1.1  mrg 	  /* Implementation start.  */
    203      1.1  mrg 
    204      1.1  mrg   if (*mbase && compare_fcn (base, retval, len) < 0)
    205      1.1  mrg     {
    206      1.1  mrg       retval = base;
    207      1.1  mrg     }
    208      1.1  mrg 	  /* Implementation end.  */
    209      1.1  mrg 	  /* Advance to the next element.  */
    210      1.1  mrg 	  base += sstride[0];
    211      1.1  mrg 	  mbase += mstride[0];
    212      1.1  mrg 	}
    213      1.1  mrg       while (++count[0] != extent[0]);
    214      1.1  mrg       n = 0;
    215      1.1  mrg       do
    216      1.1  mrg 	{
    217      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    218      1.1  mrg 	     the next dimension.  */
    219      1.1  mrg 	  count[n] = 0;
    220      1.1  mrg 	  /* We could precalculate these products, but this is a less
    221      1.1  mrg 	     frequently used path so probably not worth it.  */
    222      1.1  mrg 	  base -= sstride[n] * extent[n];
    223      1.1  mrg 	  mbase -= mstride[n] * extent[n];
    224      1.1  mrg 	  n++;
    225      1.1  mrg 	  if (n >= rank)
    226      1.1  mrg 	    {
    227      1.1  mrg 	      /* Break out of the loop.  */
    228      1.1  mrg 	      base = NULL;
    229      1.1  mrg 	      break;
    230      1.1  mrg 	    }
    231      1.1  mrg 	  else
    232      1.1  mrg 	    {
    233      1.1  mrg 	      count[n]++;
    234      1.1  mrg 	      base += sstride[n];
    235      1.1  mrg 	      mbase += mstride[n];
    236      1.1  mrg 	    }
    237      1.1  mrg 	}
    238      1.1  mrg       while (count[n] == extent[n]);
    239      1.1  mrg     }
    240      1.1  mrg     memcpy (ret, retval, len * sizeof (*ret));
    241      1.1  mrg   }
    242      1.1  mrg }
    243      1.1  mrg 
    244      1.1  mrg 
    245      1.1  mrg extern void sminval0_s4 (GFC_UINTEGER_4 * restrict,
    246      1.1  mrg         gfc_charlen_type,
    247      1.1  mrg 	gfc_array_s4 * const restrict array, GFC_LOGICAL_4 *, gfc_charlen_type);
    248      1.1  mrg export_proto(sminval0_s4);
    249      1.1  mrg 
    250      1.1  mrg void
    251      1.1  mrg sminval0_s4 (GFC_UINTEGER_4 * restrict ret,
    252      1.1  mrg         gfc_charlen_type xlen, gfc_array_s4 * const restrict array,
    253      1.1  mrg 	GFC_LOGICAL_4 *mask, gfc_charlen_type len)
    254      1.1  mrg 
    255      1.1  mrg {
    256      1.1  mrg   if (mask == NULL || *mask)
    257      1.1  mrg     {
    258      1.1  mrg       minval0_s4 (ret, xlen, array, len);
    259      1.1  mrg       return;
    260      1.1  mrg     }
    261      1.1  mrg   memset (ret, INITVAL, sizeof (*ret) * len);
    262      1.1  mrg }
    263      1.1  mrg 
    264      1.1  mrg #endif
    265