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