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 dnl 6 1.1 mrg dnl Pass the implementation for a single section as the parameter to 7 1.1 mrg dnl {MASK_}ARRAY_FUNCTION. 8 1.1 mrg dnl The variables base, delta, and len describe the input section. 9 1.1 mrg dnl For masked section the mask is described by mbase and mdelta. 10 1.1 mrg dnl These should not be modified. The result should be stored in *dest. 11 1.1 mrg dnl The names count, extent, sstride, dstride, base, dest, rank, dim 12 1.1 mrg dnl retarray, array, pdim and mstride should not be used. 13 1.1 mrg dnl The variable n is declared as index_type and may be used. 14 1.1 mrg dnl Other variable declarations may be placed at the start of the code, 15 1.1 mrg dnl The types of the array parameter and the return value are 16 1.1 mrg dnl atype_name and rtype_name respectively. 17 1.1 mrg dnl Execution should be allowed to continue to the end of the block. 18 1.1 mrg dnl You should not return or break from the inner loop of the implementation. 19 1.1 mrg dnl Care should also be taken to avoid using the names defined in iparm.m4 20 1.1 mrg define(START_ARRAY_FUNCTION, 21 1.1 mrg `#include <string.h> 22 1.1 mrg #include <assert.h> 23 1.1 mrg 24 1.1 mrg static inline int 25 1.1 mrg compare_fcn (const atype_name *a, const atype_name *b, gfc_charlen_type n) 26 1.1 mrg { 27 1.1 mrg if (sizeof ('atype_name`) == 1) 28 1.1 mrg return memcmp (a, b, n); 29 1.1 mrg else 30 1.1 mrg return memcmp_char4 (a, b, n); 31 1.1 mrg } 32 1.1 mrg 33 1.1 mrg extern void name`'rtype_qual`_'atype_code (rtype * const restrict, 34 1.1 mrg gfc_charlen_type, atype * const restrict, 35 1.1 mrg const index_type * const restrict, gfc_charlen_type); 36 1.1 mrg export_proto(name`'rtype_qual`_'atype_code); 37 1.1 mrg 38 1.1 mrg void 39 1.1 mrg name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 40 1.1 mrg gfc_charlen_type xlen, atype * const restrict array, 41 1.1 mrg const index_type * const restrict pdim, gfc_charlen_type string_len) 42 1.1 mrg { 43 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 44 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 45 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 46 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS]; 47 1.1 mrg const atype_name * restrict base; 48 1.1 mrg rtype_name * restrict dest; 49 1.1 mrg index_type rank; 50 1.1 mrg index_type n; 51 1.1 mrg index_type len; 52 1.1 mrg index_type delta; 53 1.1 mrg index_type dim; 54 1.1 mrg int continue_loop; 55 1.1 mrg 56 1.1 mrg assert (xlen == string_len); 57 1.1 mrg /* Make dim zero based to avoid confusion. */ 58 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1; 59 1.1 mrg dim = (*pdim) - 1; 60 1.1 mrg 61 1.1 mrg if (unlikely (dim < 0 || dim > rank)) 62 1.1 mrg { 63 1.1 mrg runtime_error ("Dim argument incorrect in u_name intrinsic: " 64 1.1 mrg "is %ld, should be between 1 and %ld", 65 1.1 mrg (long int) dim + 1, (long int) rank + 1); 66 1.1 mrg } 67 1.1 mrg 68 1.1 mrg len = GFC_DESCRIPTOR_EXTENT(array,dim); 69 1.1 mrg if (len < 0) 70 1.1 mrg len = 0; 71 1.1 mrg 72 1.1 mrg delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len; 73 1.1 mrg 74 1.1 mrg for (n = 0; n < dim; n++) 75 1.1 mrg { 76 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len; 77 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 78 1.1 mrg 79 1.1 mrg if (extent[n] < 0) 80 1.1 mrg extent[n] = 0; 81 1.1 mrg } 82 1.1 mrg for (n = dim; n < rank; n++) 83 1.1 mrg { 84 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len; 85 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1); 86 1.1 mrg 87 1.1 mrg if (extent[n] < 0) 88 1.1 mrg extent[n] = 0; 89 1.1 mrg } 90 1.1 mrg 91 1.1 mrg if (retarray->base_addr == NULL) 92 1.1 mrg { 93 1.1 mrg size_t alloc_size, str; 94 1.1 mrg 95 1.1 mrg for (n = 0; n < rank; n++) 96 1.1 mrg { 97 1.1 mrg if (n == 0) 98 1.1 mrg str = 1; 99 1.1 mrg else 100 1.1 mrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; 101 1.1 mrg 102 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); 103 1.1 mrg 104 1.1 mrg } 105 1.1 mrg 106 1.1 mrg retarray->offset = 0; 107 1.1 mrg retarray->dtype.rank = rank; 108 1.1 mrg 109 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1] 110 1.1 mrg * string_len; 111 1.1 mrg 112 1.1 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name)); 113 1.1 mrg if (alloc_size == 0) 114 1.1.1.2 mrg return; 115 1.1 mrg } 116 1.1 mrg else 117 1.1 mrg { 118 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray)) 119 1.1 mrg runtime_error ("rank of return array incorrect in" 120 1.1 mrg " u_name intrinsic: is %ld, should be %ld", 121 1.1 mrg (long int) (GFC_DESCRIPTOR_RANK (retarray)), 122 1.1 mrg (long int) rank); 123 1.1 mrg 124 1.1 mrg if (unlikely (compile_options.bounds_check)) 125 1.1 mrg bounds_ifunction_return ((array_t *) retarray, extent, 126 1.1 mrg "return value", "u_name"); 127 1.1 mrg } 128 1.1 mrg 129 1.1 mrg for (n = 0; n < rank; n++) 130 1.1 mrg { 131 1.1 mrg count[n] = 0; 132 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len; 133 1.1 mrg if (extent[n] <= 0) 134 1.1 mrg return; 135 1.1 mrg } 136 1.1 mrg 137 1.1 mrg base = array->base_addr; 138 1.1 mrg dest = retarray->base_addr; 139 1.1 mrg 140 1.1 mrg continue_loop = 1; 141 1.1 mrg while (continue_loop) 142 1.1 mrg { 143 1.1 mrg const atype_name * restrict src; 144 1.1 mrg src = base; 145 1.1 mrg { 146 1.1 mrg ')dnl 147 1.1 mrg define(START_ARRAY_BLOCK, 148 1.1 mrg ` if (len <= 0) 149 1.1 mrg memset (dest, '$1`, sizeof (*dest) * string_len); 150 1.1 mrg else 151 1.1 mrg { 152 1.1 mrg for (n = 0; n < len; n++, src += delta) 153 1.1 mrg { 154 1.1 mrg ')dnl 155 1.1 mrg define(FINISH_ARRAY_FUNCTION, 156 1.1 mrg ` } 157 1.1 mrg '$1` 158 1.1 mrg memcpy (dest, retval, sizeof (*dest) * string_len); 159 1.1 mrg } 160 1.1 mrg } 161 1.1 mrg /* Advance to the next element. */ 162 1.1 mrg count[0]++; 163 1.1 mrg base += sstride[0]; 164 1.1 mrg dest += dstride[0]; 165 1.1 mrg n = 0; 166 1.1 mrg while (count[n] == extent[n]) 167 1.1 mrg { 168 1.1 mrg /* When we get to the end of a dimension, reset it and increment 169 1.1 mrg the next dimension. */ 170 1.1 mrg count[n] = 0; 171 1.1 mrg /* We could precalculate these products, but this is a less 172 1.1 mrg frequently used path so probably not worth it. */ 173 1.1 mrg base -= sstride[n] * extent[n]; 174 1.1 mrg dest -= dstride[n] * extent[n]; 175 1.1 mrg n++; 176 1.1 mrg if (n >= rank) 177 1.1 mrg { 178 1.1 mrg /* Break out of the loop. */ 179 1.1 mrg continue_loop = 0; 180 1.1 mrg break; 181 1.1 mrg } 182 1.1 mrg else 183 1.1 mrg { 184 1.1 mrg count[n]++; 185 1.1 mrg base += sstride[n]; 186 1.1 mrg dest += dstride[n]; 187 1.1 mrg } 188 1.1 mrg } 189 1.1 mrg } 190 1.1 mrg }')dnl 191 1.1 mrg define(START_MASKED_ARRAY_FUNCTION, 192 1.1 mrg ` 193 1.1 mrg extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict, 194 1.1 mrg gfc_charlen_type, atype * const restrict, 195 1.1 mrg const index_type * const restrict, 196 1.1 mrg gfc_array_l1 * const restrict, gfc_charlen_type); 197 1.1 mrg export_proto(`m'name`'rtype_qual`_'atype_code); 198 1.1 mrg 199 1.1 mrg void 200 1.1 mrg `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 201 1.1 mrg gfc_charlen_type xlen, atype * const restrict array, 202 1.1 mrg const index_type * const restrict pdim, 203 1.1 mrg gfc_array_l1 * const restrict mask, 204 1.1 mrg gfc_charlen_type string_len) 205 1.1 mrg 206 1.1 mrg { 207 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 208 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 209 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 210 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS]; 211 1.1 mrg index_type mstride[GFC_MAX_DIMENSIONS]; 212 1.1 mrg rtype_name * restrict dest; 213 1.1 mrg const atype_name * restrict base; 214 1.1 mrg const GFC_LOGICAL_1 * restrict mbase; 215 1.1 mrg index_type rank; 216 1.1 mrg index_type dim; 217 1.1 mrg index_type n; 218 1.1 mrg index_type len; 219 1.1 mrg index_type delta; 220 1.1 mrg index_type mdelta; 221 1.1 mrg int mask_kind; 222 1.1 mrg 223 1.1 mrg if (mask == NULL) 224 1.1 mrg { 225 1.1 mrg name`'rtype_qual`_'atype_code (retarray, xlen, array, pdim, string_len); 226 1.1 mrg return; 227 1.1 mrg } 228 1.1 mrg 229 1.1 mrg assert (xlen == string_len); 230 1.1 mrg 231 1.1 mrg dim = (*pdim) - 1; 232 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1; 233 1.1 mrg 234 1.1 mrg if (unlikely (dim < 0 || dim > rank)) 235 1.1 mrg { 236 1.1 mrg runtime_error ("Dim argument incorrect in u_name intrinsic: " 237 1.1 mrg "is %ld, should be between 1 and %ld", 238 1.1 mrg (long int) dim + 1, (long int) rank + 1); 239 1.1 mrg } 240 1.1 mrg 241 1.1 mrg len = GFC_DESCRIPTOR_EXTENT(array,dim); 242 1.1.1.2 mrg if (len < 0) 243 1.1.1.2 mrg len = 0; 244 1.1 mrg 245 1.1 mrg mbase = mask->base_addr; 246 1.1 mrg 247 1.1 mrg mask_kind = GFC_DESCRIPTOR_SIZE (mask); 248 1.1 mrg 249 1.1 mrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8 250 1.1 mrg #ifdef HAVE_GFC_LOGICAL_16 251 1.1 mrg || mask_kind == 16 252 1.1 mrg #endif 253 1.1 mrg ) 254 1.1 mrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind); 255 1.1 mrg else 256 1.1 mrg runtime_error ("Funny sized logical array"); 257 1.1 mrg 258 1.1 mrg delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len; 259 1.1 mrg mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim); 260 1.1 mrg 261 1.1 mrg for (n = 0; n < dim; n++) 262 1.1 mrg { 263 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len; 264 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n); 265 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 266 1.1 mrg 267 1.1 mrg if (extent[n] < 0) 268 1.1 mrg extent[n] = 0; 269 1.1 mrg 270 1.1 mrg } 271 1.1 mrg for (n = dim; n < rank; n++) 272 1.1 mrg { 273 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len; 274 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1); 275 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1); 276 1.1 mrg 277 1.1 mrg if (extent[n] < 0) 278 1.1 mrg extent[n] = 0; 279 1.1 mrg } 280 1.1 mrg 281 1.1 mrg if (retarray->base_addr == NULL) 282 1.1 mrg { 283 1.1 mrg size_t alloc_size, str; 284 1.1 mrg 285 1.1 mrg for (n = 0; n < rank; n++) 286 1.1 mrg { 287 1.1 mrg if (n == 0) 288 1.1 mrg str = 1; 289 1.1 mrg else 290 1.1 mrg str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; 291 1.1 mrg 292 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); 293 1.1 mrg 294 1.1 mrg } 295 1.1 mrg 296 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1] 297 1.1 mrg * string_len; 298 1.1 mrg 299 1.1 mrg retarray->offset = 0; 300 1.1 mrg retarray->dtype.rank = rank; 301 1.1 mrg 302 1.1.1.2 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name)); 303 1.1 mrg if (alloc_size == 0) 304 1.1.1.2 mrg return; 305 1.1 mrg } 306 1.1 mrg else 307 1.1 mrg { 308 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray)) 309 1.1 mrg runtime_error ("rank of return array incorrect in u_name intrinsic"); 310 1.1 mrg 311 1.1 mrg if (unlikely (compile_options.bounds_check)) 312 1.1 mrg { 313 1.1 mrg bounds_ifunction_return ((array_t *) retarray, extent, 314 1.1 mrg "return value", "u_name"); 315 1.1 mrg bounds_equal_extents ((array_t *) mask, (array_t *) array, 316 1.1 mrg "MASK argument", "u_name"); 317 1.1 mrg } 318 1.1 mrg } 319 1.1 mrg 320 1.1 mrg for (n = 0; n < rank; n++) 321 1.1 mrg { 322 1.1 mrg count[n] = 0; 323 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len; 324 1.1 mrg if (extent[n] <= 0) 325 1.1 mrg return; 326 1.1 mrg } 327 1.1 mrg 328 1.1 mrg dest = retarray->base_addr; 329 1.1 mrg base = array->base_addr; 330 1.1 mrg 331 1.1 mrg while (base) 332 1.1 mrg { 333 1.1 mrg const atype_name * restrict src; 334 1.1 mrg const GFC_LOGICAL_1 * restrict msrc; 335 1.1 mrg 336 1.1 mrg src = base; 337 1.1 mrg msrc = mbase; 338 1.1 mrg { 339 1.1 mrg ')dnl 340 1.1 mrg define(START_MASKED_ARRAY_BLOCK, 341 1.1 mrg ` for (n = 0; n < len; n++, src += delta, msrc += mdelta) 342 1.1 mrg { 343 1.1 mrg ')dnl 344 1.1 mrg define(FINISH_MASKED_ARRAY_FUNCTION, 345 1.1 mrg ` } 346 1.1 mrg memcpy (dest, retval, sizeof (*dest) * string_len); 347 1.1 mrg } 348 1.1 mrg /* Advance to the next element. */ 349 1.1 mrg count[0]++; 350 1.1 mrg base += sstride[0]; 351 1.1 mrg mbase += mstride[0]; 352 1.1 mrg dest += dstride[0]; 353 1.1 mrg n = 0; 354 1.1 mrg while (count[n] == extent[n]) 355 1.1 mrg { 356 1.1 mrg /* When we get to the end of a dimension, reset it and increment 357 1.1 mrg the next dimension. */ 358 1.1 mrg count[n] = 0; 359 1.1 mrg /* We could precalculate these products, but this is a less 360 1.1 mrg frequently used path so probably not worth it. */ 361 1.1 mrg base -= sstride[n] * extent[n]; 362 1.1 mrg mbase -= mstride[n] * extent[n]; 363 1.1 mrg dest -= dstride[n] * extent[n]; 364 1.1 mrg n++; 365 1.1 mrg if (n >= rank) 366 1.1 mrg { 367 1.1 mrg /* Break out of the loop. */ 368 1.1 mrg base = NULL; 369 1.1 mrg break; 370 1.1 mrg } 371 1.1 mrg else 372 1.1 mrg { 373 1.1 mrg count[n]++; 374 1.1 mrg base += sstride[n]; 375 1.1 mrg mbase += mstride[n]; 376 1.1 mrg dest += dstride[n]; 377 1.1 mrg } 378 1.1 mrg } 379 1.1 mrg } 380 1.1 mrg }')dnl 381 1.1 mrg define(SCALAR_ARRAY_FUNCTION, 382 1.1 mrg ` 383 1.1 mrg void `s'name`'rtype_qual`_'atype_code (rtype * const restrict, 384 1.1 mrg gfc_charlen_type, atype * const restrict, 385 1.1 mrg const index_type * const restrict, 386 1.1 mrg GFC_LOGICAL_4 *, gfc_charlen_type); 387 1.1 mrg 388 1.1 mrg export_proto(`s'name`'rtype_qual`_'atype_code); 389 1.1 mrg 390 1.1 mrg void 391 1.1 mrg `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 392 1.1 mrg gfc_charlen_type xlen, atype * const restrict array, 393 1.1 mrg const index_type * const restrict pdim, 394 1.1 mrg GFC_LOGICAL_4 *mask, gfc_charlen_type string_len) 395 1.1 mrg 396 1.1 mrg { 397 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 398 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 399 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS]; 400 1.1 mrg rtype_name * restrict dest; 401 1.1 mrg index_type rank; 402 1.1 mrg index_type n; 403 1.1 mrg index_type dim; 404 1.1 mrg 405 1.1 mrg 406 1.1 mrg if (mask == NULL || *mask) 407 1.1 mrg { 408 1.1 mrg name`'rtype_qual`_'atype_code (retarray, xlen, array, pdim, string_len); 409 1.1 mrg return; 410 1.1 mrg } 411 1.1 mrg /* Make dim zero based to avoid confusion. */ 412 1.1 mrg dim = (*pdim) - 1; 413 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1; 414 1.1 mrg 415 1.1 mrg if (unlikely (dim < 0 || dim > rank)) 416 1.1 mrg { 417 1.1 mrg runtime_error ("Dim argument incorrect in u_name intrinsic: " 418 1.1 mrg "is %ld, should be between 1 and %ld", 419 1.1 mrg (long int) dim + 1, (long int) rank + 1); 420 1.1 mrg } 421 1.1 mrg 422 1.1 mrg for (n = 0; n < dim; n++) 423 1.1 mrg { 424 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 425 1.1 mrg 426 1.1 mrg if (extent[n] <= 0) 427 1.1 mrg extent[n] = 0; 428 1.1 mrg } 429 1.1 mrg 430 1.1 mrg for (n = dim; n < rank; n++) 431 1.1 mrg { 432 1.1 mrg extent[n] = 433 1.1 mrg GFC_DESCRIPTOR_EXTENT(array,n + 1); 434 1.1 mrg 435 1.1 mrg if (extent[n] <= 0) 436 1.1 mrg extent[n] = 0; 437 1.1 mrg } 438 1.1 mrg 439 1.1 mrg if (retarray->base_addr == NULL) 440 1.1 mrg { 441 1.1 mrg size_t alloc_size, str; 442 1.1 mrg 443 1.1 mrg for (n = 0; n < rank; n++) 444 1.1 mrg { 445 1.1 mrg if (n == 0) 446 1.1 mrg str = 1; 447 1.1 mrg else 448 1.1 mrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; 449 1.1 mrg 450 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); 451 1.1 mrg 452 1.1 mrg } 453 1.1 mrg 454 1.1 mrg retarray->offset = 0; 455 1.1 mrg retarray->dtype.rank = rank; 456 1.1 mrg 457 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1] 458 1.1 mrg * string_len; 459 1.1 mrg 460 1.1.1.2 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name)); 461 1.1 mrg if (alloc_size == 0) 462 1.1.1.2 mrg return; 463 1.1 mrg } 464 1.1 mrg else 465 1.1 mrg { 466 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray)) 467 1.1 mrg runtime_error ("rank of return array incorrect in" 468 1.1 mrg " u_name intrinsic: is %ld, should be %ld", 469 1.1 mrg (long int) (GFC_DESCRIPTOR_RANK (retarray)), 470 1.1 mrg (long int) rank); 471 1.1 mrg 472 1.1 mrg if (unlikely (compile_options.bounds_check)) 473 1.1 mrg { 474 1.1 mrg for (n=0; n < rank; n++) 475 1.1 mrg { 476 1.1 mrg index_type ret_extent; 477 1.1 mrg 478 1.1 mrg ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n); 479 1.1 mrg if (extent[n] != ret_extent) 480 1.1 mrg runtime_error ("Incorrect extent in return value of" 481 1.1 mrg " u_name intrinsic in dimension %ld:" 482 1.1 mrg " is %ld, should be %ld", (long int) n + 1, 483 1.1 mrg (long int) ret_extent, (long int) extent[n]); 484 1.1 mrg } 485 1.1 mrg } 486 1.1 mrg } 487 1.1 mrg 488 1.1 mrg for (n = 0; n < rank; n++) 489 1.1 mrg { 490 1.1 mrg count[n] = 0; 491 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len; 492 1.1 mrg } 493 1.1 mrg 494 1.1 mrg dest = retarray->base_addr; 495 1.1 mrg 496 1.1 mrg while(1) 497 1.1 mrg { 498 1.1 mrg memset (dest, '$1`, sizeof (*dest) * string_len); 499 1.1 mrg count[0]++; 500 1.1 mrg dest += dstride[0]; 501 1.1 mrg n = 0; 502 1.1 mrg while (count[n] == extent[n]) 503 1.1 mrg { 504 1.1 mrg /* When we get to the end of a dimension, reset it and increment 505 1.1 mrg the next dimension. */ 506 1.1 mrg count[n] = 0; 507 1.1 mrg /* We could precalculate these products, but this is a less 508 1.1 mrg frequently used path so probably not worth it. */ 509 1.1 mrg dest -= dstride[n] * extent[n]; 510 1.1 mrg n++; 511 1.1 mrg if (n >= rank) 512 1.1 mrg return; 513 1.1 mrg else 514 1.1 mrg { 515 1.1 mrg count[n]++; 516 1.1 mrg dest += dstride[n]; 517 1.1 mrg } 518 1.1 mrg } 519 1.1 mrg } 520 1.1 mrg }')dnl 521 1.1 mrg define(ARRAY_FUNCTION, 522 1.1 mrg `START_ARRAY_FUNCTION($1) 523 1.1 mrg $2 524 1.1 mrg START_ARRAY_BLOCK($1) 525 1.1 mrg $3 526 1.1 mrg FINISH_ARRAY_FUNCTION($4)')dnl 527 1.1 mrg define(MASKED_ARRAY_FUNCTION, 528 1.1 mrg `START_MASKED_ARRAY_FUNCTION 529 1.1 mrg $2 530 1.1 mrg START_MASKED_ARRAY_BLOCK 531 1.1 mrg $3 532 1.1 mrg FINISH_MASKED_ARRAY_FUNCTION')dnl 533