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 31 1.1 mrg #if defined (HAVE_GFC_UINTEGER_4) && defined (HAVE_GFC_INTEGER_4) 32 1.1 mrg 33 1.1 mrg static inline int 34 1.1 mrg compare_fcn (const GFC_UINTEGER_4 *a, const GFC_UINTEGER_4 *b, gfc_charlen_type n) 35 1.1 mrg { 36 1.1 mrg if (sizeof (GFC_UINTEGER_4) == 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_4 maxloc2_4_s4 (gfc_array_s4 * const restrict, GFC_LOGICAL_4 back, 43 1.1 mrg gfc_charlen_type); 44 1.1 mrg export_proto(maxloc2_4_s4); 45 1.1 mrg 46 1.1 mrg GFC_INTEGER_4 47 1.1 mrg maxloc2_4_s4 (gfc_array_s4 * 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_4 *src; 53 1.1 mrg const GFC_UINTEGER_4 *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_4 mmaxloc2_4_s4 (gfc_array_s4 * 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_4_s4); 82 1.1 mrg 83 1.1 mrg GFC_INTEGER_4 84 1.1 mrg mmaxloc2_4_s4 (gfc_array_s4 * 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_4 *src; 92 1.1 mrg const GFC_UINTEGER_4 *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_4 smaxloc2_4_s4 (gfc_array_s4 * const restrict, 148 1.1 mrg GFC_LOGICAL_4 *mask, GFC_LOGICAL_4 back, gfc_charlen_type); 149 1.1 mrg export_proto(smaxloc2_4_s4); 150 1.1 mrg 151 1.1 mrg GFC_INTEGER_4 152 1.1 mrg smaxloc2_4_s4 (gfc_array_s4 * 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.3 mrg if (mask == NULL || *mask) 156 1.1.1.3 mrg return maxloc2_4_s4 (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