Home | History | Annotate | Line # | Download | only in generated
      1      1.1  mrg /* Implementation of the MAXLOC intrinsic
      2  1.1.1.5  mrg    Copyright (C) 2017-2024 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 
     31      1.1  mrg #if defined (HAVE_GFC_UINTEGER_1) && defined (HAVE_GFC_INTEGER_16)
     32      1.1  mrg 
     33      1.1  mrg static inline int
     34      1.1  mrg compare_fcn (const GFC_UINTEGER_1 *a, const GFC_UINTEGER_1 *b, gfc_charlen_type n)
     35      1.1  mrg {
     36      1.1  mrg   if (sizeof (GFC_UINTEGER_1) == 1)
     37      1.1  mrg     return memcmp (a, b, n);
     38      1.1  mrg   else
     39      1.1  mrg     return memcmp_char4 (a, b, n);
     40      1.1  mrg }
     41      1.1  mrg 
     42      1.1  mrg extern GFC_INTEGER_16 maxloc2_16_s1 (gfc_array_s1 * const restrict, GFC_LOGICAL_4 back,
     43      1.1  mrg        gfc_charlen_type);
     44      1.1  mrg export_proto(maxloc2_16_s1);
     45      1.1  mrg 
     46      1.1  mrg GFC_INTEGER_16
     47      1.1  mrg maxloc2_16_s1 (gfc_array_s1 * const restrict array, GFC_LOGICAL_4 back, gfc_charlen_type len)
     48      1.1  mrg {
     49      1.1  mrg   index_type ret;
     50      1.1  mrg   index_type sstride;
     51      1.1  mrg   index_type extent;
     52      1.1  mrg   const GFC_UINTEGER_1 *src;
     53      1.1  mrg   const GFC_UINTEGER_1 *maxval;
     54      1.1  mrg   index_type i;
     55      1.1  mrg 
     56      1.1  mrg   extent = GFC_DESCRIPTOR_EXTENT(array,0);
     57      1.1  mrg   if (extent <= 0)
     58      1.1  mrg     return 0;
     59      1.1  mrg 
     60      1.1  mrg   sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
     61      1.1  mrg 
     62      1.1  mrg   ret = 1;
     63      1.1  mrg   src = array->base_addr;
     64      1.1  mrg   maxval = NULL;
     65      1.1  mrg   for (i=1; i<=extent; i++)
     66      1.1  mrg     {
     67      1.1  mrg       if (maxval == NULL || (back ? compare_fcn (src, maxval, len) >= 0 :
     68      1.1  mrg       	 	    	    	    compare_fcn (src, maxval, len) > 0))
     69      1.1  mrg       {
     70      1.1  mrg 	 ret = i;
     71      1.1  mrg 	 maxval = src;
     72      1.1  mrg       }
     73      1.1  mrg       src += sstride;
     74      1.1  mrg     }
     75      1.1  mrg   return ret;
     76      1.1  mrg }
     77      1.1  mrg 
     78      1.1  mrg extern GFC_INTEGER_16 mmaxloc2_16_s1 (gfc_array_s1 * const restrict,
     79      1.1  mrg        		    	gfc_array_l1 *const restrict mask, GFC_LOGICAL_4 back,
     80      1.1  mrg 			gfc_charlen_type);
     81      1.1  mrg export_proto(mmaxloc2_16_s1);
     82      1.1  mrg 
     83      1.1  mrg GFC_INTEGER_16
     84      1.1  mrg mmaxloc2_16_s1 (gfc_array_s1 * const restrict array,
     85      1.1  mrg 				 gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back,
     86      1.1  mrg 				 gfc_charlen_type len)
     87      1.1  mrg {
     88      1.1  mrg   index_type ret;
     89      1.1  mrg   index_type sstride;
     90      1.1  mrg   index_type extent;
     91      1.1  mrg   const GFC_UINTEGER_1 *src;
     92      1.1  mrg   const GFC_UINTEGER_1 *maxval;
     93      1.1  mrg   index_type i, j;
     94      1.1  mrg   GFC_LOGICAL_1 *mbase;
     95      1.1  mrg   int mask_kind;
     96      1.1  mrg   index_type mstride;
     97      1.1  mrg 
     98      1.1  mrg   extent = GFC_DESCRIPTOR_EXTENT(array,0);
     99      1.1  mrg   if (extent <= 0)
    100      1.1  mrg     return 0;
    101      1.1  mrg 
    102      1.1  mrg   sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
    103      1.1  mrg 
    104      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    105      1.1  mrg   mbase = mask->base_addr;
    106      1.1  mrg 
    107      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    108      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    109      1.1  mrg       || mask_kind == 16
    110      1.1  mrg #endif
    111      1.1  mrg       )
    112      1.1  mrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    113      1.1  mrg   else
    114      1.1  mrg     internal_error (NULL, "Funny sized logical array");
    115      1.1  mrg 
    116      1.1  mrg   mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
    117      1.1  mrg 
    118      1.1  mrg   /* Search for the first occurrence of a true element in mask. */
    119      1.1  mrg   for (j=0; j<extent; j++)
    120      1.1  mrg     {
    121      1.1  mrg       if (*mbase)
    122      1.1  mrg         break;
    123      1.1  mrg       mbase += mstride;
    124      1.1  mrg     }
    125      1.1  mrg 
    126      1.1  mrg   if (j == extent)
    127      1.1  mrg     return 0;
    128      1.1  mrg 
    129      1.1  mrg   ret = j + 1;
    130      1.1  mrg   src = array->base_addr + j * sstride;
    131      1.1  mrg   maxval = src;
    132      1.1  mrg 
    133      1.1  mrg   for (i=j+1; i<=extent; i++)
    134      1.1  mrg     {
    135      1.1  mrg       if (*mbase && (back ? compare_fcn (src, maxval, len) >= 0 :
    136      1.1  mrg       	 	    	   compare_fcn (src, maxval, len) > 0))
    137      1.1  mrg       {
    138      1.1  mrg 	 ret = i;
    139      1.1  mrg 	 maxval = src;
    140      1.1  mrg       }
    141      1.1  mrg       src += sstride;
    142      1.1  mrg       mbase += mstride;
    143      1.1  mrg     }
    144      1.1  mrg   return ret;
    145      1.1  mrg }
    146      1.1  mrg 
    147      1.1  mrg extern GFC_INTEGER_16 smaxloc2_16_s1 (gfc_array_s1 * const restrict,
    148      1.1  mrg                                GFC_LOGICAL_4 *mask, GFC_LOGICAL_4 back, gfc_charlen_type);
    149      1.1  mrg export_proto(smaxloc2_16_s1);
    150      1.1  mrg 
    151      1.1  mrg GFC_INTEGER_16
    152      1.1  mrg smaxloc2_16_s1 (gfc_array_s1 * const restrict array,
    153      1.1  mrg 				 GFC_LOGICAL_4 *mask, GFC_LOGICAL_4 back, gfc_charlen_type len)
    154      1.1  mrg {
    155  1.1.1.4  mrg   if (mask == NULL || *mask)
    156  1.1.1.4  mrg     return maxloc2_16_s1 (array, back, len);
    157      1.1  mrg   else
    158      1.1  mrg     return 0;
    159      1.1  mrg }
    160      1.1  mrg 
    161      1.1  mrg #endif
    162