1 1.1 mrg /* Generic implementation of the PACK intrinsic 2 1.1.1.5 mrg Copyright (C) 2002-2024 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 Ligbfortran 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 #include <string.h> 28 1.1 mrg 29 1.1 mrg /* PACK is specified as follows: 30 1.1 mrg 31 1.1 mrg 13.14.80 PACK (ARRAY, MASK, [VECTOR]) 32 1.1 mrg 33 1.1 mrg Description: Pack an array into an array of rank one under the 34 1.1 mrg control of a mask. 35 1.1 mrg 36 1.1 mrg Class: Transformational function. 37 1.1 mrg 38 1.1 mrg Arguments: 39 1.1 mrg ARRAY may be of any type. It shall not be scalar. 40 1.1 mrg MASK shall be of type LOGICAL. It shall be conformable with ARRAY. 41 1.1 mrg VECTOR (optional) shall be of the same type and type parameters 42 1.1 mrg as ARRAY. VECTOR shall have at least as many elements as 43 1.1 mrg there are true elements in MASK. If MASK is a scalar 44 1.1 mrg with the value true, VECTOR shall have at least as many 45 1.1 mrg elements as there are in ARRAY. 46 1.1 mrg 47 1.1 mrg Result Characteristics: The result is an array of rank one with the 48 1.1 mrg same type and type parameters as ARRAY. If VECTOR is present, the 49 1.1 mrg result size is that of VECTOR; otherwise, the result size is the 50 1.1 mrg number /t/ of true elements in MASK unless MASK is scalar with the 51 1.1 mrg value true, in which case the result size is the size of ARRAY. 52 1.1 mrg 53 1.1 mrg Result Value: Element /i/ of the result is the element of ARRAY 54 1.1 mrg that corresponds to the /i/th true element of MASK, taking elements 55 1.1 mrg in array element order, for /i/ = 1, 2, ..., /t/. If VECTOR is 56 1.1 mrg present and has size /n/ > /t/, element /i/ of the result has the 57 1.1 mrg value VECTOR(/i/), for /i/ = /t/ + 1, ..., /n/. 58 1.1 mrg 59 1.1 mrg Examples: The nonzero elements of an array M with the value 60 1.1 mrg | 0 0 0 | 61 1.1 mrg | 9 0 0 | may be "gathered" by the function PACK. The result of 62 1.1 mrg | 0 0 7 | 63 1.1 mrg PACK (M, MASK = M.NE.0) is [9,7] and the result of PACK (M, M.NE.0, 64 1.1 mrg VECTOR = (/ 2,4,6,8,10,12 /)) is [9,7,6,8,10,12]. 65 1.1 mrg 66 1.1 mrg There are two variants of the PACK intrinsic: one, where MASK is 67 1.1 mrg array valued, and the other one where MASK is scalar. */ 68 1.1 mrg 69 1.1 mrg static void 70 1.1 mrg pack_internal (gfc_array_char *ret, const gfc_array_char *array, 71 1.1 mrg const gfc_array_l1 *mask, const gfc_array_char *vector, 72 1.1 mrg index_type size) 73 1.1 mrg { 74 1.1 mrg /* r.* indicates the return array. */ 75 1.1 mrg index_type rstride0; 76 1.1 mrg char * restrict rptr; 77 1.1 mrg /* s.* indicates the source array. */ 78 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 79 1.1 mrg index_type sstride0; 80 1.1 mrg const char *sptr; 81 1.1 mrg /* m.* indicates the mask array. */ 82 1.1 mrg index_type mstride[GFC_MAX_DIMENSIONS]; 83 1.1 mrg index_type mstride0; 84 1.1 mrg const GFC_LOGICAL_1 *mptr; 85 1.1 mrg 86 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 87 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 88 1.1.1.3 mrg bool zero_sized; 89 1.1 mrg index_type n; 90 1.1 mrg index_type dim; 91 1.1 mrg index_type nelem; 92 1.1 mrg index_type total; 93 1.1 mrg int mask_kind; 94 1.1 mrg 95 1.1 mrg dim = GFC_DESCRIPTOR_RANK (array); 96 1.1 mrg 97 1.1.1.5 mrg sstride[0] = 0; /* Avoid warnings if not initialized. */ 98 1.1.1.5 mrg mstride[0] = 0; 99 1.1.1.5 mrg 100 1.1 mrg sptr = array->base_addr; 101 1.1 mrg mptr = mask->base_addr; 102 1.1 mrg 103 1.1 mrg /* Use the same loop for all logical types, by using GFC_LOGICAL_1 104 1.1 mrg and using shifting to address size and endian issues. */ 105 1.1 mrg 106 1.1 mrg mask_kind = GFC_DESCRIPTOR_SIZE (mask); 107 1.1 mrg 108 1.1 mrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8 109 1.1 mrg #ifdef HAVE_GFC_LOGICAL_16 110 1.1 mrg || mask_kind == 16 111 1.1 mrg #endif 112 1.1 mrg ) 113 1.1 mrg { 114 1.1 mrg /* Don't convert a NULL pointer as we use test for NULL below. */ 115 1.1 mrg if (mptr) 116 1.1 mrg mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind); 117 1.1 mrg } 118 1.1 mrg else 119 1.1 mrg runtime_error ("Funny sized logical array"); 120 1.1 mrg 121 1.1.1.3 mrg zero_sized = false; 122 1.1 mrg for (n = 0; n < dim; n++) 123 1.1 mrg { 124 1.1 mrg count[n] = 0; 125 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 126 1.1.1.3 mrg if (extent[n] <= 0) 127 1.1.1.3 mrg zero_sized = true; 128 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n); 129 1.1 mrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n); 130 1.1 mrg } 131 1.1 mrg if (sstride[0] == 0) 132 1.1 mrg sstride[0] = size; 133 1.1 mrg if (mstride[0] == 0) 134 1.1 mrg mstride[0] = mask_kind; 135 1.1 mrg 136 1.1.1.3 mrg if (zero_sized) 137 1.1.1.3 mrg sptr = NULL; 138 1.1.1.3 mrg else 139 1.1.1.3 mrg sptr = array->base_addr; 140 1.1.1.3 mrg 141 1.1 mrg if (ret->base_addr == NULL || unlikely (compile_options.bounds_check)) 142 1.1 mrg { 143 1.1 mrg /* Count the elements, either for allocating memory or 144 1.1 mrg for bounds checking. */ 145 1.1 mrg 146 1.1 mrg if (vector != NULL) 147 1.1 mrg { 148 1.1 mrg /* The return array will have as many 149 1.1 mrg elements as there are in VECTOR. */ 150 1.1 mrg total = GFC_DESCRIPTOR_EXTENT(vector,0); 151 1.1 mrg } 152 1.1 mrg else 153 1.1 mrg { 154 1.1 mrg /* We have to count the true elements in MASK. */ 155 1.1 mrg 156 1.1 mrg total = count_0 (mask); 157 1.1 mrg } 158 1.1 mrg 159 1.1 mrg if (ret->base_addr == NULL) 160 1.1 mrg { 161 1.1 mrg /* Setup the array descriptor. */ 162 1.1 mrg GFC_DIMENSION_SET(ret->dim[0], 0, total-1, 1); 163 1.1 mrg 164 1.1 mrg ret->offset = 0; 165 1.1 mrg /* xmallocarray allocates a single byte for zero size. */ 166 1.1 mrg ret->base_addr = xmallocarray (total, size); 167 1.1 mrg 168 1.1 mrg if (total == 0) 169 1.1 mrg return; /* In this case, nothing remains to be done. */ 170 1.1 mrg } 171 1.1 mrg else 172 1.1 mrg { 173 1.1 mrg /* We come here because of range checking. */ 174 1.1 mrg index_type ret_extent; 175 1.1 mrg 176 1.1 mrg ret_extent = GFC_DESCRIPTOR_EXTENT(ret,0); 177 1.1 mrg if (total != ret_extent) 178 1.1 mrg runtime_error ("Incorrect extent in return value of PACK intrinsic;" 179 1.1 mrg " is %ld, should be %ld", (long int) total, 180 1.1 mrg (long int) ret_extent); 181 1.1 mrg } 182 1.1 mrg } 183 1.1 mrg 184 1.1 mrg rstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(ret,0); 185 1.1 mrg if (rstride0 == 0) 186 1.1 mrg rstride0 = size; 187 1.1 mrg sstride0 = sstride[0]; 188 1.1 mrg mstride0 = mstride[0]; 189 1.1 mrg rptr = ret->base_addr; 190 1.1 mrg 191 1.1 mrg while (sptr && mptr) 192 1.1 mrg { 193 1.1 mrg /* Test this element. */ 194 1.1 mrg if (*mptr) 195 1.1 mrg { 196 1.1 mrg /* Add it. */ 197 1.1 mrg memcpy (rptr, sptr, size); 198 1.1 mrg rptr += rstride0; 199 1.1 mrg } 200 1.1 mrg /* Advance to the next element. */ 201 1.1 mrg sptr += sstride0; 202 1.1 mrg mptr += mstride0; 203 1.1 mrg count[0]++; 204 1.1 mrg n = 0; 205 1.1 mrg while (count[n] == extent[n]) 206 1.1 mrg { 207 1.1 mrg /* When we get to the end of a dimension, reset it and increment 208 1.1 mrg the next dimension. */ 209 1.1 mrg count[n] = 0; 210 1.1 mrg /* We could precalculate these products, but this is a less 211 1.1 mrg frequently used path so probably not worth it. */ 212 1.1 mrg sptr -= sstride[n] * extent[n]; 213 1.1 mrg mptr -= mstride[n] * extent[n]; 214 1.1 mrg n++; 215 1.1 mrg if (n >= dim) 216 1.1 mrg { 217 1.1 mrg /* Break out of the loop. */ 218 1.1 mrg sptr = NULL; 219 1.1 mrg break; 220 1.1 mrg } 221 1.1 mrg else 222 1.1 mrg { 223 1.1 mrg count[n]++; 224 1.1 mrg sptr += sstride[n]; 225 1.1 mrg mptr += mstride[n]; 226 1.1 mrg } 227 1.1 mrg } 228 1.1 mrg } 229 1.1 mrg 230 1.1 mrg /* Add any remaining elements from VECTOR. */ 231 1.1 mrg if (vector) 232 1.1 mrg { 233 1.1 mrg n = GFC_DESCRIPTOR_EXTENT(vector,0); 234 1.1 mrg nelem = ((rptr - ret->base_addr) / rstride0); 235 1.1 mrg if (n > nelem) 236 1.1 mrg { 237 1.1 mrg sstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(vector,0); 238 1.1 mrg if (sstride0 == 0) 239 1.1 mrg sstride0 = size; 240 1.1 mrg 241 1.1 mrg sptr = vector->base_addr + sstride0 * nelem; 242 1.1 mrg n -= nelem; 243 1.1 mrg while (n--) 244 1.1 mrg { 245 1.1 mrg memcpy (rptr, sptr, size); 246 1.1 mrg rptr += rstride0; 247 1.1 mrg sptr += sstride0; 248 1.1 mrg } 249 1.1 mrg } 250 1.1 mrg } 251 1.1 mrg } 252 1.1 mrg 253 1.1 mrg extern void pack (gfc_array_char *, const gfc_array_char *, 254 1.1 mrg const gfc_array_l1 *, const gfc_array_char *); 255 1.1 mrg export_proto(pack); 256 1.1 mrg 257 1.1 mrg void 258 1.1 mrg pack (gfc_array_char *ret, const gfc_array_char *array, 259 1.1 mrg const gfc_array_l1 *mask, const gfc_array_char *vector) 260 1.1 mrg { 261 1.1 mrg index_type type_size; 262 1.1 mrg index_type size; 263 1.1 mrg 264 1.1 mrg type_size = GFC_DTYPE_TYPE_SIZE(array); 265 1.1 mrg 266 1.1 mrg switch(type_size) 267 1.1 mrg { 268 1.1 mrg case GFC_DTYPE_LOGICAL_1: 269 1.1 mrg case GFC_DTYPE_INTEGER_1: 270 1.1 mrg pack_i1 ((gfc_array_i1 *) ret, (gfc_array_i1 *) array, 271 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_i1 *) vector); 272 1.1 mrg return; 273 1.1 mrg 274 1.1 mrg case GFC_DTYPE_LOGICAL_2: 275 1.1 mrg case GFC_DTYPE_INTEGER_2: 276 1.1 mrg pack_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) array, 277 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_i2 *) vector); 278 1.1 mrg return; 279 1.1 mrg 280 1.1 mrg case GFC_DTYPE_LOGICAL_4: 281 1.1 mrg case GFC_DTYPE_INTEGER_4: 282 1.1 mrg pack_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) array, 283 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_i4 *) vector); 284 1.1 mrg return; 285 1.1 mrg 286 1.1 mrg case GFC_DTYPE_LOGICAL_8: 287 1.1 mrg case GFC_DTYPE_INTEGER_8: 288 1.1 mrg pack_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) array, 289 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_i8 *) vector); 290 1.1 mrg return; 291 1.1 mrg 292 1.1 mrg #ifdef HAVE_GFC_INTEGER_16 293 1.1 mrg case GFC_DTYPE_LOGICAL_16: 294 1.1 mrg case GFC_DTYPE_INTEGER_16: 295 1.1 mrg pack_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) array, 296 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_i16 *) vector); 297 1.1 mrg return; 298 1.1 mrg #endif 299 1.1 mrg 300 1.1 mrg case GFC_DTYPE_REAL_4: 301 1.1 mrg pack_r4 ((gfc_array_r4 *) ret, (gfc_array_r4 *) array, 302 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_r4 *) vector); 303 1.1 mrg return; 304 1.1 mrg 305 1.1 mrg case GFC_DTYPE_REAL_8: 306 1.1 mrg pack_r8 ((gfc_array_r8 *) ret, (gfc_array_r8 *) array, 307 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_r8 *) vector); 308 1.1 mrg return; 309 1.1 mrg 310 1.1 mrg /* FIXME: This here is a hack, which will have to be removed when 311 1.1 mrg the array descriptor is reworked. Currently, we don't store the 312 1.1 mrg kind value for the type, but only the size. Because on targets with 313 1.1.1.5 mrg _Float128, we have sizeof(long double) == sizeof(_Float128), 314 1.1 mrg we cannot discriminate here and have to fall back to the generic 315 1.1 mrg handling (which is suboptimal). */ 316 1.1 mrg #if !defined(GFC_REAL_16_IS_FLOAT128) 317 1.1 mrg # ifdef HAVE_GFC_REAL_10 318 1.1 mrg case GFC_DTYPE_REAL_10: 319 1.1 mrg pack_r10 ((gfc_array_r10 *) ret, (gfc_array_r10 *) array, 320 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_r10 *) vector); 321 1.1 mrg return; 322 1.1 mrg # endif 323 1.1 mrg 324 1.1 mrg # ifdef HAVE_GFC_REAL_16 325 1.1 mrg case GFC_DTYPE_REAL_16: 326 1.1 mrg pack_r16 ((gfc_array_r16 *) ret, (gfc_array_r16 *) array, 327 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_r16 *) vector); 328 1.1 mrg return; 329 1.1 mrg # endif 330 1.1 mrg #endif 331 1.1 mrg 332 1.1 mrg case GFC_DTYPE_COMPLEX_4: 333 1.1 mrg pack_c4 ((gfc_array_c4 *) ret, (gfc_array_c4 *) array, 334 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_c4 *) vector); 335 1.1 mrg return; 336 1.1 mrg 337 1.1 mrg case GFC_DTYPE_COMPLEX_8: 338 1.1 mrg pack_c8 ((gfc_array_c8 *) ret, (gfc_array_c8 *) array, 339 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_c8 *) vector); 340 1.1 mrg return; 341 1.1 mrg 342 1.1 mrg /* FIXME: This here is a hack, which will have to be removed when 343 1.1 mrg the array descriptor is reworked. Currently, we don't store the 344 1.1 mrg kind value for the type, but only the size. Because on targets with 345 1.1.1.5 mrg _Float128, we have sizeof(long double) == sizeof(_Float128), 346 1.1 mrg we cannot discriminate here and have to fall back to the generic 347 1.1 mrg handling (which is suboptimal). */ 348 1.1 mrg #if !defined(GFC_REAL_16_IS_FLOAT128) 349 1.1 mrg # ifdef HAVE_GFC_COMPLEX_10 350 1.1 mrg case GFC_DTYPE_COMPLEX_10: 351 1.1 mrg pack_c10 ((gfc_array_c10 *) ret, (gfc_array_c10 *) array, 352 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_c10 *) vector); 353 1.1 mrg return; 354 1.1 mrg # endif 355 1.1 mrg 356 1.1 mrg # ifdef HAVE_GFC_COMPLEX_16 357 1.1 mrg case GFC_DTYPE_COMPLEX_16: 358 1.1 mrg pack_c16 ((gfc_array_c16 *) ret, (gfc_array_c16 *) array, 359 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_c16 *) vector); 360 1.1 mrg return; 361 1.1 mrg # endif 362 1.1 mrg #endif 363 1.1 mrg } 364 1.1 mrg 365 1.1 mrg /* For other types, let's check the actual alignment of the data pointers. 366 1.1 mrg If they are aligned, we can safely call the unpack functions. */ 367 1.1 mrg 368 1.1 mrg switch (GFC_DESCRIPTOR_SIZE (array)) 369 1.1 mrg { 370 1.1 mrg case 1: 371 1.1 mrg pack_i1 ((gfc_array_i1 *) ret, (gfc_array_i1 *) array, 372 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_i1 *) vector); 373 1.1 mrg return; 374 1.1 mrg 375 1.1 mrg case 2: 376 1.1 mrg if (GFC_UNALIGNED_2(ret->base_addr) || GFC_UNALIGNED_2(array->base_addr) 377 1.1 mrg || (vector && GFC_UNALIGNED_2(vector->base_addr))) 378 1.1 mrg break; 379 1.1 mrg else 380 1.1 mrg { 381 1.1 mrg pack_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) array, 382 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_i2 *) vector); 383 1.1 mrg return; 384 1.1 mrg } 385 1.1 mrg 386 1.1 mrg case 4: 387 1.1 mrg if (GFC_UNALIGNED_4(ret->base_addr) || GFC_UNALIGNED_4(array->base_addr) 388 1.1 mrg || (vector && GFC_UNALIGNED_4(vector->base_addr))) 389 1.1 mrg break; 390 1.1 mrg else 391 1.1 mrg { 392 1.1 mrg pack_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) array, 393 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_i4 *) vector); 394 1.1 mrg return; 395 1.1 mrg } 396 1.1 mrg 397 1.1 mrg case 8: 398 1.1 mrg if (GFC_UNALIGNED_8(ret->base_addr) || GFC_UNALIGNED_8(array->base_addr) 399 1.1 mrg || (vector && GFC_UNALIGNED_8(vector->base_addr))) 400 1.1 mrg break; 401 1.1 mrg else 402 1.1 mrg { 403 1.1 mrg pack_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) array, 404 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_i8 *) vector); 405 1.1 mrg return; 406 1.1 mrg } 407 1.1 mrg 408 1.1 mrg #ifdef HAVE_GFC_INTEGER_16 409 1.1 mrg case 16: 410 1.1 mrg if (GFC_UNALIGNED_16(ret->base_addr) || GFC_UNALIGNED_16(array->base_addr) 411 1.1 mrg || (vector && GFC_UNALIGNED_16(vector->base_addr))) 412 1.1 mrg break; 413 1.1 mrg else 414 1.1 mrg { 415 1.1 mrg pack_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) array, 416 1.1 mrg (gfc_array_l1 *) mask, (gfc_array_i16 *) vector); 417 1.1 mrg return; 418 1.1 mrg } 419 1.1 mrg #endif 420 1.1 mrg default: 421 1.1 mrg break; 422 1.1 mrg } 423 1.1 mrg 424 1.1 mrg size = GFC_DESCRIPTOR_SIZE (array); 425 1.1 mrg pack_internal (ret, array, mask, vector, size); 426 1.1 mrg } 427 1.1 mrg 428 1.1 mrg 429 1.1 mrg extern void pack_char (gfc_array_char *, GFC_INTEGER_4, const gfc_array_char *, 430 1.1 mrg const gfc_array_l1 *, const gfc_array_char *, 431 1.1 mrg GFC_INTEGER_4, GFC_INTEGER_4); 432 1.1 mrg export_proto(pack_char); 433 1.1 mrg 434 1.1 mrg void 435 1.1 mrg pack_char (gfc_array_char *ret, 436 1.1 mrg GFC_INTEGER_4 ret_length __attribute__((unused)), 437 1.1 mrg const gfc_array_char *array, const gfc_array_l1 *mask, 438 1.1 mrg const gfc_array_char *vector, GFC_INTEGER_4 array_length, 439 1.1 mrg GFC_INTEGER_4 vector_length __attribute__((unused))) 440 1.1 mrg { 441 1.1 mrg pack_internal (ret, array, mask, vector, array_length); 442 1.1 mrg } 443 1.1 mrg 444 1.1 mrg 445 1.1 mrg extern void pack_char4 (gfc_array_char *, GFC_INTEGER_4, const gfc_array_char *, 446 1.1 mrg const gfc_array_l1 *, const gfc_array_char *, 447 1.1 mrg GFC_INTEGER_4, GFC_INTEGER_4); 448 1.1 mrg export_proto(pack_char4); 449 1.1 mrg 450 1.1 mrg void 451 1.1 mrg pack_char4 (gfc_array_char *ret, 452 1.1 mrg GFC_INTEGER_4 ret_length __attribute__((unused)), 453 1.1 mrg const gfc_array_char *array, const gfc_array_l1 *mask, 454 1.1 mrg const gfc_array_char *vector, GFC_INTEGER_4 array_length, 455 1.1 mrg GFC_INTEGER_4 vector_length __attribute__((unused))) 456 1.1 mrg { 457 1.1 mrg pack_internal (ret, array, mask, vector, array_length * sizeof (gfc_char4_t)); 458 1.1 mrg } 459 1.1 mrg 460 1.1 mrg 461 1.1 mrg static void 462 1.1 mrg pack_s_internal (gfc_array_char *ret, const gfc_array_char *array, 463 1.1 mrg const GFC_LOGICAL_4 *mask, const gfc_array_char *vector, 464 1.1 mrg index_type size) 465 1.1 mrg { 466 1.1 mrg /* r.* indicates the return array. */ 467 1.1 mrg index_type rstride0; 468 1.1 mrg char *rptr; 469 1.1 mrg /* s.* indicates the source array. */ 470 1.1 mrg index_type sstride[GFC_MAX_DIMENSIONS]; 471 1.1 mrg index_type sstride0; 472 1.1 mrg const char *sptr; 473 1.1 mrg 474 1.1 mrg index_type count[GFC_MAX_DIMENSIONS]; 475 1.1 mrg index_type extent[GFC_MAX_DIMENSIONS]; 476 1.1 mrg index_type n; 477 1.1 mrg index_type dim; 478 1.1 mrg index_type ssize; 479 1.1 mrg index_type nelem; 480 1.1 mrg index_type total; 481 1.1 mrg 482 1.1 mrg dim = GFC_DESCRIPTOR_RANK (array); 483 1.1 mrg /* Initialize sstride[0] to avoid -Wmaybe-uninitialized 484 1.1 mrg complaints. */ 485 1.1 mrg sstride[0] = size; 486 1.1 mrg ssize = 1; 487 1.1 mrg for (n = 0; n < dim; n++) 488 1.1 mrg { 489 1.1 mrg count[n] = 0; 490 1.1 mrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); 491 1.1 mrg if (extent[n] < 0) 492 1.1 mrg extent[n] = 0; 493 1.1 mrg 494 1.1 mrg sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n); 495 1.1 mrg ssize *= extent[n]; 496 1.1 mrg } 497 1.1 mrg if (sstride[0] == 0) 498 1.1 mrg sstride[0] = size; 499 1.1 mrg 500 1.1 mrg sstride0 = sstride[0]; 501 1.1 mrg 502 1.1 mrg if (ssize != 0) 503 1.1 mrg sptr = array->base_addr; 504 1.1 mrg else 505 1.1 mrg sptr = NULL; 506 1.1 mrg 507 1.1 mrg if (ret->base_addr == NULL) 508 1.1 mrg { 509 1.1 mrg /* Allocate the memory for the result. */ 510 1.1 mrg 511 1.1 mrg if (vector != NULL) 512 1.1 mrg { 513 1.1 mrg /* The return array will have as many elements as there are 514 1.1 mrg in vector. */ 515 1.1 mrg total = GFC_DESCRIPTOR_EXTENT(vector,0); 516 1.1 mrg if (total <= 0) 517 1.1 mrg { 518 1.1 mrg total = 0; 519 1.1 mrg vector = NULL; 520 1.1 mrg } 521 1.1 mrg } 522 1.1 mrg else 523 1.1 mrg { 524 1.1 mrg if (*mask) 525 1.1 mrg { 526 1.1 mrg /* The result array will have as many elements as the input 527 1.1 mrg array. */ 528 1.1 mrg total = extent[0]; 529 1.1 mrg for (n = 1; n < dim; n++) 530 1.1 mrg total *= extent[n]; 531 1.1 mrg } 532 1.1 mrg else 533 1.1 mrg /* The result array will be empty. */ 534 1.1 mrg total = 0; 535 1.1 mrg } 536 1.1 mrg 537 1.1 mrg /* Setup the array descriptor. */ 538 1.1 mrg GFC_DIMENSION_SET(ret->dim[0],0,total-1,1); 539 1.1 mrg 540 1.1 mrg ret->offset = 0; 541 1.1 mrg 542 1.1 mrg ret->base_addr = xmallocarray (total, size); 543 1.1 mrg 544 1.1 mrg if (total == 0) 545 1.1 mrg return; 546 1.1 mrg } 547 1.1 mrg 548 1.1 mrg rstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(ret,0); 549 1.1 mrg if (rstride0 == 0) 550 1.1 mrg rstride0 = size; 551 1.1 mrg rptr = ret->base_addr; 552 1.1 mrg 553 1.1 mrg /* The remaining possibilities are now: 554 1.1 mrg If MASK is .TRUE., we have to copy the source array into the 555 1.1 mrg result array. We then have to fill it up with elements from VECTOR. 556 1.1 mrg If MASK is .FALSE., we have to copy VECTOR into the result 557 1.1 mrg array. If VECTOR were not present we would have already returned. */ 558 1.1 mrg 559 1.1 mrg if (*mask && ssize != 0) 560 1.1 mrg { 561 1.1 mrg while (sptr) 562 1.1 mrg { 563 1.1 mrg /* Add this element. */ 564 1.1 mrg memcpy (rptr, sptr, size); 565 1.1 mrg rptr += rstride0; 566 1.1 mrg 567 1.1 mrg /* Advance to the next element. */ 568 1.1 mrg sptr += sstride0; 569 1.1 mrg count[0]++; 570 1.1 mrg n = 0; 571 1.1 mrg while (count[n] == extent[n]) 572 1.1 mrg { 573 1.1 mrg /* When we get to the end of a dimension, reset it and 574 1.1 mrg increment the next dimension. */ 575 1.1 mrg count[n] = 0; 576 1.1 mrg /* We could precalculate these products, but this is a 577 1.1 mrg less frequently used path so probably not worth it. */ 578 1.1 mrg sptr -= sstride[n] * extent[n]; 579 1.1 mrg n++; 580 1.1 mrg if (n >= dim) 581 1.1 mrg { 582 1.1 mrg /* Break out of the loop. */ 583 1.1 mrg sptr = NULL; 584 1.1 mrg break; 585 1.1 mrg } 586 1.1 mrg else 587 1.1 mrg { 588 1.1 mrg count[n]++; 589 1.1 mrg sptr += sstride[n]; 590 1.1 mrg } 591 1.1 mrg } 592 1.1 mrg } 593 1.1 mrg } 594 1.1 mrg 595 1.1 mrg /* Add any remaining elements from VECTOR. */ 596 1.1 mrg if (vector) 597 1.1 mrg { 598 1.1 mrg n = GFC_DESCRIPTOR_EXTENT(vector,0); 599 1.1 mrg nelem = ((rptr - ret->base_addr) / rstride0); 600 1.1 mrg if (n > nelem) 601 1.1 mrg { 602 1.1 mrg sstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(vector,0); 603 1.1 mrg if (sstride0 == 0) 604 1.1 mrg sstride0 = size; 605 1.1 mrg 606 1.1 mrg sptr = vector->base_addr + sstride0 * nelem; 607 1.1 mrg n -= nelem; 608 1.1 mrg while (n--) 609 1.1 mrg { 610 1.1 mrg memcpy (rptr, sptr, size); 611 1.1 mrg rptr += rstride0; 612 1.1 mrg sptr += sstride0; 613 1.1 mrg } 614 1.1 mrg } 615 1.1 mrg } 616 1.1 mrg } 617 1.1 mrg 618 1.1 mrg extern void pack_s (gfc_array_char *ret, const gfc_array_char *array, 619 1.1 mrg const GFC_LOGICAL_4 *, const gfc_array_char *); 620 1.1 mrg export_proto(pack_s); 621 1.1 mrg 622 1.1 mrg void 623 1.1 mrg pack_s (gfc_array_char *ret, const gfc_array_char *array, 624 1.1 mrg const GFC_LOGICAL_4 *mask, const gfc_array_char *vector) 625 1.1 mrg { 626 1.1 mrg pack_s_internal (ret, array, mask, vector, GFC_DESCRIPTOR_SIZE (array)); 627 1.1 mrg } 628 1.1 mrg 629 1.1 mrg 630 1.1 mrg extern void pack_s_char (gfc_array_char *ret, GFC_INTEGER_4, 631 1.1 mrg const gfc_array_char *array, const GFC_LOGICAL_4 *, 632 1.1 mrg const gfc_array_char *, GFC_INTEGER_4, 633 1.1 mrg GFC_INTEGER_4); 634 1.1 mrg export_proto(pack_s_char); 635 1.1 mrg 636 1.1 mrg void 637 1.1 mrg pack_s_char (gfc_array_char *ret, 638 1.1 mrg GFC_INTEGER_4 ret_length __attribute__((unused)), 639 1.1 mrg const gfc_array_char *array, const GFC_LOGICAL_4 *mask, 640 1.1 mrg const gfc_array_char *vector, GFC_INTEGER_4 array_length, 641 1.1 mrg GFC_INTEGER_4 vector_length __attribute__((unused))) 642 1.1 mrg { 643 1.1 mrg pack_s_internal (ret, array, mask, vector, array_length); 644 1.1 mrg } 645 1.1 mrg 646 1.1 mrg 647 1.1 mrg extern void pack_s_char4 (gfc_array_char *ret, GFC_INTEGER_4, 648 1.1 mrg const gfc_array_char *array, const GFC_LOGICAL_4 *, 649 1.1 mrg const gfc_array_char *, GFC_INTEGER_4, 650 1.1 mrg GFC_INTEGER_4); 651 1.1 mrg export_proto(pack_s_char4); 652 1.1 mrg 653 1.1 mrg void 654 1.1 mrg pack_s_char4 (gfc_array_char *ret, 655 1.1 mrg GFC_INTEGER_4 ret_length __attribute__((unused)), 656 1.1 mrg const gfc_array_char *array, const GFC_LOGICAL_4 *mask, 657 1.1 mrg const gfc_array_char *vector, GFC_INTEGER_4 array_length, 658 1.1 mrg GFC_INTEGER_4 vector_length __attribute__((unused))) 659 1.1 mrg { 660 1.1 mrg pack_s_internal (ret, array, mask, vector, 661 1.1 mrg array_length * sizeof (gfc_char4_t)); 662 1.1 mrg } 663