Home | History | Annotate | Line # | Download | only in generated
maxloc2_4_s4.c revision 1.1.1.3
      1 /* Implementation of the MAXLOC intrinsic
      2    Copyright (C) 2017-2022 Free Software Foundation, Inc.
      3    Contributed by Thomas Koenig
      4 
      5 This file is part of the GNU Fortran runtime library (libgfortran).
      6 
      7 Libgfortran is free software; you can redistribute it and/or
      8 modify it under the terms of the GNU General Public
      9 License as published by the Free Software Foundation; either
     10 version 3 of the License, or (at your option) any later version.
     11 
     12 Libgfortran is distributed in the hope that it will be useful,
     13 but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 Under Section 7 of GPL version 3, you are granted additional
     18 permissions described in the GCC Runtime Library Exception, version
     19 3.1, as published by the Free Software Foundation.
     20 
     21 You should have received a copy of the GNU General Public License and
     22 a copy of the GCC Runtime Library Exception along with this program;
     23 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24 <http://www.gnu.org/licenses/>.  */
     25 
     26 #include "libgfortran.h"
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <assert.h>
     30 
     31 #if defined (HAVE_GFC_UINTEGER_4) && defined (HAVE_GFC_INTEGER_4)
     32 
     33 static inline int
     34 compare_fcn (const GFC_UINTEGER_4 *a, const GFC_UINTEGER_4 *b, gfc_charlen_type n)
     35 {
     36   if (sizeof (GFC_UINTEGER_4) == 1)
     37     return memcmp (a, b, n);
     38   else
     39     return memcmp_char4 (a, b, n);
     40 }
     41 
     42 extern GFC_INTEGER_4 maxloc2_4_s4 (gfc_array_s4 * const restrict, GFC_LOGICAL_4 back,
     43        gfc_charlen_type);
     44 export_proto(maxloc2_4_s4);
     45 
     46 GFC_INTEGER_4
     47 maxloc2_4_s4 (gfc_array_s4 * const restrict array, GFC_LOGICAL_4 back, gfc_charlen_type len)
     48 {
     49   index_type ret;
     50   index_type sstride;
     51   index_type extent;
     52   const GFC_UINTEGER_4 *src;
     53   const GFC_UINTEGER_4 *maxval;
     54   index_type i;
     55 
     56   extent = GFC_DESCRIPTOR_EXTENT(array,0);
     57   if (extent <= 0)
     58     return 0;
     59 
     60   sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
     61 
     62   ret = 1;
     63   src = array->base_addr;
     64   maxval = NULL;
     65   for (i=1; i<=extent; i++)
     66     {
     67       if (maxval == NULL || (back ? compare_fcn (src, maxval, len) >= 0 :
     68       	 	    	    	    compare_fcn (src, maxval, len) > 0))
     69       {
     70 	 ret = i;
     71 	 maxval = src;
     72       }
     73       src += sstride;
     74     }
     75   return ret;
     76 }
     77 
     78 extern GFC_INTEGER_4 mmaxloc2_4_s4 (gfc_array_s4 * const restrict,
     79        		    	gfc_array_l1 *const restrict mask, GFC_LOGICAL_4 back,
     80 			gfc_charlen_type);
     81 export_proto(mmaxloc2_4_s4);
     82 
     83 GFC_INTEGER_4
     84 mmaxloc2_4_s4 (gfc_array_s4 * const restrict array,
     85 				 gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back,
     86 				 gfc_charlen_type len)
     87 {
     88   index_type ret;
     89   index_type sstride;
     90   index_type extent;
     91   const GFC_UINTEGER_4 *src;
     92   const GFC_UINTEGER_4 *maxval;
     93   index_type i, j;
     94   GFC_LOGICAL_1 *mbase;
     95   int mask_kind;
     96   index_type mstride;
     97 
     98   extent = GFC_DESCRIPTOR_EXTENT(array,0);
     99   if (extent <= 0)
    100     return 0;
    101 
    102   sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
    103 
    104   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    105   mbase = mask->base_addr;
    106 
    107   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    108 #ifdef HAVE_GFC_LOGICAL_16
    109       || mask_kind == 16
    110 #endif
    111       )
    112     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    113   else
    114     internal_error (NULL, "Funny sized logical array");
    115 
    116   mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
    117 
    118   /* Search for the first occurrence of a true element in mask. */
    119   for (j=0; j<extent; j++)
    120     {
    121       if (*mbase)
    122         break;
    123       mbase += mstride;
    124     }
    125 
    126   if (j == extent)
    127     return 0;
    128 
    129   ret = j + 1;
    130   src = array->base_addr + j * sstride;
    131   maxval = src;
    132 
    133   for (i=j+1; i<=extent; i++)
    134     {
    135       if (*mbase && (back ? compare_fcn (src, maxval, len) >= 0 :
    136       	 	    	   compare_fcn (src, maxval, len) > 0))
    137       {
    138 	 ret = i;
    139 	 maxval = src;
    140       }
    141       src += sstride;
    142       mbase += mstride;
    143     }
    144   return ret;
    145 }
    146 
    147 extern GFC_INTEGER_4 smaxloc2_4_s4 (gfc_array_s4 * const restrict,
    148                                GFC_LOGICAL_4 *mask, GFC_LOGICAL_4 back, gfc_charlen_type);
    149 export_proto(smaxloc2_4_s4);
    150 
    151 GFC_INTEGER_4
    152 smaxloc2_4_s4 (gfc_array_s4 * const restrict array,
    153 				 GFC_LOGICAL_4 *mask, GFC_LOGICAL_4 back, gfc_charlen_type len)
    154 {
    155   if (mask)
    156     return maxloc2_4_s4 (array, len, back);
    157   else
    158     return 0;
    159 }
    160 
    161 #endif
    162