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