Rebase.
[official-gcc.git] / libgfortran / intrinsics / pack_generic.c
blob3fbfa0aaa030e3a51cf4350892ad14ee443315d0
1 /* Generic implementation of the PACK intrinsic
2 Copyright (C) 2002-2014 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 <stdlib.h>
28 #include <assert.h>
29 #include <string.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
36 control of a mask.
38 Class: Transformational function.
40 Arguments:
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
62 | 0 0 0 |
63 | 9 0 0 | may be "gathered" by the function PACK. The result of
64 | 0 0 7 |
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. */
71 static void
72 pack_internal (gfc_array_char *ret, const gfc_array_char *array,
73 const gfc_array_l1 *mask, const gfc_array_char *vector,
74 index_type size)
76 /* r.* indicates the return array. */
77 index_type rstride0;
78 char * restrict rptr;
79 /* s.* indicates the source array. */
80 index_type sstride[GFC_MAX_DIMENSIONS];
81 index_type sstride0;
82 const char *sptr;
83 /* m.* indicates the mask array. */
84 index_type mstride[GFC_MAX_DIMENSIONS];
85 index_type mstride0;
86 const GFC_LOGICAL_1 *mptr;
88 index_type count[GFC_MAX_DIMENSIONS];
89 index_type extent[GFC_MAX_DIMENSIONS];
90 index_type n;
91 index_type dim;
92 index_type nelem;
93 index_type total;
94 int mask_kind;
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
108 || mask_kind == 16
109 #endif
112 /* Don't convert a NULL pointer as we use test for NULL below. */
113 if (mptr)
114 mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind);
116 else
117 runtime_error ("Funny sized logical array");
119 for (n = 0; n < dim; n++)
121 count[n] = 0;
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);
126 if (sstride[0] == 0)
127 sstride[0] = size;
128 if (mstride[0] == 0)
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. */
136 if (vector != NULL)
138 /* The return array will have as many
139 elements as there are in VECTOR. */
140 total = GFC_DESCRIPTOR_EXTENT(vector,0);
142 else
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);
154 ret->offset = 0;
155 /* xmallocarray allocates a single byte for zero size. */
156 ret->base_addr = xmallocarray (total, size);
158 if (total == 0)
159 return; /* In this case, nothing remains to be done. */
161 else
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);
175 if (rstride0 == 0)
176 rstride0 = size;
177 sstride0 = sstride[0];
178 mstride0 = mstride[0];
179 rptr = ret->base_addr;
181 while (sptr && mptr)
183 /* Test this element. */
184 if (*mptr)
186 /* Add it. */
187 memcpy (rptr, sptr, size);
188 rptr += rstride0;
190 /* Advance to the next element. */
191 sptr += sstride0;
192 mptr += mstride0;
193 count[0]++;
194 n = 0;
195 while (count[n] == extent[n])
197 /* When we get to the end of a dimension, reset it and increment
198 the next dimension. */
199 count[n] = 0;
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];
204 n++;
205 if (n >= dim)
207 /* Break out of the loop. */
208 sptr = NULL;
209 break;
211 else
213 count[n]++;
214 sptr += sstride[n];
215 mptr += mstride[n];
220 /* Add any remaining elements from VECTOR. */
221 if (vector)
223 n = GFC_DESCRIPTOR_EXTENT(vector,0);
224 nelem = ((rptr - ret->base_addr) / rstride0);
225 if (n > nelem)
227 sstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(vector,0);
228 if (sstride0 == 0)
229 sstride0 = size;
231 sptr = vector->base_addr + sstride0 * nelem;
232 n -= nelem;
233 while (n--)
235 memcpy (rptr, sptr, size);
236 rptr += rstride0;
237 sptr += sstride0;
243 extern void pack (gfc_array_char *, const gfc_array_char *,
244 const gfc_array_l1 *, const gfc_array_char *);
245 export_proto(pack);
247 void
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;
252 index_type size;
254 type_size = GFC_DTYPE_TYPE_SIZE(array);
256 switch(type_size)
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);
263 return;
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);
269 return;
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);
275 return;
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);
281 return;
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);
288 return;
289 #endif
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);
294 return;
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);
299 return;
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);
312 return;
313 # endif
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);
319 return;
320 # endif
321 #endif
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);
326 return;
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);
331 return;
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);
344 return;
345 # endif
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);
351 return;
352 # endif
353 #endif
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)))
362 break;
363 else
365 pack_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) array,
366 (gfc_array_l1 *) mask, (gfc_array_i2 *) vector);
367 return;
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)))
373 break;
374 else
376 pack_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) array,
377 (gfc_array_l1 *) mask, (gfc_array_i4 *) vector);
378 return;
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)))
384 break;
385 else
387 pack_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) array,
388 (gfc_array_l1 *) mask, (gfc_array_i8 *) vector);
389 return;
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)))
396 break;
397 else
399 pack_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) array,
400 (gfc_array_l1 *) mask, (gfc_array_i16 *) vector);
401 return;
403 #endif
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);
417 void
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);
433 void
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));
444 static void
445 pack_s_internal (gfc_array_char *ret, const gfc_array_char *array,
446 const GFC_LOGICAL_4 *mask, const gfc_array_char *vector,
447 index_type size)
449 /* r.* indicates the return array. */
450 index_type rstride0;
451 char *rptr;
452 /* s.* indicates the source array. */
453 index_type sstride[GFC_MAX_DIMENSIONS];
454 index_type sstride0;
455 const char *sptr;
457 index_type count[GFC_MAX_DIMENSIONS];
458 index_type extent[GFC_MAX_DIMENSIONS];
459 index_type n;
460 index_type dim;
461 index_type ssize;
462 index_type nelem;
463 index_type total;
465 dim = GFC_DESCRIPTOR_RANK (array);
466 ssize = 1;
467 for (n = 0; n < dim; n++)
469 count[n] = 0;
470 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
471 if (extent[n] < 0)
472 extent[n] = 0;
474 sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n);
475 ssize *= extent[n];
477 if (sstride[0] == 0)
478 sstride[0] = size;
480 sstride0 = sstride[0];
482 if (ssize != 0)
483 sptr = array->base_addr;
484 else
485 sptr = NULL;
487 if (ret->base_addr == NULL)
489 /* Allocate the memory for the result. */
491 if (vector != NULL)
493 /* The return array will have as many elements as there are
494 in vector. */
495 total = GFC_DESCRIPTOR_EXTENT(vector,0);
496 if (total <= 0)
498 total = 0;
499 vector = NULL;
502 else
504 if (*mask)
506 /* The result array will have as many elements as the input
507 array. */
508 total = extent[0];
509 for (n = 1; n < dim; n++)
510 total *= extent[n];
512 else
513 /* The result array will be empty. */
514 total = 0;
517 /* Setup the array descriptor. */
518 GFC_DIMENSION_SET(ret->dim[0],0,total-1,1);
520 ret->offset = 0;
522 ret->base_addr = xmallocarray (total, size);
524 if (total == 0)
525 return;
528 rstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(ret,0);
529 if (rstride0 == 0)
530 rstride0 = size;
531 rptr = ret->base_addr;
533 /* The remaining possibilities are now:
534 If MASK is .TRUE., we have to copy the source array into the
535 result array. We then have to fill it up with elements from VECTOR.
536 If MASK is .FALSE., we have to copy VECTOR into the result
537 array. If VECTOR were not present we would have already returned. */
539 if (*mask && ssize != 0)
541 while (sptr)
543 /* Add this element. */
544 memcpy (rptr, sptr, size);
545 rptr += rstride0;
547 /* Advance to the next element. */
548 sptr += sstride0;
549 count[0]++;
550 n = 0;
551 while (count[n] == extent[n])
553 /* When we get to the end of a dimension, reset it and
554 increment the next dimension. */
555 count[n] = 0;
556 /* We could precalculate these products, but this is a
557 less frequently used path so probably not worth it. */
558 sptr -= sstride[n] * extent[n];
559 n++;
560 if (n >= dim)
562 /* Break out of the loop. */
563 sptr = NULL;
564 break;
566 else
568 count[n]++;
569 sptr += sstride[n];
575 /* Add any remaining elements from VECTOR. */
576 if (vector)
578 n = GFC_DESCRIPTOR_EXTENT(vector,0);
579 nelem = ((rptr - ret->base_addr) / rstride0);
580 if (n > nelem)
582 sstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(vector,0);
583 if (sstride0 == 0)
584 sstride0 = size;
586 sptr = vector->base_addr + sstride0 * nelem;
587 n -= nelem;
588 while (n--)
590 memcpy (rptr, sptr, size);
591 rptr += rstride0;
592 sptr += sstride0;
598 extern void pack_s (gfc_array_char *ret, const gfc_array_char *array,
599 const GFC_LOGICAL_4 *, const gfc_array_char *);
600 export_proto(pack_s);
602 void
603 pack_s (gfc_array_char *ret, const gfc_array_char *array,
604 const GFC_LOGICAL_4 *mask, const gfc_array_char *vector)
606 pack_s_internal (ret, array, mask, vector, GFC_DESCRIPTOR_SIZE (array));
610 extern void pack_s_char (gfc_array_char *ret, GFC_INTEGER_4,
611 const gfc_array_char *array, const GFC_LOGICAL_4 *,
612 const gfc_array_char *, GFC_INTEGER_4,
613 GFC_INTEGER_4);
614 export_proto(pack_s_char);
616 void
617 pack_s_char (gfc_array_char *ret,
618 GFC_INTEGER_4 ret_length __attribute__((unused)),
619 const gfc_array_char *array, const GFC_LOGICAL_4 *mask,
620 const gfc_array_char *vector, GFC_INTEGER_4 array_length,
621 GFC_INTEGER_4 vector_length __attribute__((unused)))
623 pack_s_internal (ret, array, mask, vector, array_length);
627 extern void pack_s_char4 (gfc_array_char *ret, GFC_INTEGER_4,
628 const gfc_array_char *array, const GFC_LOGICAL_4 *,
629 const gfc_array_char *, GFC_INTEGER_4,
630 GFC_INTEGER_4);
631 export_proto(pack_s_char4);
633 void
634 pack_s_char4 (gfc_array_char *ret,
635 GFC_INTEGER_4 ret_length __attribute__((unused)),
636 const gfc_array_char *array, const GFC_LOGICAL_4 *mask,
637 const gfc_array_char *vector, GFC_INTEGER_4 array_length,
638 GFC_INTEGER_4 vector_length __attribute__((unused)))
640 pack_s_internal (ret, array, mask, vector,
641 array_length * sizeof (gfc_char4_t));