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