1 1.1 mrg /* Implementation of the MINLOC intrinsic 2 1.1.1.3 mrg Copyright (C) 2002-2022 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 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 #include <assert.h> 28 1.1 mrg 29 1.1 mrg 30 1.1 mrg #if defined (HAVE_GFC_INTEGER_8) && defined (HAVE_GFC_INTEGER_8) 31 1.1 mrg 32 1.1 mrg #define HAVE_BACK_ARG 1 33 1.1 mrg 34 1.1 mrg 35 1.1 mrg extern void minloc1_8_i8 (gfc_array_i8 * const restrict, 36 1.1 mrg gfc_array_i8 * const restrict, const index_type * const restrict, GFC_LOGICAL_4 back); 37 1.1 mrg export_proto(minloc1_8_i8); 38 1.1 mrg 39 1.1 mrg void 40 1.1 mrg minloc1_8_i8 (gfc_array_i8 * const restrict retarray, 41 1.1 mrg gfc_array_i8 * const restrict array, 42 1.1 mrg const index_type * const restrict pdim, GFC_LOGICAL_4 back) 43 1.1 mrg { 44 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 45 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 46 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 47 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS]; 48 1.1 mrg const GFC_INTEGER_8 * restrict base; 49 1.1 mrg GFC_INTEGER_8 * restrict dest; 50 1.1 mrg index_type rank; 51 1.1 mrg index_type n; 52 1.1 mrg index_type len; 53 1.1 mrg index_type delta; 54 1.1 mrg index_type dim; 55 1.1 mrg int continue_loop; 56 1.1 mrg 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 MINLOC 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 delta = GFC_DESCRIPTOR_STRIDE(array,dim); 72 1.1 mrg 73 1.1 mrg for (n = 0; n < dim; n++) 74 1.1 mrg { 75 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n); 76 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 77 1.1 mrg 78 1.1 mrg if (extent[n] < 0) 79 1.1 mrg extent[n] = 0; 80 1.1 mrg } 81 1.1 mrg for (n = dim; n < rank; n++) 82 1.1 mrg { 83 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1); 84 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1); 85 1.1 mrg 86 1.1 mrg if (extent[n] < 0) 87 1.1 mrg extent[n] = 0; 88 1.1 mrg } 89 1.1 mrg 90 1.1 mrg if (retarray->base_addr == NULL) 91 1.1 mrg { 92 1.1 mrg size_t alloc_size, str; 93 1.1 mrg 94 1.1 mrg for (n = 0; n < rank; n++) 95 1.1 mrg { 96 1.1 mrg if (n == 0) 97 1.1 mrg str = 1; 98 1.1 mrg else 99 1.1 mrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; 100 1.1 mrg 101 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); 102 1.1 mrg 103 1.1 mrg } 104 1.1 mrg 105 1.1 mrg retarray->offset = 0; 106 1.1 mrg retarray->dtype.rank = rank; 107 1.1 mrg 108 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]; 109 1.1 mrg 110 1.1 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8)); 111 1.1 mrg if (alloc_size == 0) 112 1.1 mrg { 113 1.1 mrg /* Make sure we have a zero-sized array. */ 114 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1); 115 1.1 mrg return; 116 1.1 mrg 117 1.1 mrg } 118 1.1 mrg } 119 1.1 mrg else 120 1.1 mrg { 121 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray)) 122 1.1 mrg runtime_error ("rank of return array incorrect in" 123 1.1 mrg " MINLOC intrinsic: is %ld, should be %ld", 124 1.1 mrg (long int) (GFC_DESCRIPTOR_RANK (retarray)), 125 1.1 mrg (long int) rank); 126 1.1 mrg 127 1.1 mrg if (unlikely (compile_options.bounds_check)) 128 1.1 mrg bounds_ifunction_return ((array_t *) retarray, extent, 129 1.1 mrg "return value", "MINLOC"); 130 1.1 mrg } 131 1.1 mrg 132 1.1 mrg for (n = 0; n < rank; n++) 133 1.1 mrg { 134 1.1 mrg count[n] = 0; 135 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n); 136 1.1 mrg if (extent[n] <= 0) 137 1.1 mrg return; 138 1.1 mrg } 139 1.1 mrg 140 1.1 mrg base = array->base_addr; 141 1.1 mrg dest = retarray->base_addr; 142 1.1 mrg 143 1.1 mrg continue_loop = 1; 144 1.1 mrg while (continue_loop) 145 1.1 mrg { 146 1.1 mrg const GFC_INTEGER_8 * restrict src; 147 1.1 mrg GFC_INTEGER_8 result; 148 1.1 mrg src = base; 149 1.1 mrg { 150 1.1 mrg 151 1.1 mrg GFC_INTEGER_8 minval; 152 1.1 mrg #if defined (GFC_INTEGER_8_INFINITY) 153 1.1 mrg minval = GFC_INTEGER_8_INFINITY; 154 1.1 mrg #else 155 1.1 mrg minval = GFC_INTEGER_8_HUGE; 156 1.1 mrg #endif 157 1.1 mrg result = 1; 158 1.1 mrg if (len <= 0) 159 1.1 mrg *dest = 0; 160 1.1 mrg else 161 1.1 mrg { 162 1.1 mrg #if ! defined HAVE_BACK_ARG 163 1.1 mrg for (n = 0; n < len; n++, src += delta) 164 1.1 mrg { 165 1.1 mrg #endif 166 1.1 mrg 167 1.1 mrg #if defined (GFC_INTEGER_8_QUIET_NAN) 168 1.1 mrg for (n = 0; n < len; n++, src += delta) 169 1.1 mrg { 170 1.1 mrg if (*src <= minval) 171 1.1 mrg { 172 1.1 mrg minval = *src; 173 1.1 mrg result = (GFC_INTEGER_8)n + 1; 174 1.1 mrg break; 175 1.1 mrg } 176 1.1 mrg } 177 1.1 mrg #else 178 1.1 mrg n = 0; 179 1.1 mrg #endif 180 1.1 mrg if (back) 181 1.1 mrg for (; n < len; n++, src += delta) 182 1.1 mrg { 183 1.1 mrg if (unlikely (*src <= minval)) 184 1.1 mrg { 185 1.1 mrg minval = *src; 186 1.1 mrg result = (GFC_INTEGER_8)n + 1; 187 1.1 mrg } 188 1.1 mrg } 189 1.1 mrg else 190 1.1 mrg for (; n < len; n++, src += delta) 191 1.1 mrg { 192 1.1 mrg if (unlikely (*src < minval)) 193 1.1 mrg { 194 1.1 mrg minval = *src; 195 1.1 mrg result = (GFC_INTEGER_8) n + 1; 196 1.1 mrg } 197 1.1 mrg } 198 1.1 mrg 199 1.1 mrg *dest = result; 200 1.1 mrg } 201 1.1 mrg } 202 1.1 mrg /* Advance to the next element. */ 203 1.1 mrg count[0]++; 204 1.1 mrg base += sstride[0]; 205 1.1 mrg dest += dstride[0]; 206 1.1 mrg n = 0; 207 1.1 mrg while (count[n] == extent[n]) 208 1.1 mrg { 209 1.1 mrg /* When we get to the end of a dimension, reset it and increment 210 1.1 mrg the next dimension. */ 211 1.1 mrg count[n] = 0; 212 1.1 mrg /* We could precalculate these products, but this is a less 213 1.1 mrg frequently used path so probably not worth it. */ 214 1.1 mrg base -= sstride[n] * extent[n]; 215 1.1 mrg dest -= dstride[n] * extent[n]; 216 1.1 mrg n++; 217 1.1 mrg if (n >= rank) 218 1.1 mrg { 219 1.1 mrg /* Break out of the loop. */ 220 1.1 mrg continue_loop = 0; 221 1.1 mrg break; 222 1.1 mrg } 223 1.1 mrg else 224 1.1 mrg { 225 1.1 mrg count[n]++; 226 1.1 mrg base += sstride[n]; 227 1.1 mrg dest += dstride[n]; 228 1.1 mrg } 229 1.1 mrg } 230 1.1 mrg } 231 1.1 mrg } 232 1.1 mrg 233 1.1 mrg 234 1.1 mrg extern void mminloc1_8_i8 (gfc_array_i8 * const restrict, 235 1.1 mrg gfc_array_i8 * const restrict, const index_type * const restrict, 236 1.1 mrg gfc_array_l1 * const restrict, GFC_LOGICAL_4 back); 237 1.1 mrg export_proto(mminloc1_8_i8); 238 1.1 mrg 239 1.1 mrg void 240 1.1 mrg mminloc1_8_i8 (gfc_array_i8 * const restrict retarray, 241 1.1 mrg gfc_array_i8 * const restrict array, 242 1.1 mrg const index_type * const restrict pdim, 243 1.1 mrg gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back) 244 1.1 mrg { 245 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 246 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 247 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 248 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS]; 249 1.1 mrg index_type mstride[GFC_MAX_DIMENSIONS]; 250 1.1 mrg GFC_INTEGER_8 * restrict dest; 251 1.1 mrg const GFC_INTEGER_8 * restrict base; 252 1.1 mrg const GFC_LOGICAL_1 * restrict mbase; 253 1.1 mrg index_type rank; 254 1.1 mrg index_type dim; 255 1.1 mrg index_type n; 256 1.1 mrg index_type len; 257 1.1 mrg index_type delta; 258 1.1 mrg index_type mdelta; 259 1.1 mrg int mask_kind; 260 1.1 mrg 261 1.1 mrg if (mask == NULL) 262 1.1 mrg { 263 1.1 mrg #ifdef HAVE_BACK_ARG 264 1.1 mrg minloc1_8_i8 (retarray, array, pdim, back); 265 1.1 mrg #else 266 1.1 mrg minloc1_8_i8 (retarray, array, pdim); 267 1.1 mrg #endif 268 1.1 mrg return; 269 1.1 mrg } 270 1.1 mrg 271 1.1 mrg dim = (*pdim) - 1; 272 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1; 273 1.1 mrg 274 1.1 mrg 275 1.1 mrg if (unlikely (dim < 0 || dim > rank)) 276 1.1 mrg { 277 1.1 mrg runtime_error ("Dim argument incorrect in MINLOC intrinsic: " 278 1.1 mrg "is %ld, should be between 1 and %ld", 279 1.1 mrg (long int) dim + 1, (long int) rank + 1); 280 1.1 mrg } 281 1.1 mrg 282 1.1 mrg len = GFC_DESCRIPTOR_EXTENT(array,dim); 283 1.1 mrg if (len <= 0) 284 1.1 mrg return; 285 1.1 mrg 286 1.1 mrg mbase = mask->base_addr; 287 1.1 mrg 288 1.1 mrg mask_kind = GFC_DESCRIPTOR_SIZE (mask); 289 1.1 mrg 290 1.1 mrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8 291 1.1 mrg #ifdef HAVE_GFC_LOGICAL_16 292 1.1 mrg || mask_kind == 16 293 1.1 mrg #endif 294 1.1 mrg ) 295 1.1 mrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind); 296 1.1 mrg else 297 1.1 mrg runtime_error ("Funny sized logical array"); 298 1.1 mrg 299 1.1 mrg delta = GFC_DESCRIPTOR_STRIDE(array,dim); 300 1.1 mrg mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim); 301 1.1 mrg 302 1.1 mrg for (n = 0; n < dim; n++) 303 1.1 mrg { 304 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n); 305 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n); 306 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 307 1.1 mrg 308 1.1 mrg if (extent[n] < 0) 309 1.1 mrg extent[n] = 0; 310 1.1 mrg 311 1.1 mrg } 312 1.1 mrg for (n = dim; n < rank; n++) 313 1.1 mrg { 314 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1); 315 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1); 316 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1); 317 1.1 mrg 318 1.1 mrg if (extent[n] < 0) 319 1.1 mrg extent[n] = 0; 320 1.1 mrg } 321 1.1 mrg 322 1.1 mrg if (retarray->base_addr == NULL) 323 1.1 mrg { 324 1.1 mrg size_t alloc_size, str; 325 1.1 mrg 326 1.1 mrg for (n = 0; n < rank; n++) 327 1.1 mrg { 328 1.1 mrg if (n == 0) 329 1.1 mrg str = 1; 330 1.1 mrg else 331 1.1 mrg str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; 332 1.1 mrg 333 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); 334 1.1 mrg 335 1.1 mrg } 336 1.1 mrg 337 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]; 338 1.1 mrg 339 1.1 mrg retarray->offset = 0; 340 1.1 mrg retarray->dtype.rank = rank; 341 1.1 mrg 342 1.1 mrg if (alloc_size == 0) 343 1.1 mrg { 344 1.1 mrg /* Make sure we have a zero-sized array. */ 345 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1); 346 1.1 mrg return; 347 1.1 mrg } 348 1.1 mrg else 349 1.1 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8)); 350 1.1 mrg 351 1.1 mrg } 352 1.1 mrg else 353 1.1 mrg { 354 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray)) 355 1.1 mrg runtime_error ("rank of return array incorrect in MINLOC intrinsic"); 356 1.1 mrg 357 1.1 mrg if (unlikely (compile_options.bounds_check)) 358 1.1 mrg { 359 1.1 mrg bounds_ifunction_return ((array_t *) retarray, extent, 360 1.1 mrg "return value", "MINLOC"); 361 1.1 mrg bounds_equal_extents ((array_t *) mask, (array_t *) array, 362 1.1 mrg "MASK argument", "MINLOC"); 363 1.1 mrg } 364 1.1 mrg } 365 1.1 mrg 366 1.1 mrg for (n = 0; n < rank; n++) 367 1.1 mrg { 368 1.1 mrg count[n] = 0; 369 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n); 370 1.1 mrg if (extent[n] <= 0) 371 1.1 mrg return; 372 1.1 mrg } 373 1.1 mrg 374 1.1 mrg dest = retarray->base_addr; 375 1.1 mrg base = array->base_addr; 376 1.1 mrg 377 1.1 mrg while (base) 378 1.1 mrg { 379 1.1 mrg const GFC_INTEGER_8 * restrict src; 380 1.1 mrg const GFC_LOGICAL_1 * restrict msrc; 381 1.1 mrg GFC_INTEGER_8 result; 382 1.1 mrg src = base; 383 1.1 mrg msrc = mbase; 384 1.1 mrg { 385 1.1 mrg 386 1.1 mrg GFC_INTEGER_8 minval; 387 1.1 mrg #if defined (GFC_INTEGER_8_INFINITY) 388 1.1 mrg minval = GFC_INTEGER_8_INFINITY; 389 1.1 mrg #else 390 1.1 mrg minval = GFC_INTEGER_8_HUGE; 391 1.1 mrg #endif 392 1.1 mrg #if defined (GFC_INTEGER_8_QUIET_NAN) 393 1.1 mrg GFC_INTEGER_8 result2 = 0; 394 1.1 mrg #endif 395 1.1 mrg result = 0; 396 1.1 mrg for (n = 0; n < len; n++, src += delta, msrc += mdelta) 397 1.1 mrg { 398 1.1 mrg 399 1.1 mrg if (*msrc) 400 1.1 mrg { 401 1.1 mrg #if defined (GFC_INTEGER_8_QUIET_NAN) 402 1.1 mrg if (!result2) 403 1.1 mrg result2 = (GFC_INTEGER_8)n + 1; 404 1.1 mrg if (*src <= minval) 405 1.1 mrg #endif 406 1.1 mrg { 407 1.1 mrg minval = *src; 408 1.1 mrg result = (GFC_INTEGER_8)n + 1; 409 1.1 mrg break; 410 1.1 mrg } 411 1.1 mrg } 412 1.1 mrg } 413 1.1 mrg #if defined (GFC_INTEGER_8_QUIET_NAN) 414 1.1 mrg if (unlikely (n >= len)) 415 1.1 mrg result = result2; 416 1.1 mrg else 417 1.1 mrg #endif 418 1.1 mrg if (back) 419 1.1 mrg for (; n < len; n++, src += delta, msrc += mdelta) 420 1.1 mrg { 421 1.1 mrg if (*msrc && unlikely (*src <= minval)) 422 1.1 mrg { 423 1.1 mrg minval = *src; 424 1.1 mrg result = (GFC_INTEGER_8)n + 1; 425 1.1 mrg } 426 1.1 mrg } 427 1.1 mrg else 428 1.1 mrg for (; n < len; n++, src += delta, msrc += mdelta) 429 1.1 mrg { 430 1.1 mrg if (*msrc && unlikely (*src < minval)) 431 1.1 mrg { 432 1.1 mrg minval = *src; 433 1.1 mrg result = (GFC_INTEGER_8) n + 1; 434 1.1 mrg } 435 1.1 mrg } 436 1.1 mrg *dest = result; 437 1.1 mrg } 438 1.1 mrg /* Advance to the next element. */ 439 1.1 mrg count[0]++; 440 1.1 mrg base += sstride[0]; 441 1.1 mrg mbase += mstride[0]; 442 1.1 mrg dest += dstride[0]; 443 1.1 mrg n = 0; 444 1.1 mrg while (count[n] == extent[n]) 445 1.1 mrg { 446 1.1 mrg /* When we get to the end of a dimension, reset it and increment 447 1.1 mrg the next dimension. */ 448 1.1 mrg count[n] = 0; 449 1.1 mrg /* We could precalculate these products, but this is a less 450 1.1 mrg frequently used path so probably not worth it. */ 451 1.1 mrg base -= sstride[n] * extent[n]; 452 1.1 mrg mbase -= mstride[n] * extent[n]; 453 1.1 mrg dest -= dstride[n] * extent[n]; 454 1.1 mrg n++; 455 1.1 mrg if (n >= rank) 456 1.1 mrg { 457 1.1 mrg /* Break out of the loop. */ 458 1.1 mrg base = NULL; 459 1.1 mrg break; 460 1.1 mrg } 461 1.1 mrg else 462 1.1 mrg { 463 1.1 mrg count[n]++; 464 1.1 mrg base += sstride[n]; 465 1.1 mrg mbase += mstride[n]; 466 1.1 mrg dest += dstride[n]; 467 1.1 mrg } 468 1.1 mrg } 469 1.1 mrg } 470 1.1 mrg } 471 1.1 mrg 472 1.1 mrg 473 1.1 mrg extern void sminloc1_8_i8 (gfc_array_i8 * const restrict, 474 1.1 mrg gfc_array_i8 * const restrict, const index_type * const restrict, 475 1.1 mrg GFC_LOGICAL_4 *, GFC_LOGICAL_4 back); 476 1.1 mrg export_proto(sminloc1_8_i8); 477 1.1 mrg 478 1.1 mrg void 479 1.1 mrg sminloc1_8_i8 (gfc_array_i8 * const restrict retarray, 480 1.1 mrg gfc_array_i8 * const restrict array, 481 1.1 mrg const index_type * const restrict pdim, 482 1.1 mrg GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back) 483 1.1 mrg { 484 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 485 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 486 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS]; 487 1.1 mrg GFC_INTEGER_8 * restrict dest; 488 1.1 mrg index_type rank; 489 1.1 mrg index_type n; 490 1.1 mrg index_type dim; 491 1.1 mrg 492 1.1 mrg 493 1.1 mrg if (mask == NULL || *mask) 494 1.1 mrg { 495 1.1 mrg #ifdef HAVE_BACK_ARG 496 1.1 mrg minloc1_8_i8 (retarray, array, pdim, back); 497 1.1 mrg #else 498 1.1 mrg minloc1_8_i8 (retarray, array, pdim); 499 1.1 mrg #endif 500 1.1 mrg return; 501 1.1 mrg } 502 1.1 mrg /* Make dim zero based to avoid confusion. */ 503 1.1 mrg dim = (*pdim) - 1; 504 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1; 505 1.1 mrg 506 1.1 mrg if (unlikely (dim < 0 || dim > rank)) 507 1.1 mrg { 508 1.1 mrg runtime_error ("Dim argument incorrect in MINLOC intrinsic: " 509 1.1 mrg "is %ld, should be between 1 and %ld", 510 1.1 mrg (long int) dim + 1, (long int) rank + 1); 511 1.1 mrg } 512 1.1 mrg 513 1.1 mrg for (n = 0; n < dim; n++) 514 1.1 mrg { 515 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 516 1.1 mrg 517 1.1 mrg if (extent[n] <= 0) 518 1.1 mrg extent[n] = 0; 519 1.1 mrg } 520 1.1 mrg 521 1.1 mrg for (n = dim; n < rank; n++) 522 1.1 mrg { 523 1.1 mrg extent[n] = 524 1.1 mrg GFC_DESCRIPTOR_EXTENT(array,n + 1); 525 1.1 mrg 526 1.1 mrg if (extent[n] <= 0) 527 1.1 mrg extent[n] = 0; 528 1.1 mrg } 529 1.1 mrg 530 1.1 mrg if (retarray->base_addr == NULL) 531 1.1 mrg { 532 1.1 mrg size_t alloc_size, str; 533 1.1 mrg 534 1.1 mrg for (n = 0; n < rank; n++) 535 1.1 mrg { 536 1.1 mrg if (n == 0) 537 1.1 mrg str = 1; 538 1.1 mrg else 539 1.1 mrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; 540 1.1 mrg 541 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); 542 1.1 mrg 543 1.1 mrg } 544 1.1 mrg 545 1.1 mrg retarray->offset = 0; 546 1.1 mrg retarray->dtype.rank = rank; 547 1.1 mrg 548 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]; 549 1.1 mrg 550 1.1 mrg if (alloc_size == 0) 551 1.1 mrg { 552 1.1 mrg /* Make sure we have a zero-sized array. */ 553 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1); 554 1.1 mrg return; 555 1.1 mrg } 556 1.1 mrg else 557 1.1 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8)); 558 1.1 mrg } 559 1.1 mrg else 560 1.1 mrg { 561 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray)) 562 1.1 mrg runtime_error ("rank of return array incorrect in" 563 1.1 mrg " MINLOC intrinsic: is %ld, should be %ld", 564 1.1 mrg (long int) (GFC_DESCRIPTOR_RANK (retarray)), 565 1.1 mrg (long int) rank); 566 1.1 mrg 567 1.1 mrg if (unlikely (compile_options.bounds_check)) 568 1.1 mrg { 569 1.1 mrg for (n=0; n < rank; n++) 570 1.1 mrg { 571 1.1 mrg index_type ret_extent; 572 1.1 mrg 573 1.1 mrg ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n); 574 1.1 mrg if (extent[n] != ret_extent) 575 1.1 mrg runtime_error ("Incorrect extent in return value of" 576 1.1 mrg " MINLOC intrinsic in dimension %ld:" 577 1.1 mrg " is %ld, should be %ld", (long int) n + 1, 578 1.1 mrg (long int) ret_extent, (long int) extent[n]); 579 1.1 mrg } 580 1.1 mrg } 581 1.1 mrg } 582 1.1 mrg 583 1.1 mrg for (n = 0; n < rank; n++) 584 1.1 mrg { 585 1.1 mrg count[n] = 0; 586 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n); 587 1.1 mrg } 588 1.1 mrg 589 1.1 mrg dest = retarray->base_addr; 590 1.1 mrg 591 1.1 mrg while(1) 592 1.1 mrg { 593 1.1 mrg *dest = 0; 594 1.1 mrg count[0]++; 595 1.1 mrg dest += dstride[0]; 596 1.1 mrg n = 0; 597 1.1 mrg while (count[n] == extent[n]) 598 1.1 mrg { 599 1.1 mrg /* When we get to the end of a dimension, reset it and increment 600 1.1 mrg the next dimension. */ 601 1.1 mrg count[n] = 0; 602 1.1 mrg /* We could precalculate these products, but this is a less 603 1.1 mrg frequently used path so probably not worth it. */ 604 1.1 mrg dest -= dstride[n] * extent[n]; 605 1.1 mrg n++; 606 1.1 mrg if (n >= rank) 607 1.1 mrg return; 608 1.1 mrg else 609 1.1 mrg { 610 1.1 mrg count[n]++; 611 1.1 mrg dest += dstride[n]; 612 1.1 mrg } 613 1.1 mrg } 614 1.1 mrg } 615 1.1 mrg } 616 1.1 mrg 617 1.1 mrg #endif 618