1 /* Generic implementation of the PACK intrinsic
2 Copyright (C) 2002-2016 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"
31 /* PACK is specified as follows:
33 13.14.80 PACK (ARRAY, MASK, [VECTOR])
35 Description: Pack an array into an array of rank one under the
38 Class: Transformational function.
41 ARRAY may be of any type. It shall not be scalar.
42 MASK shall be of type LOGICAL. It shall be conformable with ARRAY.
43 VECTOR (optional) shall be of the same type and type parameters
44 as ARRAY. VECTOR shall have at least as many elements as
45 there are true elements in MASK. If MASK is a scalar
46 with the value true, VECTOR shall have at least as many
47 elements as there are in ARRAY.
49 Result Characteristics: The result is an array of rank one with the
50 same type and type parameters as ARRAY. If VECTOR is present, the
51 result size is that of VECTOR; otherwise, the result size is the
52 number /t/ of true elements in MASK unless MASK is scalar with the
53 value true, in which case the result size is the size of ARRAY.
55 Result Value: Element /i/ of the result is the element of ARRAY
56 that corresponds to the /i/th true element of MASK, taking elements
57 in array element order, for /i/ = 1, 2, ..., /t/. If VECTOR is
58 present and has size /n/ > /t/, element /i/ of the result has the
59 value VECTOR(/i/), for /i/ = /t/ + 1, ..., /n/.
61 Examples: The nonzero elements of an array M with the value
63 | 9 0 0 | may be "gathered" by the function PACK. The result of
65 PACK (M, MASK = M.NE.0) is [9,7] and the result of PACK (M, M.NE.0,
66 VECTOR = (/ 2,4,6,8,10,12 /)) is [9,7,6,8,10,12].
68 There are two variants of the PACK intrinsic: one, where MASK is
69 array valued, and the other one where MASK is scalar. */
72 pack_internal (gfc_array_char
*ret
, const gfc_array_char
*array
,
73 const gfc_array_l1
*mask
, const gfc_array_char
*vector
,
76 /* r.* indicates the return array. */
79 /* s.* indicates the source array. */
80 index_type sstride
[GFC_MAX_DIMENSIONS
];
83 /* m.* indicates the mask array. */
84 index_type mstride
[GFC_MAX_DIMENSIONS
];
86 const GFC_LOGICAL_1
*mptr
;
88 index_type count
[GFC_MAX_DIMENSIONS
];
89 index_type extent
[GFC_MAX_DIMENSIONS
];
96 dim
= GFC_DESCRIPTOR_RANK (array
);
98 sptr
= array
->base_addr
;
99 mptr
= mask
->base_addr
;
101 /* Use the same loop for all logical types, by using GFC_LOGICAL_1
102 and using shifting to address size and endian issues. */
104 mask_kind
= GFC_DESCRIPTOR_SIZE (mask
);
106 if (mask_kind
== 1 || mask_kind
== 2 || mask_kind
== 4 || mask_kind
== 8
107 #ifdef HAVE_GFC_LOGICAL_16
112 /* Don't convert a NULL pointer as we use test for NULL below. */
114 mptr
= GFOR_POINTER_TO_L1 (mptr
, mask_kind
);
117 runtime_error ("Funny sized logical array");
119 for (n
= 0; n
< dim
; n
++)
122 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
123 sstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(array
,n
);
124 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
,n
);
129 mstride
[0] = mask_kind
;
131 if (ret
->base_addr
== NULL
|| unlikely (compile_options
.bounds_check
))
133 /* Count the elements, either for allocating memory or
134 for bounds checking. */
138 /* The return array will have as many
139 elements as there are in VECTOR. */
140 total
= GFC_DESCRIPTOR_EXTENT(vector
,0);
144 /* We have to count the true elements in MASK. */
146 total
= count_0 (mask
);
149 if (ret
->base_addr
== NULL
)
151 /* Setup the array descriptor. */
152 GFC_DIMENSION_SET(ret
->dim
[0], 0, total
-1, 1);
155 /* xmallocarray allocates a single byte for zero size. */
156 ret
->base_addr
= xmallocarray (total
, size
);
159 return; /* In this case, nothing remains to be done. */
163 /* We come here because of range checking. */
164 index_type ret_extent
;
166 ret_extent
= GFC_DESCRIPTOR_EXTENT(ret
,0);
167 if (total
!= ret_extent
)
168 runtime_error ("Incorrect extent in return value of PACK intrinsic;"
169 " is %ld, should be %ld", (long int) total
,
170 (long int) ret_extent
);
174 rstride0
= GFC_DESCRIPTOR_STRIDE_BYTES(ret
,0);
177 sstride0
= sstride
[0];
178 mstride0
= mstride
[0];
179 rptr
= ret
->base_addr
;
183 /* Test this element. */
187 memcpy (rptr
, sptr
, size
);
190 /* Advance to the next element. */
195 while (count
[n
] == extent
[n
])
197 /* When we get to the end of a dimension, reset it and increment
198 the next dimension. */
200 /* We could precalculate these products, but this is a less
201 frequently used path so probably not worth it. */
202 sptr
-= sstride
[n
] * extent
[n
];
203 mptr
-= mstride
[n
] * extent
[n
];
207 /* Break out of the loop. */
220 /* Add any remaining elements from VECTOR. */
223 n
= GFC_DESCRIPTOR_EXTENT(vector
,0);
224 nelem
= ((rptr
- ret
->base_addr
) / rstride0
);
227 sstride0
= GFC_DESCRIPTOR_STRIDE_BYTES(vector
,0);
231 sptr
= vector
->base_addr
+ sstride0
* nelem
;
235 memcpy (rptr
, sptr
, size
);
243 extern void pack (gfc_array_char
*, const gfc_array_char
*,
244 const gfc_array_l1
*, const gfc_array_char
*);
248 pack (gfc_array_char
*ret
, const gfc_array_char
*array
,
249 const gfc_array_l1
*mask
, const gfc_array_char
*vector
)
251 index_type type_size
;
254 type_size
= GFC_DTYPE_TYPE_SIZE(array
);
258 case GFC_DTYPE_LOGICAL_1
:
259 case GFC_DTYPE_INTEGER_1
:
260 case GFC_DTYPE_DERIVED_1
:
261 pack_i1 ((gfc_array_i1
*) ret
, (gfc_array_i1
*) array
,
262 (gfc_array_l1
*) mask
, (gfc_array_i1
*) vector
);
265 case GFC_DTYPE_LOGICAL_2
:
266 case GFC_DTYPE_INTEGER_2
:
267 pack_i2 ((gfc_array_i2
*) ret
, (gfc_array_i2
*) array
,
268 (gfc_array_l1
*) mask
, (gfc_array_i2
*) vector
);
271 case GFC_DTYPE_LOGICAL_4
:
272 case GFC_DTYPE_INTEGER_4
:
273 pack_i4 ((gfc_array_i4
*) ret
, (gfc_array_i4
*) array
,
274 (gfc_array_l1
*) mask
, (gfc_array_i4
*) vector
);
277 case GFC_DTYPE_LOGICAL_8
:
278 case GFC_DTYPE_INTEGER_8
:
279 pack_i8 ((gfc_array_i8
*) ret
, (gfc_array_i8
*) array
,
280 (gfc_array_l1
*) mask
, (gfc_array_i8
*) vector
);
283 #ifdef HAVE_GFC_INTEGER_16
284 case GFC_DTYPE_LOGICAL_16
:
285 case GFC_DTYPE_INTEGER_16
:
286 pack_i16 ((gfc_array_i16
*) ret
, (gfc_array_i16
*) array
,
287 (gfc_array_l1
*) mask
, (gfc_array_i16
*) vector
);
291 case GFC_DTYPE_REAL_4
:
292 pack_r4 ((gfc_array_r4
*) ret
, (gfc_array_r4
*) array
,
293 (gfc_array_l1
*) mask
, (gfc_array_r4
*) vector
);
296 case GFC_DTYPE_REAL_8
:
297 pack_r8 ((gfc_array_r8
*) ret
, (gfc_array_r8
*) array
,
298 (gfc_array_l1
*) mask
, (gfc_array_r8
*) vector
);
301 /* FIXME: This here is a hack, which will have to be removed when
302 the array descriptor is reworked. Currently, we don't store the
303 kind value for the type, but only the size. Because on targets with
304 __float128, we have sizeof(logn double) == sizeof(__float128),
305 we cannot discriminate here and have to fall back to the generic
306 handling (which is suboptimal). */
307 #if !defined(GFC_REAL_16_IS_FLOAT128)
308 # ifdef HAVE_GFC_REAL_10
309 case GFC_DTYPE_REAL_10
:
310 pack_r10 ((gfc_array_r10
*) ret
, (gfc_array_r10
*) array
,
311 (gfc_array_l1
*) mask
, (gfc_array_r10
*) vector
);
315 # ifdef HAVE_GFC_REAL_16
316 case GFC_DTYPE_REAL_16
:
317 pack_r16 ((gfc_array_r16
*) ret
, (gfc_array_r16
*) array
,
318 (gfc_array_l1
*) mask
, (gfc_array_r16
*) vector
);
323 case GFC_DTYPE_COMPLEX_4
:
324 pack_c4 ((gfc_array_c4
*) ret
, (gfc_array_c4
*) array
,
325 (gfc_array_l1
*) mask
, (gfc_array_c4
*) vector
);
328 case GFC_DTYPE_COMPLEX_8
:
329 pack_c8 ((gfc_array_c8
*) ret
, (gfc_array_c8
*) array
,
330 (gfc_array_l1
*) mask
, (gfc_array_c8
*) vector
);
333 /* FIXME: This here is a hack, which will have to be removed when
334 the array descriptor is reworked. Currently, we don't store the
335 kind value for the type, but only the size. Because on targets with
336 __float128, we have sizeof(logn double) == sizeof(__float128),
337 we cannot discriminate here and have to fall back to the generic
338 handling (which is suboptimal). */
339 #if !defined(GFC_REAL_16_IS_FLOAT128)
340 # ifdef HAVE_GFC_COMPLEX_10
341 case GFC_DTYPE_COMPLEX_10
:
342 pack_c10 ((gfc_array_c10
*) ret
, (gfc_array_c10
*) array
,
343 (gfc_array_l1
*) mask
, (gfc_array_c10
*) vector
);
347 # ifdef HAVE_GFC_COMPLEX_16
348 case GFC_DTYPE_COMPLEX_16
:
349 pack_c16 ((gfc_array_c16
*) ret
, (gfc_array_c16
*) array
,
350 (gfc_array_l1
*) mask
, (gfc_array_c16
*) vector
);
355 /* For derived types, let's check the actual alignment of the
356 data pointers. If they are aligned, we can safely call
357 the unpack functions. */
359 case GFC_DTYPE_DERIVED_2
:
360 if (GFC_UNALIGNED_2(ret
->base_addr
) || GFC_UNALIGNED_2(array
->base_addr
)
361 || (vector
&& GFC_UNALIGNED_2(vector
->base_addr
)))
365 pack_i2 ((gfc_array_i2
*) ret
, (gfc_array_i2
*) array
,
366 (gfc_array_l1
*) mask
, (gfc_array_i2
*) vector
);
370 case GFC_DTYPE_DERIVED_4
:
371 if (GFC_UNALIGNED_4(ret
->base_addr
) || GFC_UNALIGNED_4(array
->base_addr
)
372 || (vector
&& GFC_UNALIGNED_4(vector
->base_addr
)))
376 pack_i4 ((gfc_array_i4
*) ret
, (gfc_array_i4
*) array
,
377 (gfc_array_l1
*) mask
, (gfc_array_i4
*) vector
);
381 case GFC_DTYPE_DERIVED_8
:
382 if (GFC_UNALIGNED_8(ret
->base_addr
) || GFC_UNALIGNED_8(array
->base_addr
)
383 || (vector
&& GFC_UNALIGNED_8(vector
->base_addr
)))
387 pack_i8 ((gfc_array_i8
*) ret
, (gfc_array_i8
*) array
,
388 (gfc_array_l1
*) mask
, (gfc_array_i8
*) vector
);
392 #ifdef HAVE_GFC_INTEGER_16
393 case GFC_DTYPE_DERIVED_16
:
394 if (GFC_UNALIGNED_16(ret
->base_addr
) || GFC_UNALIGNED_16(array
->base_addr
)
395 || (vector
&& GFC_UNALIGNED_16(vector
->base_addr
)))
399 pack_i16 ((gfc_array_i16
*) ret
, (gfc_array_i16
*) array
,
400 (gfc_array_l1
*) mask
, (gfc_array_i16
*) vector
);
407 size
= GFC_DESCRIPTOR_SIZE (array
);
408 pack_internal (ret
, array
, mask
, vector
, size
);
412 extern void pack_char (gfc_array_char
*, GFC_INTEGER_4
, const gfc_array_char
*,
413 const gfc_array_l1
*, const gfc_array_char
*,
414 GFC_INTEGER_4
, GFC_INTEGER_4
);
415 export_proto(pack_char
);
418 pack_char (gfc_array_char
*ret
,
419 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
420 const gfc_array_char
*array
, const gfc_array_l1
*mask
,
421 const gfc_array_char
*vector
, GFC_INTEGER_4 array_length
,
422 GFC_INTEGER_4 vector_length
__attribute__((unused
)))
424 pack_internal (ret
, array
, mask
, vector
, array_length
);
428 extern void pack_char4 (gfc_array_char
*, GFC_INTEGER_4
, const gfc_array_char
*,
429 const gfc_array_l1
*, const gfc_array_char
*,
430 GFC_INTEGER_4
, GFC_INTEGER_4
);
431 export_proto(pack_char4
);
434 pack_char4 (gfc_array_char
*ret
,
435 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
436 const gfc_array_char
*array
, const gfc_array_l1
*mask
,
437 const gfc_array_char
*vector
, GFC_INTEGER_4 array_length
,
438 GFC_INTEGER_4 vector_length
__attribute__((unused
)))
440 pack_internal (ret
, array
, mask
, vector
, array_length
* sizeof (gfc_char4_t
));
445 pack_s_internal (gfc_array_char
*ret
, const gfc_array_char
*array
,
446 const GFC_LOGICAL_4
*mask
, const gfc_array_char
*vector
,
449 /* r.* indicates the return array. */
452 /* s.* indicates the source array. */
453 index_type sstride
[GFC_MAX_DIMENSIONS
];
457 index_type count
[GFC_MAX_DIMENSIONS
];
458 index_type extent
[GFC_MAX_DIMENSIONS
];
465 dim
= GFC_DESCRIPTOR_RANK (array
);
466 /* Initialize sstride[0] to avoid -Wmaybe-uninitialized
470 for (n
= 0; n
< dim
; n
++)
473 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
477 sstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(array
,n
);
483 sstride0
= sstride
[0];
486 sptr
= array
->base_addr
;
490 if (ret
->base_addr
== NULL
)
492 /* Allocate the memory for the result. */
496 /* The return array will have as many elements as there are
498 total
= GFC_DESCRIPTOR_EXTENT(vector
,0);
509 /* The result array will have as many elements as the input
512 for (n
= 1; n
< dim
; n
++)
516 /* The result array will be empty. */
520 /* Setup the array descriptor. */
521 GFC_DIMENSION_SET(ret
->dim
[0],0,total
-1,1);
525 ret
->base_addr
= xmallocarray (total
, size
);
531 rstride0
= GFC_DESCRIPTOR_STRIDE_BYTES(ret
,0);
534 rptr
= ret
->base_addr
;
536 /* The remaining possibilities are now:
537 If MASK is .TRUE., we have to copy the source array into the
538 result array. We then have to fill it up with elements from VECTOR.
539 If MASK is .FALSE., we have to copy VECTOR into the result
540 array. If VECTOR were not present we would have already returned. */
542 if (*mask
&& ssize
!= 0)
546 /* Add this element. */
547 memcpy (rptr
, sptr
, size
);
550 /* Advance to the next element. */
554 while (count
[n
] == extent
[n
])
556 /* When we get to the end of a dimension, reset it and
557 increment the next dimension. */
559 /* We could precalculate these products, but this is a
560 less frequently used path so probably not worth it. */
561 sptr
-= sstride
[n
] * extent
[n
];
565 /* Break out of the loop. */
578 /* Add any remaining elements from VECTOR. */
581 n
= GFC_DESCRIPTOR_EXTENT(vector
,0);
582 nelem
= ((rptr
- ret
->base_addr
) / rstride0
);
585 sstride0
= GFC_DESCRIPTOR_STRIDE_BYTES(vector
,0);
589 sptr
= vector
->base_addr
+ sstride0
* nelem
;
593 memcpy (rptr
, sptr
, size
);
601 extern void pack_s (gfc_array_char
*ret
, const gfc_array_char
*array
,
602 const GFC_LOGICAL_4
*, const gfc_array_char
*);
603 export_proto(pack_s
);
606 pack_s (gfc_array_char
*ret
, const gfc_array_char
*array
,
607 const GFC_LOGICAL_4
*mask
, const gfc_array_char
*vector
)
609 pack_s_internal (ret
, array
, mask
, vector
, GFC_DESCRIPTOR_SIZE (array
));
613 extern void pack_s_char (gfc_array_char
*ret
, GFC_INTEGER_4
,
614 const gfc_array_char
*array
, const GFC_LOGICAL_4
*,
615 const gfc_array_char
*, GFC_INTEGER_4
,
617 export_proto(pack_s_char
);
620 pack_s_char (gfc_array_char
*ret
,
621 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
622 const gfc_array_char
*array
, const GFC_LOGICAL_4
*mask
,
623 const gfc_array_char
*vector
, GFC_INTEGER_4 array_length
,
624 GFC_INTEGER_4 vector_length
__attribute__((unused
)))
626 pack_s_internal (ret
, array
, mask
, vector
, array_length
);
630 extern void pack_s_char4 (gfc_array_char
*ret
, GFC_INTEGER_4
,
631 const gfc_array_char
*array
, const GFC_LOGICAL_4
*,
632 const gfc_array_char
*, GFC_INTEGER_4
,
634 export_proto(pack_s_char4
);
637 pack_s_char4 (gfc_array_char
*ret
,
638 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
639 const gfc_array_char
*array
, const GFC_LOGICAL_4
*mask
,
640 const gfc_array_char
*vector
, GFC_INTEGER_4 array_length
,
641 GFC_INTEGER_4 vector_length
__attribute__((unused
)))
643 pack_s_internal (ret
, array
, mask
, vector
,
644 array_length
* sizeof (gfc_char4_t
));