1 1.1 mrg dnl Support macro file for intrinsic functions. 2 1.1 mrg dnl Contains the generic sections of the array functions. 3 1.1 mrg dnl This file is part of the GNU Fortran Runtime Library (libgfortran) 4 1.1 mrg dnl Distributed under the GNU GPL with exception. See COPYING for details. 5 1.1 mrg define(START_FOREACH_FUNCTION, 6 1.1 mrg `static inline int 7 1.1 mrg compare_fcn (const atype_name *a, const atype_name *b, gfc_charlen_type n) 8 1.1 mrg { 9 1.1 mrg if (sizeof ('atype_name`) == 1) 10 1.1 mrg return memcmp (a, b, n); 11 1.1 mrg else 12 1.1 mrg return memcmp_char4 (a, b, n); 13 1.1 mrg 14 1.1 mrg } 15 1.1 mrg 16 1.1 mrg extern void name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 17 1.1 mrg 'atype` * const restrict array'back_arg`, gfc_charlen_type len); 18 1.1 mrg export_proto('name`'rtype_qual`_'atype_code); 19 1.1 mrg 20 1.1 mrg void 21 1.1 mrg name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 22 1.1 mrg 'atype` * const restrict array'back_arg`, gfc_charlen_type len) 23 1.1 mrg { 24 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 25 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 26 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 27 1.1 mrg index_type dstride; 28 1.1 mrg const 'atype_name *base; 29 1.1 mrg rtype_name * restrict dest; 30 1.1 mrg index_type rank; 31 1.1 mrg index_type n; 32 1.1 mrg 33 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array); 34 1.1 mrg if (rank <= 0) 35 1.1 mrg runtime_error ("Rank of array needs to be > 0"); 36 1.1 mrg 37 1.1 mrg if (retarray->base_addr == NULL) 38 1.1 mrg { 39 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1); 40 1.1 mrg retarray->dtype.rank = 1; 41 1.1 mrg retarray->offset = 0; 42 1.1 mrg retarray->base_addr = xmallocarray (rank, sizeof (rtype_name)); 43 1.1 mrg } 44 1.1 mrg else 45 1.1 mrg { 46 1.1 mrg if (unlikely (compile_options.bounds_check)) 47 1.1 mrg bounds_iforeach_return ((array_t *) retarray, (array_t *) array, 48 1.1 mrg "u_name"); 49 1.1 mrg } 50 1.1 mrg 51 1.1 mrg dstride = GFC_DESCRIPTOR_STRIDE(retarray,0); 52 1.1 mrg dest = retarray->base_addr; 53 1.1 mrg for (n = 0; n < rank; n++) 54 1.1 mrg { 55 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len; 56 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 57 1.1 mrg count[n] = 0; 58 1.1 mrg if (extent[n] <= 0) 59 1.1 mrg { 60 1.1 mrg /* Set the return value. */ 61 1.1 mrg for (n = 0; n < rank; n++) 62 1.1 mrg dest[n * dstride] = 0; 63 1.1 mrg return; 64 1.1 mrg } 65 1.1 mrg } 66 1.1 mrg 67 1.1 mrg base = array->base_addr; 68 1.1 mrg 69 1.1 mrg /* Initialize the return value. */ 70 1.1 mrg for (n = 0; n < rank; n++) 71 1.1 mrg dest[n * dstride] = 1; 72 1.1 mrg { 73 1.1 mrg ')dnl 74 1.1 mrg define(START_FOREACH_BLOCK, 75 1.1 mrg ` while (base) 76 1.1 mrg { 77 1.1 mrg do 78 1.1 mrg { 79 1.1 mrg /* Implementation start. */ 80 1.1 mrg ')dnl 81 1.1 mrg define(FINISH_FOREACH_FUNCTION, 82 1.1 mrg ` /* Implementation end. */ 83 1.1 mrg /* Advance to the next element. */ 84 1.1 mrg base += sstride[0]; 85 1.1 mrg } 86 1.1 mrg while (++count[0] != extent[0]); 87 1.1 mrg n = 0; 88 1.1 mrg do 89 1.1 mrg { 90 1.1 mrg /* When we get to the end of a dimension, reset it and increment 91 1.1 mrg the next dimension. */ 92 1.1 mrg count[n] = 0; 93 1.1 mrg /* We could precalculate these products, but this is a less 94 1.1 mrg frequently used path so probably not worth it. */ 95 1.1 mrg base -= sstride[n] * extent[n]; 96 1.1 mrg n++; 97 1.1 mrg if (n >= rank) 98 1.1 mrg { 99 1.1 mrg /* Break out of the loop. */ 100 1.1 mrg base = NULL; 101 1.1 mrg break; 102 1.1 mrg } 103 1.1 mrg else 104 1.1 mrg { 105 1.1 mrg count[n]++; 106 1.1 mrg base += sstride[n]; 107 1.1 mrg } 108 1.1 mrg } 109 1.1 mrg while (count[n] == extent[n]); 110 1.1 mrg } 111 1.1 mrg } 112 1.1 mrg }')dnl 113 1.1 mrg define(START_MASKED_FOREACH_FUNCTION, 114 1.1 mrg ` 115 1.1 mrg extern void `m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict, 116 1.1 mrg 'atype` * const restrict, gfc_array_l1 * const restrict 'back_arg`, 117 1.1 mrg gfc_charlen_type len); 118 1.1 mrg export_proto(m'name`'rtype_qual`_'atype_code`); 119 1.1 mrg 120 1.1 mrg void 121 1.1 mrg m'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 122 1.1 mrg 'atype` * const restrict array, 123 1.1 mrg gfc_array_l1 * const restrict mask'back_arg`, 124 1.1 mrg gfc_charlen_type len) 125 1.1 mrg { 126 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 127 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 128 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 129 1.1 mrg index_type mstride[GFC_MAX_DIMENSIONS]; 130 1.1 mrg index_type dstride; 131 1.1 mrg 'rtype_name *dest; 132 1.1 mrg const atype_name *base; 133 1.1 mrg GFC_LOGICAL_1 *mbase; 134 1.1 mrg int rank; 135 1.1 mrg index_type n; 136 1.1 mrg int mask_kind; 137 1.1 mrg 138 1.1 mrg if (mask == NULL) 139 1.1 mrg { 140 1.1 mrg #ifdef HAVE_BACK_ARG 141 1.1 mrg name`'rtype_qual`_'atype_code (retarray, array, back, len); 142 1.1 mrg #else 143 1.1 mrg name`'rtype_qual`_'atype_code (retarray, array, len); 144 1.1 mrg #endif 145 1.1 mrg return; 146 1.1 mrg } 147 1.1 mrg 148 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array); 149 1.1 mrg if (rank <= 0) 150 1.1 mrg runtime_error ("Rank of array needs to be > 0"); 151 1.1 mrg 152 1.1 mrg if (retarray->base_addr == NULL) 153 1.1 mrg { 154 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1); 155 1.1 mrg retarray->dtype.rank = 1; 156 1.1 mrg retarray->offset = 0; 157 1.1 mrg retarray->base_addr = xmallocarray (rank, sizeof (rtype_name)); 158 1.1 mrg } 159 1.1 mrg else 160 1.1 mrg { 161 1.1 mrg if (unlikely (compile_options.bounds_check)) 162 1.1 mrg { 163 1.1 mrg 164 1.1 mrg bounds_iforeach_return ((array_t *) retarray, (array_t *) array, 165 1.1 mrg "u_name"); 166 1.1 mrg bounds_equal_extents ((array_t *) mask, (array_t *) array, 167 1.1 mrg "MASK argument", "u_name"); 168 1.1 mrg } 169 1.1 mrg } 170 1.1 mrg 171 1.1 mrg mask_kind = GFC_DESCRIPTOR_SIZE (mask); 172 1.1 mrg 173 1.1 mrg mbase = mask->base_addr; 174 1.1 mrg 175 1.1 mrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8 176 1.1 mrg #ifdef HAVE_GFC_LOGICAL_16 177 1.1 mrg || mask_kind == 16 178 1.1 mrg #endif 179 1.1 mrg ) 180 1.1 mrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind); 181 1.1 mrg else 182 1.1 mrg runtime_error ("Funny sized logical array"); 183 1.1 mrg 184 1.1 mrg dstride = GFC_DESCRIPTOR_STRIDE(retarray,0); 185 1.1 mrg dest = retarray->base_addr; 186 1.1 mrg for (n = 0; n < rank; n++) 187 1.1 mrg { 188 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len; 189 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n); 190 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 191 1.1 mrg count[n] = 0; 192 1.1 mrg if (extent[n] <= 0) 193 1.1 mrg { 194 1.1 mrg /* Set the return value. */ 195 1.1 mrg for (n = 0; n < rank; n++) 196 1.1 mrg dest[n * dstride] = 0; 197 1.1 mrg return; 198 1.1 mrg } 199 1.1 mrg } 200 1.1 mrg 201 1.1 mrg base = array->base_addr; 202 1.1 mrg 203 1.1 mrg /* Initialize the return value. */ 204 1.1 mrg for (n = 0; n < rank; n++) 205 1.1 mrg dest[n * dstride] = 0; 206 1.1 mrg { 207 1.1 mrg ')dnl 208 1.1 mrg define(START_MASKED_FOREACH_BLOCK, `START_FOREACH_BLOCK')dnl 209 1.1 mrg define(FINISH_MASKED_FOREACH_FUNCTION, 210 1.1 mrg ` /* Implementation end. */ 211 1.1 mrg /* Advance to the next element. */ 212 1.1 mrg base += sstride[0]; 213 1.1 mrg mbase += mstride[0]; 214 1.1 mrg } 215 1.1 mrg while (++count[0] != extent[0]); 216 1.1 mrg n = 0; 217 1.1 mrg do 218 1.1 mrg { 219 1.1 mrg /* When we get to the end of a dimension, reset it and increment 220 1.1 mrg the next dimension. */ 221 1.1 mrg count[n] = 0; 222 1.1 mrg /* We could precalculate these products, but this is a less 223 1.1 mrg frequently used path so probably not worth it. */ 224 1.1 mrg base -= sstride[n] * extent[n]; 225 1.1 mrg mbase -= mstride[n] * extent[n]; 226 1.1 mrg n++; 227 1.1 mrg if (n >= rank) 228 1.1 mrg { 229 1.1 mrg /* Break out of the loop. */ 230 1.1 mrg base = NULL; 231 1.1 mrg break; 232 1.1 mrg } 233 1.1 mrg else 234 1.1 mrg { 235 1.1 mrg count[n]++; 236 1.1 mrg base += sstride[n]; 237 1.1 mrg mbase += mstride[n]; 238 1.1 mrg } 239 1.1 mrg } 240 1.1 mrg while (count[n] == extent[n]); 241 1.1 mrg } 242 1.1 mrg } 243 1.1 mrg }')dnl 244 1.1 mrg define(FOREACH_FUNCTION, 245 1.1 mrg `START_FOREACH_FUNCTION 246 1.1 mrg $1 247 1.1 mrg START_FOREACH_BLOCK 248 1.1 mrg $2 249 1.1 mrg FINISH_FOREACH_FUNCTION')dnl 250 1.1 mrg define(MASKED_FOREACH_FUNCTION, 251 1.1 mrg `START_MASKED_FOREACH_FUNCTION 252 1.1 mrg $1 253 1.1 mrg START_MASKED_FOREACH_BLOCK 254 1.1 mrg $2 255 1.1 mrg FINISH_MASKED_FOREACH_FUNCTION')dnl 256 1.1 mrg define(SCALAR_FOREACH_FUNCTION, 257 1.1 mrg ` 258 1.1 mrg extern void `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict, 259 1.1 mrg 'atype` * const restrict, GFC_LOGICAL_4 *'back_arg`, 260 1.1 mrg gfc_charlen_type len); 261 1.1 mrg export_proto(s'name`'rtype_qual`_'atype_code); 262 1.1 mrg 263 1.1 mrg void 264 1.1 mrg `s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, 265 1.1 mrg 'atype` * const restrict array, 266 1.1 mrg GFC_LOGICAL_4 * mask'back_arg`, 267 1.1 mrg gfc_charlen_type len) 268 1.1 mrg { 269 1.1 mrg index_type rank; 270 1.1 mrg index_type dstride; 271 1.1 mrg index_type n; 272 1.1 mrg 'rtype_name *dest; 273 1.1 mrg 274 1.1 mrg if (mask == NULL || *mask) 275 1.1 mrg { 276 1.1 mrg #ifdef HAVE_BACK_ARG 277 1.1 mrg name`'rtype_qual`_'atype_code (retarray, array, back, len); 278 1.1 mrg #else 279 1.1 mrg name`'rtype_qual`_'atype_code (retarray, array, len); 280 1.1 mrg #endif 281 1.1 mrg return; 282 1.1 mrg } 283 1.1 mrg 284 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array); 285 1.1 mrg 286 1.1 mrg if (rank <= 0) 287 1.1 mrg runtime_error ("Rank of array needs to be > 0"); 288 1.1 mrg 289 1.1 mrg if (retarray->base_addr == NULL) 290 1.1 mrg { 291 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1); 292 1.1 mrg retarray->dtype.rank = 1; 293 1.1 mrg retarray->offset = 0; 294 1.1 mrg retarray->base_addr = xmallocarray (rank, sizeof (rtype_name)); 295 1.1 mrg } 296 1.1 mrg else if (unlikely (compile_options.bounds_check)) 297 1.1 mrg { 298 1.1 mrg bounds_iforeach_return ((array_t *) retarray, (array_t *) array, 299 1.1 mrg "u_name"); 300 1.1 mrg } 301 1.1 mrg 302 1.1 mrg dstride = GFC_DESCRIPTOR_STRIDE(retarray,0); 303 1.1 mrg dest = retarray->base_addr; 304 1.1 mrg for (n = 0; n<rank; n++) 305 1.1 mrg dest[n * dstride] = $1 ; 306 1.1 mrg }')dnl 307