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