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