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