2018-03-08 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgfortran / intrinsics / pack_generic.c
blob7de1e82c9ea2bb8f7aa3fe94ed74573461c553fa
1 /* Generic implementation of the PACK intrinsic
2 Copyright (C) 2002-2018 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 Ligbfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgfortran.h"
27 #include <string.h>
29 /* PACK is specified as follows:
31 13.14.80 PACK (ARRAY, MASK, [VECTOR])
33 Description: Pack an array into an array of rank one under the
34 control of a mask.
36 Class: Transformational function.
38 Arguments:
39 ARRAY may be of any type. It shall not be scalar.
40 MASK shall be of type LOGICAL. It shall be conformable with ARRAY.
41 VECTOR (optional) shall be of the same type and type parameters
42 as ARRAY. VECTOR shall have at least as many elements as
43 there are true elements in MASK. If MASK is a scalar
44 with the value true, VECTOR shall have at least as many
45 elements as there are in ARRAY.
47 Result Characteristics: The result is an array of rank one with the
48 same type and type parameters as ARRAY. If VECTOR is present, the
49 result size is that of VECTOR; otherwise, the result size is the
50 number /t/ of true elements in MASK unless MASK is scalar with the
51 value true, in which case the result size is the size of ARRAY.
53 Result Value: Element /i/ of the result is the element of ARRAY
54 that corresponds to the /i/th true element of MASK, taking elements
55 in array element order, for /i/ = 1, 2, ..., /t/. If VECTOR is
56 present and has size /n/ > /t/, element /i/ of the result has the
57 value VECTOR(/i/), for /i/ = /t/ + 1, ..., /n/.
59 Examples: The nonzero elements of an array M with the value
60 | 0 0 0 |
61 | 9 0 0 | may be "gathered" by the function PACK. The result of
62 | 0 0 7 |
63 PACK (M, MASK = M.NE.0) is [9,7] and the result of PACK (M, M.NE.0,
64 VECTOR = (/ 2,4,6,8,10,12 /)) is [9,7,6,8,10,12].
66 There are two variants of the PACK intrinsic: one, where MASK is
67 array valued, and the other one where MASK is scalar. */
69 static void
70 pack_internal (gfc_array_char *ret, const gfc_array_char *array,
71 const gfc_array_l1 *mask, const gfc_array_char *vector,
72 index_type size)
74 /* r.* indicates the return array. */
75 index_type rstride0;
76 char * restrict rptr;
77 /* s.* indicates the source array. */
78 index_type sstride[GFC_MAX_DIMENSIONS];
79 index_type sstride0;
80 const char *sptr;
81 /* m.* indicates the mask array. */
82 index_type mstride[GFC_MAX_DIMENSIONS];
83 index_type mstride0;
84 const GFC_LOGICAL_1 *mptr;
86 index_type count[GFC_MAX_DIMENSIONS];
87 index_type extent[GFC_MAX_DIMENSIONS];
88 index_type n;
89 index_type dim;
90 index_type nelem;
91 index_type total;
92 int mask_kind;
94 dim = GFC_DESCRIPTOR_RANK (array);
96 sptr = array->base_addr;
97 mptr = mask->base_addr;
99 /* Use the same loop for all logical types, by using GFC_LOGICAL_1
100 and using shifting to address size and endian issues. */
102 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
104 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
105 #ifdef HAVE_GFC_LOGICAL_16
106 || mask_kind == 16
107 #endif
110 /* Don't convert a NULL pointer as we use test for NULL below. */
111 if (mptr)
112 mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind);
114 else
115 runtime_error ("Funny sized logical array");
117 for (n = 0; n < dim; n++)
119 count[n] = 0;
120 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
121 sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n);
122 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
124 if (sstride[0] == 0)
125 sstride[0] = size;
126 if (mstride[0] == 0)
127 mstride[0] = mask_kind;
129 if (ret->base_addr == NULL || unlikely (compile_options.bounds_check))
131 /* Count the elements, either for allocating memory or
132 for bounds checking. */
134 if (vector != NULL)
136 /* The return array will have as many
137 elements as there are in VECTOR. */
138 total = GFC_DESCRIPTOR_EXTENT(vector,0);
140 else
142 /* We have to count the true elements in MASK. */
144 total = count_0 (mask);
147 if (ret->base_addr == NULL)
149 /* Setup the array descriptor. */
150 GFC_DIMENSION_SET(ret->dim[0], 0, total-1, 1);
152 ret->offset = 0;
153 /* xmallocarray allocates a single byte for zero size. */
154 ret->base_addr = xmallocarray (total, size);
156 if (total == 0)
157 return; /* In this case, nothing remains to be done. */
159 else
161 /* We come here because of range checking. */
162 index_type ret_extent;
164 ret_extent = GFC_DESCRIPTOR_EXTENT(ret,0);
165 if (total != ret_extent)
166 runtime_error ("Incorrect extent in return value of PACK intrinsic;"
167 " is %ld, should be %ld", (long int) total,
168 (long int) ret_extent);
172 rstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(ret,0);
173 if (rstride0 == 0)
174 rstride0 = size;
175 sstride0 = sstride[0];
176 mstride0 = mstride[0];
177 rptr = ret->base_addr;
179 while (sptr && mptr)
181 /* Test this element. */
182 if (*mptr)
184 /* Add it. */
185 memcpy (rptr, sptr, size);
186 rptr += rstride0;
188 /* Advance to the next element. */
189 sptr += sstride0;
190 mptr += mstride0;
191 count[0]++;
192 n = 0;
193 while (count[n] == extent[n])
195 /* When we get to the end of a dimension, reset it and increment
196 the next dimension. */
197 count[n] = 0;
198 /* We could precalculate these products, but this is a less
199 frequently used path so probably not worth it. */
200 sptr -= sstride[n] * extent[n];
201 mptr -= mstride[n] * extent[n];
202 n++;
203 if (n >= dim)
205 /* Break out of the loop. */
206 sptr = NULL;
207 break;
209 else
211 count[n]++;
212 sptr += sstride[n];
213 mptr += mstride[n];
218 /* Add any remaining elements from VECTOR. */
219 if (vector)
221 n = GFC_DESCRIPTOR_EXTENT(vector,0);
222 nelem = ((rptr - ret->base_addr) / rstride0);
223 if (n > nelem)
225 sstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(vector,0);
226 if (sstride0 == 0)
227 sstride0 = size;
229 sptr = vector->base_addr + sstride0 * nelem;
230 n -= nelem;
231 while (n--)
233 memcpy (rptr, sptr, size);
234 rptr += rstride0;
235 sptr += sstride0;
241 extern void pack (gfc_array_char *, const gfc_array_char *,
242 const gfc_array_l1 *, const gfc_array_char *);
243 export_proto(pack);
245 void
246 pack (gfc_array_char *ret, const gfc_array_char *array,
247 const gfc_array_l1 *mask, const gfc_array_char *vector)
249 index_type type_size;
250 index_type size;
252 type_size = GFC_DTYPE_TYPE_SIZE(array);
254 switch(type_size)
256 case GFC_DTYPE_LOGICAL_1:
257 case GFC_DTYPE_INTEGER_1:
258 pack_i1 ((gfc_array_i1 *) ret, (gfc_array_i1 *) array,
259 (gfc_array_l1 *) mask, (gfc_array_i1 *) vector);
260 return;
262 case GFC_DTYPE_LOGICAL_2:
263 case GFC_DTYPE_INTEGER_2:
264 pack_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) array,
265 (gfc_array_l1 *) mask, (gfc_array_i2 *) vector);
266 return;
268 case GFC_DTYPE_LOGICAL_4:
269 case GFC_DTYPE_INTEGER_4:
270 pack_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) array,
271 (gfc_array_l1 *) mask, (gfc_array_i4 *) vector);
272 return;
274 case GFC_DTYPE_LOGICAL_8:
275 case GFC_DTYPE_INTEGER_8:
276 pack_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) array,
277 (gfc_array_l1 *) mask, (gfc_array_i8 *) vector);
278 return;
280 #ifdef HAVE_GFC_INTEGER_16
281 case GFC_DTYPE_LOGICAL_16:
282 case GFC_DTYPE_INTEGER_16:
283 pack_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) array,
284 (gfc_array_l1 *) mask, (gfc_array_i16 *) vector);
285 return;
286 #endif
288 case GFC_DTYPE_REAL_4:
289 pack_r4 ((gfc_array_r4 *) ret, (gfc_array_r4 *) array,
290 (gfc_array_l1 *) mask, (gfc_array_r4 *) vector);
291 return;
293 case GFC_DTYPE_REAL_8:
294 pack_r8 ((gfc_array_r8 *) ret, (gfc_array_r8 *) array,
295 (gfc_array_l1 *) mask, (gfc_array_r8 *) vector);
296 return;
298 /* FIXME: This here is a hack, which will have to be removed when
299 the array descriptor is reworked. Currently, we don't store the
300 kind value for the type, but only the size. Because on targets with
301 __float128, we have sizeof(logn double) == sizeof(__float128),
302 we cannot discriminate here and have to fall back to the generic
303 handling (which is suboptimal). */
304 #if !defined(GFC_REAL_16_IS_FLOAT128)
305 # ifdef HAVE_GFC_REAL_10
306 case GFC_DTYPE_REAL_10:
307 pack_r10 ((gfc_array_r10 *) ret, (gfc_array_r10 *) array,
308 (gfc_array_l1 *) mask, (gfc_array_r10 *) vector);
309 return;
310 # endif
312 # ifdef HAVE_GFC_REAL_16
313 case GFC_DTYPE_REAL_16:
314 pack_r16 ((gfc_array_r16 *) ret, (gfc_array_r16 *) array,
315 (gfc_array_l1 *) mask, (gfc_array_r16 *) vector);
316 return;
317 # endif
318 #endif
320 case GFC_DTYPE_COMPLEX_4:
321 pack_c4 ((gfc_array_c4 *) ret, (gfc_array_c4 *) array,
322 (gfc_array_l1 *) mask, (gfc_array_c4 *) vector);
323 return;
325 case GFC_DTYPE_COMPLEX_8:
326 pack_c8 ((gfc_array_c8 *) ret, (gfc_array_c8 *) array,
327 (gfc_array_l1 *) mask, (gfc_array_c8 *) vector);
328 return;
330 /* FIXME: This here is a hack, which will have to be removed when
331 the array descriptor is reworked. Currently, we don't store the
332 kind value for the type, but only the size. Because on targets with
333 __float128, we have sizeof(logn double) == sizeof(__float128),
334 we cannot discriminate here and have to fall back to the generic
335 handling (which is suboptimal). */
336 #if !defined(GFC_REAL_16_IS_FLOAT128)
337 # ifdef HAVE_GFC_COMPLEX_10
338 case GFC_DTYPE_COMPLEX_10:
339 pack_c10 ((gfc_array_c10 *) ret, (gfc_array_c10 *) array,
340 (gfc_array_l1 *) mask, (gfc_array_c10 *) vector);
341 return;
342 # endif
344 # ifdef HAVE_GFC_COMPLEX_16
345 case GFC_DTYPE_COMPLEX_16:
346 pack_c16 ((gfc_array_c16 *) ret, (gfc_array_c16 *) array,
347 (gfc_array_l1 *) mask, (gfc_array_c16 *) vector);
348 return;
349 # endif
350 #endif
353 /* For other types, let's check the actual alignment of the data pointers.
354 If they are aligned, we can safely call the unpack functions. */
356 switch (GFC_DESCRIPTOR_SIZE (array))
358 case 1:
359 pack_i1 ((gfc_array_i1 *) ret, (gfc_array_i1 *) array,
360 (gfc_array_l1 *) mask, (gfc_array_i1 *) vector);
361 return;
363 case 2:
364 if (GFC_UNALIGNED_2(ret->base_addr) || GFC_UNALIGNED_2(array->base_addr)
365 || (vector && GFC_UNALIGNED_2(vector->base_addr)))
366 break;
367 else
369 pack_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) array,
370 (gfc_array_l1 *) mask, (gfc_array_i2 *) vector);
371 return;
374 case 4:
375 if (GFC_UNALIGNED_4(ret->base_addr) || GFC_UNALIGNED_4(array->base_addr)
376 || (vector && GFC_UNALIGNED_4(vector->base_addr)))
377 break;
378 else
380 pack_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) array,
381 (gfc_array_l1 *) mask, (gfc_array_i4 *) vector);
382 return;
385 case 8:
386 if (GFC_UNALIGNED_8(ret->base_addr) || GFC_UNALIGNED_8(array->base_addr)
387 || (vector && GFC_UNALIGNED_8(vector->base_addr)))
388 break;
389 else
391 pack_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) array,
392 (gfc_array_l1 *) mask, (gfc_array_i8 *) vector);
393 return;
396 #ifdef HAVE_GFC_INTEGER_16
397 case 16:
398 if (GFC_UNALIGNED_16(ret->base_addr) || GFC_UNALIGNED_16(array->base_addr)
399 || (vector && GFC_UNALIGNED_16(vector->base_addr)))
400 break;
401 else
403 pack_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) array,
404 (gfc_array_l1 *) mask, (gfc_array_i16 *) vector);
405 return;
407 #endif
408 default:
409 break;
412 size = GFC_DESCRIPTOR_SIZE (array);
413 pack_internal (ret, array, mask, vector, size);
417 extern void pack_char (gfc_array_char *, GFC_INTEGER_4, const gfc_array_char *,
418 const gfc_array_l1 *, const gfc_array_char *,
419 GFC_INTEGER_4, GFC_INTEGER_4);
420 export_proto(pack_char);
422 void
423 pack_char (gfc_array_char *ret,
424 GFC_INTEGER_4 ret_length __attribute__((unused)),
425 const gfc_array_char *array, const gfc_array_l1 *mask,
426 const gfc_array_char *vector, GFC_INTEGER_4 array_length,
427 GFC_INTEGER_4 vector_length __attribute__((unused)))
429 pack_internal (ret, array, mask, vector, array_length);
433 extern void pack_char4 (gfc_array_char *, GFC_INTEGER_4, const gfc_array_char *,
434 const gfc_array_l1 *, const gfc_array_char *,
435 GFC_INTEGER_4, GFC_INTEGER_4);
436 export_proto(pack_char4);
438 void
439 pack_char4 (gfc_array_char *ret,
440 GFC_INTEGER_4 ret_length __attribute__((unused)),
441 const gfc_array_char *array, const gfc_array_l1 *mask,
442 const gfc_array_char *vector, GFC_INTEGER_4 array_length,
443 GFC_INTEGER_4 vector_length __attribute__((unused)))
445 pack_internal (ret, array, mask, vector, array_length * sizeof (gfc_char4_t));
449 static void
450 pack_s_internal (gfc_array_char *ret, const gfc_array_char *array,
451 const GFC_LOGICAL_4 *mask, const gfc_array_char *vector,
452 index_type size)
454 /* r.* indicates the return array. */
455 index_type rstride0;
456 char *rptr;
457 /* s.* indicates the source array. */
458 index_type sstride[GFC_MAX_DIMENSIONS];
459 index_type sstride0;
460 const char *sptr;
462 index_type count[GFC_MAX_DIMENSIONS];
463 index_type extent[GFC_MAX_DIMENSIONS];
464 index_type n;
465 index_type dim;
466 index_type ssize;
467 index_type nelem;
468 index_type total;
470 dim = GFC_DESCRIPTOR_RANK (array);
471 /* Initialize sstride[0] to avoid -Wmaybe-uninitialized
472 complaints. */
473 sstride[0] = size;
474 ssize = 1;
475 for (n = 0; n < dim; n++)
477 count[n] = 0;
478 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
479 if (extent[n] < 0)
480 extent[n] = 0;
482 sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n);
483 ssize *= extent[n];
485 if (sstride[0] == 0)
486 sstride[0] = size;
488 sstride0 = sstride[0];
490 if (ssize != 0)
491 sptr = array->base_addr;
492 else
493 sptr = NULL;
495 if (ret->base_addr == NULL)
497 /* Allocate the memory for the result. */
499 if (vector != NULL)
501 /* The return array will have as many elements as there are
502 in vector. */
503 total = GFC_DESCRIPTOR_EXTENT(vector,0);
504 if (total <= 0)
506 total = 0;
507 vector = NULL;
510 else
512 if (*mask)
514 /* The result array will have as many elements as the input
515 array. */
516 total = extent[0];
517 for (n = 1; n < dim; n++)
518 total *= extent[n];
520 else
521 /* The result array will be empty. */
522 total = 0;
525 /* Setup the array descriptor. */
526 GFC_DIMENSION_SET(ret->dim[0],0,total-1,1);
528 ret->offset = 0;
530 ret->base_addr = xmallocarray (total, size);
532 if (total == 0)
533 return;
536 rstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(ret,0);
537 if (rstride0 == 0)
538 rstride0 = size;
539 rptr = ret->base_addr;
541 /* The remaining possibilities are now:
542 If MASK is .TRUE., we have to copy the source array into the
543 result array. We then have to fill it up with elements from VECTOR.
544 If MASK is .FALSE., we have to copy VECTOR into the result
545 array. If VECTOR were not present we would have already returned. */
547 if (*mask && ssize != 0)
549 while (sptr)
551 /* Add this element. */
552 memcpy (rptr, sptr, size);
553 rptr += rstride0;
555 /* Advance to the next element. */
556 sptr += sstride0;
557 count[0]++;
558 n = 0;
559 while (count[n] == extent[n])
561 /* When we get to the end of a dimension, reset it and
562 increment the next dimension. */
563 count[n] = 0;
564 /* We could precalculate these products, but this is a
565 less frequently used path so probably not worth it. */
566 sptr -= sstride[n] * extent[n];
567 n++;
568 if (n >= dim)
570 /* Break out of the loop. */
571 sptr = NULL;
572 break;
574 else
576 count[n]++;
577 sptr += sstride[n];
583 /* Add any remaining elements from VECTOR. */
584 if (vector)
586 n = GFC_DESCRIPTOR_EXTENT(vector,0);
587 nelem = ((rptr - ret->base_addr) / rstride0);
588 if (n > nelem)
590 sstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(vector,0);
591 if (sstride0 == 0)
592 sstride0 = size;
594 sptr = vector->base_addr + sstride0 * nelem;
595 n -= nelem;
596 while (n--)
598 memcpy (rptr, sptr, size);
599 rptr += rstride0;
600 sptr += sstride0;
606 extern void pack_s (gfc_array_char *ret, const gfc_array_char *array,
607 const GFC_LOGICAL_4 *, const gfc_array_char *);
608 export_proto(pack_s);
610 void
611 pack_s (gfc_array_char *ret, const gfc_array_char *array,
612 const GFC_LOGICAL_4 *mask, const gfc_array_char *vector)
614 pack_s_internal (ret, array, mask, vector, GFC_DESCRIPTOR_SIZE (array));
618 extern void pack_s_char (gfc_array_char *ret, GFC_INTEGER_4,
619 const gfc_array_char *array, const GFC_LOGICAL_4 *,
620 const gfc_array_char *, GFC_INTEGER_4,
621 GFC_INTEGER_4);
622 export_proto(pack_s_char);
624 void
625 pack_s_char (gfc_array_char *ret,
626 GFC_INTEGER_4 ret_length __attribute__((unused)),
627 const gfc_array_char *array, const GFC_LOGICAL_4 *mask,
628 const gfc_array_char *vector, GFC_INTEGER_4 array_length,
629 GFC_INTEGER_4 vector_length __attribute__((unused)))
631 pack_s_internal (ret, array, mask, vector, array_length);
635 extern void pack_s_char4 (gfc_array_char *ret, GFC_INTEGER_4,
636 const gfc_array_char *array, const GFC_LOGICAL_4 *,
637 const gfc_array_char *, GFC_INTEGER_4,
638 GFC_INTEGER_4);
639 export_proto(pack_s_char4);
641 void
642 pack_s_char4 (gfc_array_char *ret,
643 GFC_INTEGER_4 ret_length __attribute__((unused)),
644 const gfc_array_char *array, const GFC_LOGICAL_4 *mask,
645 const gfc_array_char *vector, GFC_INTEGER_4 array_length,
646 GFC_INTEGER_4 vector_length __attribute__((unused)))
648 pack_s_internal (ret, array, mask, vector,
649 array_length * sizeof (gfc_char4_t));