Home | History | Annotate | Line # | Download | only in intrinsics
      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