1 1.1 mrg dnl Support macro file for intrinsic functions. 2 1.1 mrg dnl Contains the generic sections of the array functions. 3 1.1 mrg dnl This file is part of the GNU Fortran Runtime Library (libgfortran) 4 1.1 mrg dnl Distributed under the GNU GPL with exception. See COPYING for details. 5 1.1 mrg dnl 6 1.1 mrg dnl Pass the implementation for a single section as the parameter to 7 1.1 mrg dnl {MASK_}ARRAY_FUNCTION. 8 1.1 mrg dnl The variables base, delta, and len describe the input section. 9 1.1 mrg dnl For masked section the mask is described by mbase and mdelta. 10 1.1 mrg dnl These should not be modified. The result should be stored in *dest. 11 1.1 mrg dnl The names count, extent, sstride, dstride, base, dest, rank, dim 12 1.1 mrg dnl retarray, array, pdim and mstride should not be used. 13 1.1 mrg dnl The variable n is declared as index_type and may be used. 14 1.1 mrg dnl Other variable declarations may be placed at the start of the code, 15 1.1 mrg dnl The types of the array parameter and the return value are 16 1.1 mrg dnl atype_name and rtype_name respectively. 17 1.1 mrg dnl Execution should be allowed to continue to the end of the block. 18 1.1 mrg dnl You should not return or break from the inner loop of the implementation. 19 1.1 mrg dnl Care should also be taken to avoid using the names defined in iparm.m4 20 1.1 mrg define(START_ARRAY_FUNCTION, 21 1.1 mrg ` 22 1.1 mrg extern void name`'rtype_qual`_'atype_code (rtype * const restrict, 23 1.1 mrg gfc_array_l1 * const restrict, const index_type * const restrict); 24 1.1 mrg export_proto(name`'rtype_qual`_'atype_code); 25 1.1 mrg 26 1.1 mrg void 27 1.1 mrg name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 28 1.1 mrg gfc_array_l1 * const restrict array, 29 1.1 mrg const index_type * const restrict pdim) 30 1.1 mrg { 31 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 32 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 33 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 34 1.1 mrg index_type dstride[GFC_MAX_DIMENSIONS]; 35 1.1 mrg const GFC_LOGICAL_1 * restrict base; 36 1.1 mrg rtype_name * restrict dest; 37 1.1 mrg index_type rank; 38 1.1 mrg index_type n; 39 1.1 mrg index_type len; 40 1.1 mrg index_type delta; 41 1.1 mrg index_type dim; 42 1.1 mrg int src_kind; 43 1.1 mrg int continue_loop; 44 1.1 mrg 45 1.1 mrg /* Make dim zero based to avoid confusion. */ 46 1.1 mrg dim = (*pdim) - 1; 47 1.1 mrg rank = GFC_DESCRIPTOR_RANK (array) - 1; 48 1.1 mrg 49 1.1 mrg src_kind = GFC_DESCRIPTOR_SIZE (array); 50 1.1 mrg 51 1.1 mrg len = GFC_DESCRIPTOR_EXTENT(array,dim); 52 1.1 mrg if (len < 0) 53 1.1 mrg len = 0; 54 1.1 mrg 55 1.1 mrg delta = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim); 56 1.1 mrg 57 1.1 mrg for (n = 0; n < dim; n++) 58 1.1 mrg { 59 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n); 60 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 61 1.1 mrg 62 1.1 mrg if (extent[n] < 0) 63 1.1 mrg extent[n] = 0; 64 1.1 mrg } 65 1.1 mrg for (n = dim; n < rank; n++) 66 1.1 mrg { 67 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n + 1); 68 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); 69 1.1 mrg 70 1.1 mrg if (extent[n] < 0) 71 1.1 mrg extent[n] = 0; 72 1.1 mrg } 73 1.1 mrg 74 1.1 mrg if (retarray->base_addr == NULL) 75 1.1 mrg { 76 1.1 mrg size_t alloc_size, str; 77 1.1 mrg 78 1.1 mrg for (n = 0; n < rank; n++) 79 1.1 mrg { 80 1.1 mrg if (n == 0) 81 1.1 mrg str = 1; 82 1.1 mrg else 83 1.1 mrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; 84 1.1 mrg 85 1.1 mrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); 86 1.1 mrg 87 1.1 mrg } 88 1.1 mrg 89 1.1 mrg retarray->offset = 0; 90 1.1 mrg retarray->dtype.rank = rank; 91 1.1 mrg 92 1.1 mrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]; 93 1.1 mrg 94 1.1 mrg if (alloc_size == 0) 95 1.1 mrg { 96 1.1 mrg /* Make sure we have a zero-sized array. */ 97 1.1 mrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1); 98 1.1 mrg return; 99 1.1 mrg } 100 1.1 mrg else 101 1.1 mrg retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name)); 102 1.1 mrg } 103 1.1 mrg else 104 1.1 mrg { 105 1.1 mrg if (rank != GFC_DESCRIPTOR_RANK (retarray)) 106 1.1 mrg runtime_error ("rank of return array incorrect in" 107 1.1 mrg " u_name intrinsic: is %ld, should be %ld", 108 1.1 mrg (long int) GFC_DESCRIPTOR_RANK (retarray), 109 1.1 mrg (long int) rank); 110 1.1 mrg 111 1.1 mrg if (unlikely (compile_options.bounds_check)) 112 1.1 mrg { 113 1.1 mrg for (n=0; n < rank; n++) 114 1.1 mrg { 115 1.1 mrg index_type ret_extent; 116 1.1 mrg 117 1.1 mrg ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n); 118 1.1 mrg if (extent[n] != ret_extent) 119 1.1 mrg runtime_error ("Incorrect extent in return value of" 120 1.1 mrg " u_name intrinsic in dimension %d:" 121 1.1 mrg " is %ld, should be %ld", (int) n + 1, 122 1.1 mrg (long int) ret_extent, (long int) extent[n]); 123 1.1 mrg } 124 1.1 mrg } 125 1.1 mrg } 126 1.1 mrg 127 1.1 mrg for (n = 0; n < rank; n++) 128 1.1 mrg { 129 1.1 mrg count[n] = 0; 130 1.1 mrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n); 131 1.1 mrg if (extent[n] <= 0) 132 1.1 mrg return; 133 1.1 mrg } 134 1.1 mrg 135 1.1 mrg base = array->base_addr; 136 1.1 mrg 137 1.1 mrg if (src_kind == 1 || src_kind == 2 || src_kind == 4 || src_kind == 8 138 1.1 mrg #ifdef HAVE_GFC_LOGICAL_16 139 1.1 mrg || src_kind == 16 140 1.1 mrg #endif 141 1.1 mrg ) 142 1.1 mrg { 143 1.1 mrg if (base) 144 1.1 mrg base = GFOR_POINTER_TO_L1 (base, src_kind); 145 1.1 mrg } 146 1.1 mrg else 147 1.1 mrg internal_error (NULL, "Funny sized logical array in u_name intrinsic"); 148 1.1 mrg 149 1.1 mrg dest = retarray->base_addr; 150 1.1 mrg 151 1.1 mrg continue_loop = 1; 152 1.1 mrg while (continue_loop) 153 1.1 mrg { 154 1.1 mrg const GFC_LOGICAL_1 * restrict src; 155 1.1 mrg rtype_name result; 156 1.1 mrg src = base; 157 1.1 mrg { 158 1.1 mrg ')dnl 159 1.1 mrg define(START_ARRAY_BLOCK, 160 1.1 mrg ` if (len <= 0) 161 1.1 mrg *dest = '$1`; 162 1.1 mrg else 163 1.1 mrg { 164 1.1 mrg for (n = 0; n < len; n++, src += delta) 165 1.1 mrg { 166 1.1 mrg ')dnl 167 1.1 mrg define(FINISH_ARRAY_FUNCTION, 168 1.1 mrg ` } 169 1.1 mrg *dest = result; 170 1.1 mrg } 171 1.1 mrg } 172 1.1 mrg /* Advance to the next element. */ 173 1.1 mrg count[0]++; 174 1.1 mrg base += sstride[0]; 175 1.1 mrg dest += dstride[0]; 176 1.1 mrg n = 0; 177 1.1 mrg while (count[n] == extent[n]) 178 1.1 mrg { 179 1.1 mrg /* When we get to the end of a dimension, reset it and increment 180 1.1 mrg the next dimension. */ 181 1.1 mrg count[n] = 0; 182 1.1 mrg /* We could precalculate these products, but this is a less 183 1.1 mrg frequently used path so probably not worth it. */ 184 1.1 mrg base -= sstride[n] * extent[n]; 185 1.1 mrg dest -= dstride[n] * extent[n]; 186 1.1 mrg n++; 187 1.1 mrg if (n >= rank) 188 1.1 mrg { 189 1.1 mrg /* Break out of the loop. */ 190 1.1 mrg continue_loop = 0; 191 1.1 mrg break; 192 1.1 mrg } 193 1.1 mrg else 194 1.1 mrg { 195 1.1 mrg count[n]++; 196 1.1 mrg base += sstride[n]; 197 1.1 mrg dest += dstride[n]; 198 1.1 mrg } 199 1.1 mrg } 200 1.1 mrg } 201 1.1 mrg }')dnl 202 1.1 mrg define(ARRAY_FUNCTION, 203 1.1 mrg `START_ARRAY_FUNCTION 204 1.1 mrg $2 205 1.1 mrg START_ARRAY_BLOCK($1) 206 1.1 mrg $3 207 1.1 mrg FINISH_ARRAY_FUNCTION')dnl 208