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