1 1.1 mrg /* Implementation of the ALL intrinsic 2 1.1.1.4 mrg Copyright (C) 2002-2024 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Paul Brook <paul (at) nowt.org> 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 28 1.1 mrg 29 1.1 mrg #if defined (HAVE_GFC_LOGICAL_4) 30 1.1 mrg 31 1.1 mrg 32 1.1 mrg extern void all_l4 (gfc_array_l4 * const restrict, 33 1.1 mrg gfc_array_l1 * const restrict, const index_type * const restrict); 34 1.1 mrg export_proto(all_l4); 35 1.1 mrg 36 1.1 mrg void 37 1.1 mrg all_l4 (gfc_array_l4 * const restrict retarray, 38 1.1 mrg gfc_array_l1 * const restrict array, 39 1.1 mrg const index_type * const restrict pdim) 40 1.1 mrg { 41 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 42 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 43 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 44 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS]; 45 1.1 mrg const GFC_LOGICAL_1 * restrict base; 46 1.1 mrg GFC_LOGICAL_4 * restrict dest; 47 1.1 mrg index_type rank; 48 1.1 mrg index_type n; 49 1.1 mrg index_type len; 50 1.1 mrg index_type delta; 51 1.1 mrg index_type dim; 52 1.1 mrg int src_kind; 53 1.1 mrg int continue_loop; 54 1.1 mrg 55 1.1 mrg /* Make dim zero based to avoid confusion. */ 56 1.1 mrg dim = (*pdim) - 1; 57 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1; 58 1.1 mrg 59 1.1 mrg src_kind = GFC_DESCRIPTOR_SIZE (array); 60 1.1 mrg 61 1.1 mrg len = GFC_DESCRIPTOR_EXTENT(array,dim); 62 1.1 mrg if (len < 0) 63 1.1 mrg len = 0; 64 1.1 mrg 65 1.1 mrg delta = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim); 66 1.1 mrg 67 1.1 mrg for (n = 0; n < dim; n++) 68 1.1 mrg { 69 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n); 70 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 71 1.1 mrg 72 1.1 mrg if (extent[n] < 0) 73 1.1 mrg extent[n] = 0; 74 1.1 mrg } 75 1.1 mrg for (n = dim; n < rank; n++) 76 1.1 mrg { 77 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n + 1); 78 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); 79 1.1 mrg 80 1.1 mrg if (extent[n] < 0) 81 1.1 mrg extent[n] = 0; 82 1.1 mrg } 83 1.1 mrg 84 1.1 mrg if (retarray->base_addr == NULL) 85 1.1 mrg { 86 1.1 mrg size_t alloc_size, str; 87 1.1 mrg 88 1.1 mrg for (n = 0; n < rank; n++) 89 1.1 mrg { 90 1.1 mrg if (n == 0) 91 1.1 mrg str = 1; 92 1.1 mrg else 93 1.1 mrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; 94 1.1 mrg 95 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); 96 1.1 mrg 97 1.1 mrg } 98 1.1 mrg 99 1.1 mrg retarray->offset = 0; 100 1.1 mrg retarray->dtype.rank = rank; 101 1.1 mrg 102 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]; 103 1.1 mrg 104 1.1.1.4 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_LOGICAL_4)); 105 1.1 mrg if (alloc_size == 0) 106 1.1.1.4 mrg return; 107 1.1 mrg } 108 1.1 mrg else 109 1.1 mrg { 110 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray)) 111 1.1 mrg runtime_error ("rank of return array incorrect in" 112 1.1 mrg " ALL intrinsic: is %ld, should be %ld", 113 1.1 mrg (long int) GFC_DESCRIPTOR_RANK (retarray), 114 1.1 mrg (long int) rank); 115 1.1 mrg 116 1.1 mrg if (unlikely (compile_options.bounds_check)) 117 1.1 mrg { 118 1.1 mrg for (n=0; n < rank; n++) 119 1.1 mrg { 120 1.1 mrg index_type ret_extent; 121 1.1 mrg 122 1.1 mrg ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n); 123 1.1 mrg if (extent[n] != ret_extent) 124 1.1 mrg runtime_error ("Incorrect extent in return value of" 125 1.1 mrg " ALL intrinsic in dimension %d:" 126 1.1 mrg " is %ld, should be %ld", (int) n + 1, 127 1.1 mrg (long int) ret_extent, (long int) extent[n]); 128 1.1 mrg } 129 1.1 mrg } 130 1.1 mrg } 131 1.1 mrg 132 1.1 mrg for (n = 0; n < rank; n++) 133 1.1 mrg { 134 1.1 mrg count[n] = 0; 135 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n); 136 1.1 mrg if (extent[n] <= 0) 137 1.1 mrg return; 138 1.1 mrg } 139 1.1 mrg 140 1.1 mrg base = array->base_addr; 141 1.1 mrg 142 1.1 mrg if (src_kind == 1 || src_kind == 2 || src_kind == 4 || src_kind == 8 143 1.1 mrg #ifdef HAVE_GFC_LOGICAL_16 144 1.1 mrg || src_kind == 16 145 1.1 mrg #endif 146 1.1 mrg ) 147 1.1 mrg { 148 1.1 mrg if (base) 149 1.1 mrg base = GFOR_POINTER_TO_L1 (base, src_kind); 150 1.1 mrg } 151 1.1 mrg else 152 1.1 mrg internal_error (NULL, "Funny sized logical array in ALL intrinsic"); 153 1.1 mrg 154 1.1 mrg dest = retarray->base_addr; 155 1.1 mrg 156 1.1 mrg continue_loop = 1; 157 1.1 mrg while (continue_loop) 158 1.1 mrg { 159 1.1 mrg const GFC_LOGICAL_1 * restrict src; 160 1.1 mrg GFC_LOGICAL_4 result; 161 1.1 mrg src = base; 162 1.1 mrg { 163 1.1 mrg 164 1.1 mrg /* Return true only if all the elements are set. */ 165 1.1 mrg result = 1; 166 1.1 mrg if (len <= 0) 167 1.1 mrg *dest = 1; 168 1.1 mrg else 169 1.1 mrg { 170 1.1 mrg for (n = 0; n < len; n++, src += delta) 171 1.1 mrg { 172 1.1 mrg 173 1.1 mrg if (! *src) 174 1.1 mrg { 175 1.1 mrg result = 0; 176 1.1 mrg break; 177 1.1 mrg } 178 1.1 mrg } 179 1.1 mrg *dest = result; 180 1.1 mrg } 181 1.1 mrg } 182 1.1 mrg /* Advance to the next element. */ 183 1.1 mrg count[0]++; 184 1.1 mrg base += sstride[0]; 185 1.1 mrg dest += dstride[0]; 186 1.1 mrg n = 0; 187 1.1 mrg while (count[n] == extent[n]) 188 1.1 mrg { 189 1.1 mrg /* When we get to the end of a dimension, reset it and increment 190 1.1 mrg the next dimension. */ 191 1.1 mrg count[n] = 0; 192 1.1 mrg /* We could precalculate these products, but this is a less 193 1.1 mrg frequently used path so probably not worth it. */ 194 1.1 mrg base -= sstride[n] * extent[n]; 195 1.1 mrg dest -= dstride[n] * extent[n]; 196 1.1 mrg n++; 197 1.1 mrg if (n >= rank) 198 1.1 mrg { 199 1.1 mrg /* Break out of the loop. */ 200 1.1 mrg continue_loop = 0; 201 1.1 mrg break; 202 1.1 mrg } 203 1.1 mrg else 204 1.1 mrg { 205 1.1 mrg count[n]++; 206 1.1 mrg base += sstride[n]; 207 1.1 mrg dest += dstride[n]; 208 1.1 mrg } 209 1.1 mrg } 210 1.1 mrg } 211 1.1 mrg } 212 1.1 mrg 213 1.1 mrg #endif 214