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