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