Home | History | Annotate | Line # | Download | only in generated
      1      1.1  mrg /* Specific implementation of the UNPACK intrinsic
      2  1.1.1.4  mrg    Copyright (C) 2008-2024 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Thomas Koenig <tkoenig (at) gcc.gnu.org>, based on
      4      1.1  mrg    unpack_generic.c by Paul Brook <paul (at) nowt.org>.
      5      1.1  mrg 
      6      1.1  mrg This file is part of the GNU Fortran runtime library (libgfortran).
      7      1.1  mrg 
      8      1.1  mrg Libgfortran is free software; you can redistribute it and/or
      9      1.1  mrg modify it under the terms of the GNU General Public
     10      1.1  mrg License as published by the Free Software Foundation; either
     11      1.1  mrg version 3 of the License, or (at your option) any later version.
     12      1.1  mrg 
     13      1.1  mrg Ligbfortran is distributed in the hope that it will be useful,
     14      1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     15      1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16      1.1  mrg GNU General Public License for more details.
     17      1.1  mrg 
     18      1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     19      1.1  mrg permissions described in the GCC Runtime Library Exception, version
     20      1.1  mrg 3.1, as published by the Free Software Foundation.
     21      1.1  mrg 
     22      1.1  mrg You should have received a copy of the GNU General Public License and
     23      1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     24      1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25      1.1  mrg <http://www.gnu.org/licenses/>.  */
     26      1.1  mrg 
     27      1.1  mrg #include "libgfortran.h"
     28      1.1  mrg #include <string.h>
     29      1.1  mrg 
     30      1.1  mrg 
     31      1.1  mrg #if defined (HAVE_GFC_INTEGER_4)
     32      1.1  mrg 
     33      1.1  mrg void
     34      1.1  mrg unpack0_i4 (gfc_array_i4 *ret, const gfc_array_i4 *vector,
     35      1.1  mrg 		 const gfc_array_l1 *mask, const GFC_INTEGER_4 *fptr)
     36      1.1  mrg {
     37      1.1  mrg   /* r.* indicates the return array.  */
     38      1.1  mrg   index_type rstride[GFC_MAX_DIMENSIONS];
     39      1.1  mrg   index_type rstride0;
     40      1.1  mrg   index_type rs;
     41      1.1  mrg   GFC_INTEGER_4 * restrict rptr;
     42      1.1  mrg   /* v.* indicates the vector array.  */
     43      1.1  mrg   index_type vstride0;
     44      1.1  mrg   GFC_INTEGER_4 *vptr;
     45      1.1  mrg   /* Value for field, this is constant.  */
     46      1.1  mrg   const GFC_INTEGER_4 fval = *fptr;
     47      1.1  mrg   /* m.* indicates the mask array.  */
     48      1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
     49      1.1  mrg   index_type mstride0;
     50      1.1  mrg   const GFC_LOGICAL_1 *mptr;
     51      1.1  mrg 
     52      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     53      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     54      1.1  mrg   index_type n;
     55      1.1  mrg   index_type dim;
     56      1.1  mrg 
     57      1.1  mrg   int empty;
     58      1.1  mrg   int mask_kind;
     59      1.1  mrg 
     60      1.1  mrg   empty = 0;
     61      1.1  mrg 
     62      1.1  mrg   mptr = mask->base_addr;
     63      1.1  mrg 
     64      1.1  mrg   /* Use the same loop for all logical types, by using GFC_LOGICAL_1
     65      1.1  mrg      and using shifting to address size and endian issues.  */
     66      1.1  mrg 
     67      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
     68      1.1  mrg 
     69      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
     70      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
     71      1.1  mrg       || mask_kind == 16
     72      1.1  mrg #endif
     73      1.1  mrg       )
     74      1.1  mrg     {
     75      1.1  mrg       /*  Do not convert a NULL pointer as we use test for NULL below.  */
     76      1.1  mrg       if (mptr)
     77      1.1  mrg 	mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind);
     78      1.1  mrg     }
     79      1.1  mrg   else
     80      1.1  mrg     runtime_error ("Funny sized logical array");
     81      1.1  mrg 
     82  1.1.1.3  mrg   /* Initialize to avoid -Wmaybe-uninitialized complaints.  */
     83  1.1.1.3  mrg   rstride[0] = 1;
     84      1.1  mrg   if (ret->base_addr == NULL)
     85      1.1  mrg     {
     86      1.1  mrg       /* The front end has signalled that we need to populate the
     87      1.1  mrg 	 return array descriptor.  */
     88      1.1  mrg       dim = GFC_DESCRIPTOR_RANK (mask);
     89      1.1  mrg       rs = 1;
     90      1.1  mrg       for (n = 0; n < dim; n++)
     91      1.1  mrg 	{
     92      1.1  mrg 	  count[n] = 0;
     93      1.1  mrg 	  GFC_DIMENSION_SET(ret->dim[n], 0,
     94      1.1  mrg 			    GFC_DESCRIPTOR_EXTENT(mask,n) - 1, rs);
     95      1.1  mrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
     96      1.1  mrg 	  empty = empty || extent[n] <= 0;
     97      1.1  mrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
     98      1.1  mrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
     99      1.1  mrg 	  rs *= extent[n];
    100      1.1  mrg 	}
    101      1.1  mrg       ret->offset = 0;
    102      1.1  mrg       ret->base_addr = xmallocarray (rs, sizeof (GFC_INTEGER_4));
    103      1.1  mrg     }
    104      1.1  mrg   else
    105      1.1  mrg     {
    106      1.1  mrg       dim = GFC_DESCRIPTOR_RANK (ret);
    107      1.1  mrg       for (n = 0; n < dim; n++)
    108      1.1  mrg 	{
    109      1.1  mrg 	  count[n] = 0;
    110      1.1  mrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
    111      1.1  mrg 	  empty = empty || extent[n] <= 0;
    112      1.1  mrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
    113      1.1  mrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    114      1.1  mrg 	}
    115      1.1  mrg       if (rstride[0] == 0)
    116      1.1  mrg 	rstride[0] = 1;
    117      1.1  mrg     }
    118      1.1  mrg 
    119      1.1  mrg   if (empty)
    120      1.1  mrg     return;
    121      1.1  mrg 
    122      1.1  mrg   if (mstride[0] == 0)
    123      1.1  mrg     mstride[0] = 1;
    124      1.1  mrg 
    125      1.1  mrg   vstride0 = GFC_DESCRIPTOR_STRIDE(vector,0);
    126      1.1  mrg   if (vstride0 == 0)
    127      1.1  mrg     vstride0 = 1;
    128      1.1  mrg   rstride0 = rstride[0];
    129      1.1  mrg   mstride0 = mstride[0];
    130      1.1  mrg   rptr = ret->base_addr;
    131      1.1  mrg   vptr = vector->base_addr;
    132      1.1  mrg 
    133      1.1  mrg   while (rptr)
    134      1.1  mrg     {
    135      1.1  mrg       if (*mptr)
    136      1.1  mrg         {
    137      1.1  mrg 	  /* From vector.  */
    138      1.1  mrg 	  *rptr = *vptr;
    139      1.1  mrg 	  vptr += vstride0;
    140      1.1  mrg         }
    141      1.1  mrg       else
    142      1.1  mrg         {
    143      1.1  mrg 	  /* From field.  */
    144      1.1  mrg 	  *rptr = fval;
    145      1.1  mrg         }
    146      1.1  mrg       /* Advance to the next element.  */
    147      1.1  mrg       rptr += rstride0;
    148      1.1  mrg       mptr += mstride0;
    149      1.1  mrg       count[0]++;
    150      1.1  mrg       n = 0;
    151      1.1  mrg       while (count[n] == extent[n])
    152      1.1  mrg         {
    153      1.1  mrg           /* When we get to the end of a dimension, reset it and increment
    154      1.1  mrg              the next dimension.  */
    155      1.1  mrg           count[n] = 0;
    156      1.1  mrg           /* We could precalculate these products, but this is a less
    157      1.1  mrg              frequently used path so probably not worth it.  */
    158      1.1  mrg           rptr -= rstride[n] * extent[n];
    159      1.1  mrg           mptr -= mstride[n] * extent[n];
    160      1.1  mrg           n++;
    161      1.1  mrg           if (n >= dim)
    162      1.1  mrg             {
    163      1.1  mrg               /* Break out of the loop.  */
    164      1.1  mrg               rptr = NULL;
    165      1.1  mrg               break;
    166      1.1  mrg             }
    167      1.1  mrg           else
    168      1.1  mrg             {
    169      1.1  mrg               count[n]++;
    170      1.1  mrg               rptr += rstride[n];
    171      1.1  mrg               mptr += mstride[n];
    172      1.1  mrg             }
    173      1.1  mrg         }
    174      1.1  mrg     }
    175      1.1  mrg }
    176      1.1  mrg 
    177      1.1  mrg void
    178      1.1  mrg unpack1_i4 (gfc_array_i4 *ret, const gfc_array_i4 *vector,
    179      1.1  mrg 		 const gfc_array_l1 *mask, const gfc_array_i4 *field)
    180      1.1  mrg {
    181      1.1  mrg   /* r.* indicates the return array.  */
    182      1.1  mrg   index_type rstride[GFC_MAX_DIMENSIONS];
    183      1.1  mrg   index_type rstride0;
    184      1.1  mrg   index_type rs;
    185      1.1  mrg   GFC_INTEGER_4 * restrict rptr;
    186      1.1  mrg   /* v.* indicates the vector array.  */
    187      1.1  mrg   index_type vstride0;
    188      1.1  mrg   GFC_INTEGER_4 *vptr;
    189      1.1  mrg   /* f.* indicates the field array.  */
    190      1.1  mrg   index_type fstride[GFC_MAX_DIMENSIONS];
    191      1.1  mrg   index_type fstride0;
    192      1.1  mrg   const GFC_INTEGER_4 *fptr;
    193      1.1  mrg   /* m.* indicates the mask array.  */
    194      1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
    195      1.1  mrg   index_type mstride0;
    196      1.1  mrg   const GFC_LOGICAL_1 *mptr;
    197      1.1  mrg 
    198      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    199      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    200      1.1  mrg   index_type n;
    201      1.1  mrg   index_type dim;
    202      1.1  mrg 
    203      1.1  mrg   int empty;
    204      1.1  mrg   int mask_kind;
    205      1.1  mrg 
    206      1.1  mrg   empty = 0;
    207      1.1  mrg 
    208      1.1  mrg   mptr = mask->base_addr;
    209      1.1  mrg 
    210      1.1  mrg   /* Use the same loop for all logical types, by using GFC_LOGICAL_1
    211      1.1  mrg      and using shifting to address size and endian issues.  */
    212      1.1  mrg 
    213      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    214      1.1  mrg 
    215      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    216      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    217      1.1  mrg       || mask_kind == 16
    218      1.1  mrg #endif
    219      1.1  mrg       )
    220      1.1  mrg     {
    221      1.1  mrg       /*  Do not convert a NULL pointer as we use test for NULL below.  */
    222      1.1  mrg       if (mptr)
    223      1.1  mrg 	mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind);
    224      1.1  mrg     }
    225      1.1  mrg   else
    226      1.1  mrg     runtime_error ("Funny sized logical array");
    227      1.1  mrg 
    228  1.1.1.3  mrg   /* Initialize to avoid -Wmaybe-uninitialized complaints.  */
    229  1.1.1.3  mrg   rstride[0] = 1;
    230      1.1  mrg   if (ret->base_addr == NULL)
    231      1.1  mrg     {
    232      1.1  mrg       /* The front end has signalled that we need to populate the
    233      1.1  mrg 	 return array descriptor.  */
    234      1.1  mrg       dim = GFC_DESCRIPTOR_RANK (mask);
    235      1.1  mrg       rs = 1;
    236      1.1  mrg       for (n = 0; n < dim; n++)
    237      1.1  mrg 	{
    238      1.1  mrg 	  count[n] = 0;
    239      1.1  mrg 	  GFC_DIMENSION_SET(ret->dim[n], 0,
    240      1.1  mrg 			    GFC_DESCRIPTOR_EXTENT(mask,n) - 1, rs);
    241      1.1  mrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
    242      1.1  mrg 	  empty = empty || extent[n] <= 0;
    243      1.1  mrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
    244      1.1  mrg 	  fstride[n] = GFC_DESCRIPTOR_STRIDE(field,n);
    245      1.1  mrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    246      1.1  mrg 	  rs *= extent[n];
    247      1.1  mrg 	}
    248      1.1  mrg       ret->offset = 0;
    249      1.1  mrg       ret->base_addr = xmallocarray (rs, sizeof (GFC_INTEGER_4));
    250      1.1  mrg     }
    251      1.1  mrg   else
    252      1.1  mrg     {
    253      1.1  mrg       dim = GFC_DESCRIPTOR_RANK (ret);
    254      1.1  mrg       for (n = 0; n < dim; n++)
    255      1.1  mrg 	{
    256      1.1  mrg 	  count[n] = 0;
    257      1.1  mrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
    258      1.1  mrg 	  empty = empty || extent[n] <= 0;
    259      1.1  mrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
    260      1.1  mrg 	  fstride[n] = GFC_DESCRIPTOR_STRIDE(field,n);
    261      1.1  mrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    262      1.1  mrg 	}
    263      1.1  mrg       if (rstride[0] == 0)
    264      1.1  mrg 	rstride[0] = 1;
    265      1.1  mrg     }
    266      1.1  mrg 
    267      1.1  mrg   if (empty)
    268      1.1  mrg     return;
    269      1.1  mrg 
    270      1.1  mrg   if (fstride[0] == 0)
    271      1.1  mrg     fstride[0] = 1;
    272      1.1  mrg   if (mstride[0] == 0)
    273      1.1  mrg     mstride[0] = 1;
    274      1.1  mrg 
    275      1.1  mrg   vstride0 = GFC_DESCRIPTOR_STRIDE(vector,0);
    276      1.1  mrg   if (vstride0 == 0)
    277      1.1  mrg     vstride0 = 1;
    278      1.1  mrg   rstride0 = rstride[0];
    279      1.1  mrg   fstride0 = fstride[0];
    280      1.1  mrg   mstride0 = mstride[0];
    281      1.1  mrg   rptr = ret->base_addr;
    282      1.1  mrg   fptr = field->base_addr;
    283      1.1  mrg   vptr = vector->base_addr;
    284      1.1  mrg 
    285      1.1  mrg   while (rptr)
    286      1.1  mrg     {
    287      1.1  mrg       if (*mptr)
    288      1.1  mrg         {
    289      1.1  mrg           /* From vector.  */
    290      1.1  mrg 	  *rptr = *vptr;
    291      1.1  mrg           vptr += vstride0;
    292      1.1  mrg         }
    293      1.1  mrg       else
    294      1.1  mrg         {
    295      1.1  mrg           /* From field.  */
    296      1.1  mrg 	  *rptr = *fptr;
    297      1.1  mrg         }
    298      1.1  mrg       /* Advance to the next element.  */
    299      1.1  mrg       rptr += rstride0;
    300      1.1  mrg       fptr += fstride0;
    301      1.1  mrg       mptr += mstride0;
    302      1.1  mrg       count[0]++;
    303      1.1  mrg       n = 0;
    304      1.1  mrg       while (count[n] == extent[n])
    305      1.1  mrg         {
    306      1.1  mrg           /* When we get to the end of a dimension, reset it and increment
    307      1.1  mrg              the next dimension.  */
    308      1.1  mrg           count[n] = 0;
    309      1.1  mrg           /* We could precalculate these products, but this is a less
    310      1.1  mrg              frequently used path so probably not worth it.  */
    311      1.1  mrg           rptr -= rstride[n] * extent[n];
    312      1.1  mrg           fptr -= fstride[n] * extent[n];
    313      1.1  mrg           mptr -= mstride[n] * extent[n];
    314      1.1  mrg           n++;
    315      1.1  mrg           if (n >= dim)
    316      1.1  mrg             {
    317      1.1  mrg               /* Break out of the loop.  */
    318      1.1  mrg               rptr = NULL;
    319      1.1  mrg               break;
    320      1.1  mrg             }
    321      1.1  mrg           else
    322      1.1  mrg             {
    323      1.1  mrg               count[n]++;
    324      1.1  mrg               rptr += rstride[n];
    325      1.1  mrg               fptr += fstride[n];
    326      1.1  mrg               mptr += mstride[n];
    327      1.1  mrg             }
    328      1.1  mrg         }
    329      1.1  mrg     }
    330      1.1  mrg }
    331      1.1  mrg 
    332      1.1  mrg #endif
    333      1.1  mrg 
    334