1 1.1 mrg /* Implementation of the MINLOC 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_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 minloc2_4_s4 (gfc_array_s4 * const restrict, GFC_LOGICAL_4 back, 43 1.1 mrg gfc_charlen_type); 44 1.1 mrg export_proto(minloc2_4_s4); 45 1.1 mrg 46 1.1 mrg GFC_INTEGER_4 47 1.1 mrg minloc2_4_s4 (gfc_array_s4 * 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_4 *src; 54 1.1 mrg const GFC_UINTEGER_4 *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_4 mminloc2_4_s4 (gfc_array_s4 * 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_4_s4); 83 1.1 mrg 84 1.1 mrg GFC_INTEGER_4 85 1.1 mrg mminloc2_4_s4 (gfc_array_s4 * 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_4 *src; 93 1.1 mrg const GFC_UINTEGER_4 *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_4 sminloc2_4_s4 (gfc_array_s4 * const restrict, 150 1.1 mrg GFC_LOGICAL_4 *mask, GFC_LOGICAL_4 back, gfc_charlen_type); 151 1.1 mrg export_proto(sminloc2_4_s4); 152 1.1 mrg 153 1.1 mrg GFC_INTEGER_4 154 1.1 mrg sminloc2_4_s4 (gfc_array_s4 * 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.4 mrg if (mask == NULL || *mask) 158 1.1.1.4 mrg return minloc2_4_s4 (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