1 1.1 mrg /* Implementation of the MAXVAL 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 28 1.1 mrg 29 1.1 mrg #if defined (HAVE_GFC_REAL_16) && defined (HAVE_GFC_REAL_16) 30 1.1 mrg 31 1.1 mrg 32 1.1 mrg extern void maxval_r16 (gfc_array_r16 * const restrict, 33 1.1 mrg gfc_array_r16 * const restrict, const index_type * const restrict); 34 1.1 mrg export_proto(maxval_r16); 35 1.1 mrg 36 1.1 mrg void 37 1.1 mrg maxval_r16 (gfc_array_r16 * const restrict retarray, 38 1.1 mrg gfc_array_r16 * 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_REAL_16 * restrict base; 46 1.1 mrg GFC_REAL_16 * 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 MAXVAL 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_REAL_16)); 108 1.1 mrg if (alloc_size == 0) 109 1.1 mrg { 110 1.1 mrg /* Make sure we have a zero-sized array. */ 111 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1); 112 1.1 mrg return; 113 1.1 mrg 114 1.1 mrg } 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 " MAXVAL 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", "MAXVAL"); 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); 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 GFC_REAL_16 * restrict src; 144 1.1 mrg GFC_REAL_16 result; 145 1.1 mrg src = base; 146 1.1 mrg { 147 1.1 mrg 148 1.1 mrg #if defined (GFC_REAL_16_INFINITY) 149 1.1 mrg result = -GFC_REAL_16_INFINITY; 150 1.1 mrg #else 151 1.1 mrg result = -GFC_REAL_16_HUGE; 152 1.1 mrg #endif 153 1.1 mrg if (len <= 0) 154 1.1 mrg *dest = -GFC_REAL_16_HUGE; 155 1.1 mrg else 156 1.1 mrg { 157 1.1 mrg #if ! defined HAVE_BACK_ARG 158 1.1 mrg for (n = 0; n < len; n++, src += delta) 159 1.1 mrg { 160 1.1 mrg #endif 161 1.1 mrg 162 1.1 mrg #if defined (GFC_REAL_16_QUIET_NAN) 163 1.1 mrg if (*src >= result) 164 1.1 mrg break; 165 1.1 mrg } 166 1.1 mrg if (unlikely (n >= len)) 167 1.1 mrg result = GFC_REAL_16_QUIET_NAN; 168 1.1 mrg else for (; n < len; n++, src += delta) 169 1.1 mrg { 170 1.1 mrg #endif 171 1.1 mrg if (*src > result) 172 1.1 mrg result = *src; 173 1.1 mrg } 174 1.1 mrg 175 1.1 mrg *dest = result; 176 1.1 mrg } 177 1.1 mrg } 178 1.1 mrg /* Advance to the next element. */ 179 1.1 mrg count[0]++; 180 1.1 mrg base += sstride[0]; 181 1.1 mrg dest += dstride[0]; 182 1.1 mrg n = 0; 183 1.1 mrg while (count[n] == extent[n]) 184 1.1 mrg { 185 1.1 mrg /* When we get to the end of a dimension, reset it and increment 186 1.1 mrg the next dimension. */ 187 1.1 mrg count[n] = 0; 188 1.1 mrg /* We could precalculate these products, but this is a less 189 1.1 mrg frequently used path so probably not worth it. */ 190 1.1 mrg base -= sstride[n] * extent[n]; 191 1.1 mrg dest -= dstride[n] * extent[n]; 192 1.1 mrg n++; 193 1.1 mrg if (n >= rank) 194 1.1 mrg { 195 1.1 mrg /* Break out of the loop. */ 196 1.1 mrg continue_loop = 0; 197 1.1 mrg break; 198 1.1 mrg } 199 1.1 mrg else 200 1.1 mrg { 201 1.1 mrg count[n]++; 202 1.1 mrg base += sstride[n]; 203 1.1 mrg dest += dstride[n]; 204 1.1 mrg } 205 1.1 mrg } 206 1.1 mrg } 207 1.1 mrg } 208 1.1 mrg 209 1.1 mrg 210 1.1 mrg extern void mmaxval_r16 (gfc_array_r16 * const restrict, 211 1.1 mrg gfc_array_r16 * const restrict, const index_type * const restrict, 212 1.1 mrg gfc_array_l1 * const restrict); 213 1.1 mrg export_proto(mmaxval_r16); 214 1.1 mrg 215 1.1 mrg void 216 1.1 mrg mmaxval_r16 (gfc_array_r16 * const restrict retarray, 217 1.1 mrg gfc_array_r16 * const restrict array, 218 1.1 mrg const index_type * const restrict pdim, 219 1.1 mrg gfc_array_l1 * const restrict mask) 220 1.1 mrg { 221 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 222 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 223 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 224 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS]; 225 1.1 mrg index_type mstride[GFC_MAX_DIMENSIONS]; 226 1.1 mrg GFC_REAL_16 * restrict dest; 227 1.1 mrg const GFC_REAL_16 * restrict base; 228 1.1 mrg const GFC_LOGICAL_1 * restrict mbase; 229 1.1 mrg index_type rank; 230 1.1 mrg index_type dim; 231 1.1 mrg index_type n; 232 1.1 mrg index_type len; 233 1.1 mrg index_type delta; 234 1.1 mrg index_type mdelta; 235 1.1 mrg int mask_kind; 236 1.1 mrg 237 1.1 mrg if (mask == NULL) 238 1.1 mrg { 239 1.1 mrg #ifdef HAVE_BACK_ARG 240 1.1 mrg maxval_r16 (retarray, array, pdim, back); 241 1.1 mrg #else 242 1.1 mrg maxval_r16 (retarray, array, pdim); 243 1.1 mrg #endif 244 1.1 mrg return; 245 1.1 mrg } 246 1.1 mrg 247 1.1 mrg dim = (*pdim) - 1; 248 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1; 249 1.1 mrg 250 1.1 mrg 251 1.1 mrg if (unlikely (dim < 0 || dim > rank)) 252 1.1 mrg { 253 1.1 mrg runtime_error ("Dim argument incorrect in MAXVAL intrinsic: " 254 1.1 mrg "is %ld, should be between 1 and %ld", 255 1.1 mrg (long int) dim + 1, (long int) rank + 1); 256 1.1 mrg } 257 1.1 mrg 258 1.1 mrg len = GFC_DESCRIPTOR_EXTENT(array,dim); 259 1.1 mrg if (len <= 0) 260 1.1 mrg return; 261 1.1 mrg 262 1.1 mrg mbase = mask->base_addr; 263 1.1 mrg 264 1.1 mrg mask_kind = GFC_DESCRIPTOR_SIZE (mask); 265 1.1 mrg 266 1.1 mrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8 267 1.1 mrg #ifdef HAVE_GFC_LOGICAL_16 268 1.1 mrg || mask_kind == 16 269 1.1 mrg #endif 270 1.1 mrg ) 271 1.1 mrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind); 272 1.1 mrg else 273 1.1 mrg runtime_error ("Funny sized logical array"); 274 1.1 mrg 275 1.1 mrg delta = GFC_DESCRIPTOR_STRIDE(array,dim); 276 1.1 mrg mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim); 277 1.1 mrg 278 1.1 mrg for (n = 0; n < dim; n++) 279 1.1 mrg { 280 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n); 281 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n); 282 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 283 1.1 mrg 284 1.1 mrg if (extent[n] < 0) 285 1.1 mrg extent[n] = 0; 286 1.1 mrg 287 1.1 mrg } 288 1.1 mrg for (n = dim; n < rank; n++) 289 1.1 mrg { 290 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1); 291 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1); 292 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1); 293 1.1 mrg 294 1.1 mrg if (extent[n] < 0) 295 1.1 mrg extent[n] = 0; 296 1.1 mrg } 297 1.1 mrg 298 1.1 mrg if (retarray->base_addr == NULL) 299 1.1 mrg { 300 1.1 mrg size_t alloc_size, str; 301 1.1 mrg 302 1.1 mrg for (n = 0; n < rank; n++) 303 1.1 mrg { 304 1.1 mrg if (n == 0) 305 1.1 mrg str = 1; 306 1.1 mrg else 307 1.1 mrg str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; 308 1.1 mrg 309 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); 310 1.1 mrg 311 1.1 mrg } 312 1.1 mrg 313 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]; 314 1.1 mrg 315 1.1 mrg retarray->offset = 0; 316 1.1 mrg retarray->dtype.rank = rank; 317 1.1 mrg 318 1.1 mrg if (alloc_size == 0) 319 1.1 mrg { 320 1.1 mrg /* Make sure we have a zero-sized array. */ 321 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1); 322 1.1 mrg return; 323 1.1 mrg } 324 1.1 mrg else 325 1.1 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_REAL_16)); 326 1.1 mrg 327 1.1 mrg } 328 1.1 mrg else 329 1.1 mrg { 330 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray)) 331 1.1 mrg runtime_error ("rank of return array incorrect in MAXVAL intrinsic"); 332 1.1 mrg 333 1.1 mrg if (unlikely (compile_options.bounds_check)) 334 1.1 mrg { 335 1.1 mrg bounds_ifunction_return ((array_t *) retarray, extent, 336 1.1 mrg "return value", "MAXVAL"); 337 1.1 mrg bounds_equal_extents ((array_t *) mask, (array_t *) array, 338 1.1 mrg "MASK argument", "MAXVAL"); 339 1.1 mrg } 340 1.1 mrg } 341 1.1 mrg 342 1.1 mrg for (n = 0; n < rank; n++) 343 1.1 mrg { 344 1.1 mrg count[n] = 0; 345 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n); 346 1.1 mrg if (extent[n] <= 0) 347 1.1 mrg return; 348 1.1 mrg } 349 1.1 mrg 350 1.1 mrg dest = retarray->base_addr; 351 1.1 mrg base = array->base_addr; 352 1.1 mrg 353 1.1 mrg while (base) 354 1.1 mrg { 355 1.1 mrg const GFC_REAL_16 * restrict src; 356 1.1 mrg const GFC_LOGICAL_1 * restrict msrc; 357 1.1 mrg GFC_REAL_16 result; 358 1.1 mrg src = base; 359 1.1 mrg msrc = mbase; 360 1.1 mrg { 361 1.1 mrg 362 1.1 mrg #if defined (GFC_REAL_16_INFINITY) 363 1.1 mrg result = -GFC_REAL_16_INFINITY; 364 1.1 mrg #else 365 1.1 mrg result = -GFC_REAL_16_HUGE; 366 1.1 mrg #endif 367 1.1 mrg #if defined (GFC_REAL_16_QUIET_NAN) 368 1.1 mrg int non_empty_p = 0; 369 1.1 mrg #endif 370 1.1 mrg for (n = 0; n < len; n++, src += delta, msrc += mdelta) 371 1.1 mrg { 372 1.1 mrg 373 1.1 mrg #if defined (GFC_REAL_16_INFINITY) || defined (GFC_REAL_16_QUIET_NAN) 374 1.1 mrg if (*msrc) 375 1.1 mrg { 376 1.1 mrg #if defined (GFC_REAL_16_QUIET_NAN) 377 1.1 mrg non_empty_p = 1; 378 1.1 mrg if (*src >= result) 379 1.1 mrg #endif 380 1.1 mrg break; 381 1.1 mrg } 382 1.1 mrg } 383 1.1 mrg if (unlikely (n >= len)) 384 1.1 mrg { 385 1.1 mrg #if defined (GFC_REAL_16_QUIET_NAN) 386 1.1 mrg result = non_empty_p ? GFC_REAL_16_QUIET_NAN : -GFC_REAL_16_HUGE; 387 1.1 mrg #else 388 1.1 mrg result = -GFC_REAL_16_HUGE; 389 1.1 mrg #endif 390 1.1 mrg } 391 1.1 mrg else for (; n < len; n++, src += delta, msrc += mdelta) 392 1.1 mrg { 393 1.1 mrg #endif 394 1.1 mrg if (*msrc && *src > result) 395 1.1 mrg result = *src; 396 1.1 mrg } 397 1.1 mrg *dest = result; 398 1.1 mrg } 399 1.1 mrg /* Advance to the next element. */ 400 1.1 mrg count[0]++; 401 1.1 mrg base += sstride[0]; 402 1.1 mrg mbase += mstride[0]; 403 1.1 mrg dest += dstride[0]; 404 1.1 mrg n = 0; 405 1.1 mrg while (count[n] == extent[n]) 406 1.1 mrg { 407 1.1 mrg /* When we get to the end of a dimension, reset it and increment 408 1.1 mrg the next dimension. */ 409 1.1 mrg count[n] = 0; 410 1.1 mrg /* We could precalculate these products, but this is a less 411 1.1 mrg frequently used path so probably not worth it. */ 412 1.1 mrg base -= sstride[n] * extent[n]; 413 1.1 mrg mbase -= mstride[n] * extent[n]; 414 1.1 mrg dest -= dstride[n] * extent[n]; 415 1.1 mrg n++; 416 1.1 mrg if (n >= rank) 417 1.1 mrg { 418 1.1 mrg /* Break out of the loop. */ 419 1.1 mrg base = NULL; 420 1.1 mrg break; 421 1.1 mrg } 422 1.1 mrg else 423 1.1 mrg { 424 1.1 mrg count[n]++; 425 1.1 mrg base += sstride[n]; 426 1.1 mrg mbase += mstride[n]; 427 1.1 mrg dest += dstride[n]; 428 1.1 mrg } 429 1.1 mrg } 430 1.1 mrg } 431 1.1 mrg } 432 1.1 mrg 433 1.1 mrg 434 1.1 mrg extern void smaxval_r16 (gfc_array_r16 * const restrict, 435 1.1 mrg gfc_array_r16 * const restrict, const index_type * const restrict, 436 1.1 mrg GFC_LOGICAL_4 *); 437 1.1 mrg export_proto(smaxval_r16); 438 1.1 mrg 439 1.1 mrg void 440 1.1 mrg smaxval_r16 (gfc_array_r16 * const restrict retarray, 441 1.1 mrg gfc_array_r16 * const restrict array, 442 1.1 mrg const index_type * const restrict pdim, 443 1.1 mrg GFC_LOGICAL_4 * mask) 444 1.1 mrg { 445 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 446 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 447 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS]; 448 1.1 mrg GFC_REAL_16 * restrict dest; 449 1.1 mrg index_type rank; 450 1.1 mrg index_type n; 451 1.1 mrg index_type dim; 452 1.1 mrg 453 1.1 mrg 454 1.1 mrg if (mask == NULL || *mask) 455 1.1 mrg { 456 1.1 mrg #ifdef HAVE_BACK_ARG 457 1.1 mrg maxval_r16 (retarray, array, pdim, back); 458 1.1 mrg #else 459 1.1 mrg maxval_r16 (retarray, array, pdim); 460 1.1 mrg #endif 461 1.1 mrg return; 462 1.1 mrg } 463 1.1 mrg /* Make dim zero based to avoid confusion. */ 464 1.1 mrg dim = (*pdim) - 1; 465 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1; 466 1.1 mrg 467 1.1 mrg if (unlikely (dim < 0 || dim > rank)) 468 1.1 mrg { 469 1.1 mrg runtime_error ("Dim argument incorrect in MAXVAL intrinsic: " 470 1.1 mrg "is %ld, should be between 1 and %ld", 471 1.1 mrg (long int) dim + 1, (long int) rank + 1); 472 1.1 mrg } 473 1.1 mrg 474 1.1 mrg for (n = 0; n < dim; n++) 475 1.1 mrg { 476 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 477 1.1 mrg 478 1.1 mrg if (extent[n] <= 0) 479 1.1 mrg extent[n] = 0; 480 1.1 mrg } 481 1.1 mrg 482 1.1 mrg for (n = dim; n < rank; n++) 483 1.1 mrg { 484 1.1 mrg extent[n] = 485 1.1 mrg GFC_DESCRIPTOR_EXTENT(array,n + 1); 486 1.1 mrg 487 1.1 mrg if (extent[n] <= 0) 488 1.1 mrg extent[n] = 0; 489 1.1 mrg } 490 1.1 mrg 491 1.1 mrg if (retarray->base_addr == NULL) 492 1.1 mrg { 493 1.1 mrg size_t alloc_size, str; 494 1.1 mrg 495 1.1 mrg for (n = 0; n < rank; n++) 496 1.1 mrg { 497 1.1 mrg if (n == 0) 498 1.1 mrg str = 1; 499 1.1 mrg else 500 1.1 mrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; 501 1.1 mrg 502 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); 503 1.1 mrg 504 1.1 mrg } 505 1.1 mrg 506 1.1 mrg retarray->offset = 0; 507 1.1 mrg retarray->dtype.rank = rank; 508 1.1 mrg 509 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]; 510 1.1 mrg 511 1.1 mrg if (alloc_size == 0) 512 1.1 mrg { 513 1.1 mrg /* Make sure we have a zero-sized array. */ 514 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1); 515 1.1 mrg return; 516 1.1 mrg } 517 1.1 mrg else 518 1.1 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_REAL_16)); 519 1.1 mrg } 520 1.1 mrg else 521 1.1 mrg { 522 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray)) 523 1.1 mrg runtime_error ("rank of return array incorrect in" 524 1.1 mrg " MAXVAL intrinsic: is %ld, should be %ld", 525 1.1 mrg (long int) (GFC_DESCRIPTOR_RANK (retarray)), 526 1.1 mrg (long int) rank); 527 1.1 mrg 528 1.1 mrg if (unlikely (compile_options.bounds_check)) 529 1.1 mrg { 530 1.1 mrg for (n=0; n < rank; n++) 531 1.1 mrg { 532 1.1 mrg index_type ret_extent; 533 1.1 mrg 534 1.1 mrg ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n); 535 1.1 mrg if (extent[n] != ret_extent) 536 1.1 mrg runtime_error ("Incorrect extent in return value of" 537 1.1 mrg " MAXVAL intrinsic in dimension %ld:" 538 1.1 mrg " is %ld, should be %ld", (long int) n + 1, 539 1.1 mrg (long int) ret_extent, (long int) extent[n]); 540 1.1 mrg } 541 1.1 mrg } 542 1.1 mrg } 543 1.1 mrg 544 1.1 mrg for (n = 0; n < rank; n++) 545 1.1 mrg { 546 1.1 mrg count[n] = 0; 547 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n); 548 1.1 mrg } 549 1.1 mrg 550 1.1 mrg dest = retarray->base_addr; 551 1.1 mrg 552 1.1 mrg while(1) 553 1.1 mrg { 554 1.1 mrg *dest = -GFC_REAL_16_HUGE; 555 1.1 mrg count[0]++; 556 1.1 mrg dest += dstride[0]; 557 1.1 mrg n = 0; 558 1.1 mrg while (count[n] == extent[n]) 559 1.1 mrg { 560 1.1 mrg /* When we get to the end of a dimension, reset it and increment 561 1.1 mrg the next dimension. */ 562 1.1 mrg count[n] = 0; 563 1.1 mrg /* We could precalculate these products, but this is a less 564 1.1 mrg frequently used path so probably not worth it. */ 565 1.1 mrg dest -= dstride[n] * extent[n]; 566 1.1 mrg n++; 567 1.1 mrg if (n >= rank) 568 1.1 mrg return; 569 1.1 mrg else 570 1.1 mrg { 571 1.1 mrg count[n]++; 572 1.1 mrg dest += dstride[n]; 573 1.1 mrg } 574 1.1 mrg } 575 1.1 mrg } 576 1.1 mrg } 577 1.1 mrg 578 1.1 mrg #endif 579