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