Home | History | Annotate | Line # | Download | only in generated
      1      1.1  mrg /* Implementation of the CSHIFT intrinsic
      2  1.1.1.4  mrg    Copyright (C) 2003-2024 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Feng Wang <wf_cs (at) yahoo.com>
      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 
     30      1.1  mrg #if defined (HAVE_GFC_INTEGER_8)
     31      1.1  mrg 
     32      1.1  mrg static void
     33      1.1  mrg cshift1 (gfc_array_char * const restrict ret,
     34      1.1  mrg 	const gfc_array_char * const restrict array,
     35      1.1  mrg 	const gfc_array_i8 * const restrict h,
     36      1.1  mrg 	const GFC_INTEGER_8 * const restrict pwhich)
     37      1.1  mrg {
     38      1.1  mrg   /* r.* indicates the return array.  */
     39      1.1  mrg   index_type rstride[GFC_MAX_DIMENSIONS];
     40      1.1  mrg   index_type rstride0;
     41      1.1  mrg   index_type roffset;
     42      1.1  mrg   char *rptr;
     43      1.1  mrg   char *dest;
     44      1.1  mrg   /* s.* indicates the source array.  */
     45      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     46      1.1  mrg   index_type sstride0;
     47      1.1  mrg   index_type soffset;
     48      1.1  mrg   const char *sptr;
     49      1.1  mrg   const char *src;
     50      1.1  mrg   /* h.* indicates the shift array.  */
     51      1.1  mrg   index_type hstride[GFC_MAX_DIMENSIONS];
     52      1.1  mrg   index_type hstride0;
     53      1.1  mrg   const GFC_INTEGER_8 *hptr;
     54      1.1  mrg 
     55      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     56      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     57      1.1  mrg   index_type dim;
     58      1.1  mrg   index_type len;
     59      1.1  mrg   index_type n;
     60      1.1  mrg   int which;
     61      1.1  mrg   GFC_INTEGER_8 sh;
     62      1.1  mrg   index_type arraysize;
     63      1.1  mrg   index_type size;
     64      1.1  mrg   index_type type_size;
     65      1.1  mrg 
     66      1.1  mrg   if (pwhich)
     67      1.1  mrg     which = *pwhich - 1;
     68      1.1  mrg   else
     69      1.1  mrg     which = 0;
     70      1.1  mrg 
     71      1.1  mrg   if (which < 0 || (which + 1) > GFC_DESCRIPTOR_RANK (array))
     72      1.1  mrg     runtime_error ("Argument 'DIM' is out of range in call to 'CSHIFT'");
     73      1.1  mrg 
     74      1.1  mrg   size = GFC_DESCRIPTOR_SIZE(array);
     75      1.1  mrg 
     76      1.1  mrg   arraysize = size0 ((array_t *)array);
     77      1.1  mrg 
     78      1.1  mrg   if (ret->base_addr == NULL)
     79      1.1  mrg     {
     80      1.1  mrg       ret->base_addr = xmallocarray (arraysize, size);
     81      1.1  mrg       ret->offset = 0;
     82      1.1  mrg       GFC_DTYPE_COPY(ret,array);
     83      1.1  mrg       for (index_type i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
     84      1.1  mrg         {
     85      1.1  mrg 	  index_type ub, str;
     86      1.1  mrg 
     87      1.1  mrg           ub = GFC_DESCRIPTOR_EXTENT(array,i) - 1;
     88      1.1  mrg 
     89      1.1  mrg           if (i == 0)
     90      1.1  mrg             str = 1;
     91      1.1  mrg           else
     92      1.1  mrg 	    str = GFC_DESCRIPTOR_EXTENT(ret,i-1) *
     93      1.1  mrg 	      GFC_DESCRIPTOR_STRIDE(ret,i-1);
     94      1.1  mrg 
     95      1.1  mrg 	  GFC_DIMENSION_SET(ret->dim[i], 0, ub, str);
     96      1.1  mrg         }
     97      1.1  mrg     }
     98      1.1  mrg   else if (unlikely (compile_options.bounds_check))
     99      1.1  mrg     {
    100      1.1  mrg       bounds_equal_extents ((array_t *) ret, (array_t *) array,
    101      1.1  mrg 				 "return value", "CSHIFT");
    102      1.1  mrg     }
    103      1.1  mrg 
    104      1.1  mrg   if (unlikely (compile_options.bounds_check))
    105      1.1  mrg     {
    106      1.1  mrg       bounds_reduced_extents ((array_t *) h, (array_t *) array, which,
    107      1.1  mrg       			      "SHIFT argument", "CSHIFT");
    108      1.1  mrg     }
    109      1.1  mrg 
    110      1.1  mrg   if (arraysize == 0)
    111      1.1  mrg     return;
    112      1.1  mrg 
    113      1.1  mrg   /* See if we should dispatch to a helper function.  */
    114      1.1  mrg 
    115      1.1  mrg   type_size = GFC_DTYPE_TYPE_SIZE (array);
    116      1.1  mrg 
    117      1.1  mrg   switch (type_size)
    118      1.1  mrg   {
    119      1.1  mrg     case GFC_DTYPE_LOGICAL_1:
    120      1.1  mrg     case GFC_DTYPE_INTEGER_1:
    121      1.1  mrg       cshift1_8_i1 ((gfc_array_i1 *)ret, (gfc_array_i1 *) array,
    122      1.1  mrg       			h, pwhich);
    123      1.1  mrg       return;
    124      1.1  mrg 
    125      1.1  mrg     case GFC_DTYPE_LOGICAL_2:
    126      1.1  mrg     case GFC_DTYPE_INTEGER_2:
    127      1.1  mrg       cshift1_8_i2 ((gfc_array_i2 *)ret, (gfc_array_i2 *) array,
    128      1.1  mrg       			h, pwhich);
    129      1.1  mrg       return;
    130      1.1  mrg 
    131      1.1  mrg     case GFC_DTYPE_LOGICAL_4:
    132      1.1  mrg     case GFC_DTYPE_INTEGER_4:
    133      1.1  mrg       cshift1_8_i4 ((gfc_array_i4 *)ret, (gfc_array_i4 *) array,
    134      1.1  mrg       			h, pwhich);
    135      1.1  mrg       return;
    136      1.1  mrg 
    137      1.1  mrg     case GFC_DTYPE_LOGICAL_8:
    138      1.1  mrg     case GFC_DTYPE_INTEGER_8:
    139      1.1  mrg       cshift1_8_i8 ((gfc_array_i8 *)ret, (gfc_array_i8 *) array,
    140      1.1  mrg       			h, pwhich);
    141      1.1  mrg       return;
    142      1.1  mrg 
    143      1.1  mrg #if defined (HAVE_INTEGER_16)
    144      1.1  mrg     case GFC_DTYPE_LOGICAL_16:
    145      1.1  mrg     case GFC_DTYPE_INTEGER_16:
    146      1.1  mrg       cshift1_8_i16 ((gfc_array_i16 *)ret, (gfc_array_i16 *) array,
    147      1.1  mrg       			h, pwhich);
    148      1.1  mrg       return;
    149      1.1  mrg #endif
    150      1.1  mrg 
    151      1.1  mrg     case GFC_DTYPE_REAL_4:
    152      1.1  mrg       cshift1_8_r4 ((gfc_array_r4 *)ret, (gfc_array_r4 *) array,
    153      1.1  mrg       			h, pwhich);
    154      1.1  mrg       return;
    155      1.1  mrg 
    156      1.1  mrg     case GFC_DTYPE_REAL_8:
    157      1.1  mrg       cshift1_8_r8 ((gfc_array_r8 *)ret, (gfc_array_r8 *) array,
    158      1.1  mrg       			h, pwhich);
    159      1.1  mrg       return;
    160      1.1  mrg 
    161      1.1  mrg #if defined (HAVE_REAL_10)
    162      1.1  mrg     case GFC_DTYPE_REAL_10:
    163      1.1  mrg       cshift1_8_r10 ((gfc_array_r10 *)ret, (gfc_array_r10 *) array,
    164      1.1  mrg       			h, pwhich);
    165      1.1  mrg       return;
    166      1.1  mrg #endif
    167      1.1  mrg 
    168      1.1  mrg #if defined (HAVE_REAL_16)
    169      1.1  mrg     case GFC_DTYPE_REAL_16:
    170      1.1  mrg       cshift1_8_r16 ((gfc_array_r16 *)ret, (gfc_array_r16 *) array,
    171      1.1  mrg       			h, pwhich);
    172      1.1  mrg       return;
    173      1.1  mrg #endif
    174      1.1  mrg 
    175      1.1  mrg     case GFC_DTYPE_COMPLEX_4:
    176      1.1  mrg       cshift1_8_c4 ((gfc_array_c4 *)ret, (gfc_array_c4 *) array,
    177      1.1  mrg       			h, pwhich);
    178      1.1  mrg       return;
    179      1.1  mrg 
    180      1.1  mrg     case GFC_DTYPE_COMPLEX_8:
    181      1.1  mrg       cshift1_8_c8 ((gfc_array_c8 *)ret, (gfc_array_c8 *) array,
    182      1.1  mrg       			h, pwhich);
    183      1.1  mrg       return;
    184      1.1  mrg 
    185      1.1  mrg #if defined (HAVE_COMPLEX_10)
    186      1.1  mrg     case GFC_DTYPE_COMPLEX_10:
    187      1.1  mrg       cshift1_8_c10 ((gfc_array_c10 *)ret, (gfc_array_c10 *) array,
    188      1.1  mrg       			h, pwhich);
    189      1.1  mrg       return;
    190      1.1  mrg #endif
    191      1.1  mrg 
    192      1.1  mrg #if defined (HAVE_COMPLEX_16)
    193      1.1  mrg     case GFC_DTYPE_COMPLEX_16:
    194      1.1  mrg       cshift1_8_c16 ((gfc_array_c16 *)ret, (gfc_array_c16 *) array,
    195      1.1  mrg       			h, pwhich);
    196      1.1  mrg       return;
    197      1.1  mrg #endif
    198      1.1  mrg 
    199      1.1  mrg     default:
    200      1.1  mrg       break;
    201      1.1  mrg 
    202      1.1  mrg   }
    203      1.1  mrg 
    204      1.1  mrg   extent[0] = 1;
    205      1.1  mrg   count[0] = 0;
    206      1.1  mrg   n = 0;
    207      1.1  mrg 
    208      1.1  mrg   /* Initialized for avoiding compiler warnings.  */
    209      1.1  mrg   roffset = size;
    210      1.1  mrg   soffset = size;
    211      1.1  mrg   len = 0;
    212      1.1  mrg 
    213      1.1  mrg   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
    214      1.1  mrg     {
    215      1.1  mrg       if (dim == which)
    216      1.1  mrg         {
    217      1.1  mrg           roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
    218      1.1  mrg           if (roffset == 0)
    219      1.1  mrg             roffset = size;
    220      1.1  mrg           soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
    221      1.1  mrg           if (soffset == 0)
    222      1.1  mrg             soffset = size;
    223      1.1  mrg           len = GFC_DESCRIPTOR_EXTENT(array,dim);
    224      1.1  mrg         }
    225      1.1  mrg       else
    226      1.1  mrg         {
    227      1.1  mrg           count[n] = 0;
    228      1.1  mrg           extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
    229      1.1  mrg           rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
    230      1.1  mrg           sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
    231      1.1  mrg 
    232      1.1  mrg           hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
    233      1.1  mrg           n++;
    234      1.1  mrg         }
    235      1.1  mrg     }
    236      1.1  mrg   if (sstride[0] == 0)
    237      1.1  mrg     sstride[0] = size;
    238      1.1  mrg   if (rstride[0] == 0)
    239      1.1  mrg     rstride[0] = size;
    240      1.1  mrg   if (hstride[0] == 0)
    241      1.1  mrg     hstride[0] = 1;
    242      1.1  mrg 
    243      1.1  mrg   dim = GFC_DESCRIPTOR_RANK (array);
    244      1.1  mrg   rstride0 = rstride[0];
    245      1.1  mrg   sstride0 = sstride[0];
    246      1.1  mrg   hstride0 = hstride[0];
    247      1.1  mrg   rptr = ret->base_addr;
    248      1.1  mrg   sptr = array->base_addr;
    249      1.1  mrg   hptr = h->base_addr;
    250      1.1  mrg 
    251      1.1  mrg   while (rptr)
    252      1.1  mrg     {
    253      1.1  mrg       /* Do the shift for this dimension.  */
    254      1.1  mrg       sh = *hptr;
    255      1.1  mrg       /* Normal case should be -len < sh < len; try to
    256      1.1  mrg          avoid the expensive remainder operation if possible.  */
    257      1.1  mrg       if (sh < 0)
    258      1.1  mrg         sh += len;
    259      1.1  mrg       if (unlikely (sh >= len || sh < 0))
    260      1.1  mrg         {
    261      1.1  mrg 	  sh = sh % len;
    262      1.1  mrg 	  if (sh < 0)
    263      1.1  mrg 	    sh += len;
    264      1.1  mrg 	}
    265      1.1  mrg 
    266      1.1  mrg       src = &sptr[sh * soffset];
    267      1.1  mrg       dest = rptr;
    268      1.1  mrg       if (soffset == size && roffset == size)
    269      1.1  mrg       {
    270      1.1  mrg         size_t len1 = sh * size;
    271      1.1  mrg 	size_t len2 = (len - sh) * size;
    272      1.1  mrg 	memcpy (rptr, sptr + len1, len2);
    273      1.1  mrg 	memcpy (rptr + len2, sptr, len1);
    274      1.1  mrg       }
    275      1.1  mrg       else
    276      1.1  mrg         {
    277      1.1  mrg 	  for (n = 0; n < len - sh; n++)
    278      1.1  mrg             {
    279      1.1  mrg 	      memcpy (dest, src, size);
    280      1.1  mrg 	      dest += roffset;
    281      1.1  mrg 	      src += soffset;
    282      1.1  mrg 	    }
    283      1.1  mrg 	    for (src = sptr, n = 0; n < sh; n++)
    284      1.1  mrg 	      {
    285      1.1  mrg 		memcpy (dest, src, size);
    286      1.1  mrg 		dest += roffset;
    287      1.1  mrg 		src += soffset;
    288      1.1  mrg 	      }
    289      1.1  mrg 	  }
    290      1.1  mrg 
    291      1.1  mrg       /* Advance to the next section.  */
    292      1.1  mrg       rptr += rstride0;
    293      1.1  mrg       sptr += sstride0;
    294      1.1  mrg       hptr += hstride0;
    295      1.1  mrg       count[0]++;
    296      1.1  mrg       n = 0;
    297      1.1  mrg       while (count[n] == extent[n])
    298      1.1  mrg         {
    299      1.1  mrg           /* When we get to the end of a dimension, reset it and increment
    300      1.1  mrg              the next dimension.  */
    301      1.1  mrg           count[n] = 0;
    302      1.1  mrg           /* We could precalculate these products, but this is a less
    303      1.1  mrg              frequently used path so probably not worth it.  */
    304      1.1  mrg           rptr -= rstride[n] * extent[n];
    305      1.1  mrg           sptr -= sstride[n] * extent[n];
    306      1.1  mrg 	  hptr -= hstride[n] * extent[n];
    307      1.1  mrg           n++;
    308      1.1  mrg           if (n >= dim - 1)
    309      1.1  mrg             {
    310      1.1  mrg               /* Break out of the loop.  */
    311      1.1  mrg               rptr = NULL;
    312      1.1  mrg               break;
    313      1.1  mrg             }
    314      1.1  mrg           else
    315      1.1  mrg             {
    316      1.1  mrg               count[n]++;
    317      1.1  mrg               rptr += rstride[n];
    318      1.1  mrg               sptr += sstride[n];
    319      1.1  mrg 	      hptr += hstride[n];
    320      1.1  mrg             }
    321      1.1  mrg         }
    322      1.1  mrg     }
    323      1.1  mrg }
    324      1.1  mrg 
    325      1.1  mrg void cshift1_8 (gfc_array_char * const restrict,
    326      1.1  mrg 	const gfc_array_char * const restrict,
    327      1.1  mrg 	const gfc_array_i8 * const restrict,
    328      1.1  mrg 	const GFC_INTEGER_8 * const restrict);
    329      1.1  mrg export_proto(cshift1_8);
    330      1.1  mrg 
    331      1.1  mrg void
    332      1.1  mrg cshift1_8 (gfc_array_char * const restrict ret,
    333      1.1  mrg 	const gfc_array_char * const restrict array,
    334      1.1  mrg 	const gfc_array_i8 * const restrict h,
    335      1.1  mrg 	const GFC_INTEGER_8 * const restrict pwhich)
    336      1.1  mrg {
    337      1.1  mrg   cshift1 (ret, array, h, pwhich);
    338      1.1  mrg }
    339      1.1  mrg 
    340      1.1  mrg 
    341      1.1  mrg void cshift1_8_char (gfc_array_char * const restrict ret,
    342      1.1  mrg 	GFC_INTEGER_4,
    343      1.1  mrg 	const gfc_array_char * const restrict array,
    344      1.1  mrg 	const gfc_array_i8 * const restrict h,
    345      1.1  mrg 	const GFC_INTEGER_8 * const restrict pwhich,
    346      1.1  mrg 	GFC_INTEGER_4);
    347      1.1  mrg export_proto(cshift1_8_char);
    348      1.1  mrg 
    349      1.1  mrg void
    350      1.1  mrg cshift1_8_char (gfc_array_char * const restrict ret,
    351      1.1  mrg 	GFC_INTEGER_4 ret_length __attribute__((unused)),
    352      1.1  mrg 	const gfc_array_char * const restrict array,
    353      1.1  mrg 	const gfc_array_i8 * const restrict h,
    354      1.1  mrg 	const GFC_INTEGER_8 * const restrict pwhich,
    355      1.1  mrg 	GFC_INTEGER_4 array_length __attribute__((unused)))
    356      1.1  mrg {
    357      1.1  mrg   cshift1 (ret, array, h, pwhich);
    358      1.1  mrg }
    359      1.1  mrg 
    360      1.1  mrg 
    361      1.1  mrg void cshift1_8_char4 (gfc_array_char * const restrict ret,
    362      1.1  mrg 	GFC_INTEGER_4,
    363      1.1  mrg 	const gfc_array_char * const restrict array,
    364      1.1  mrg 	const gfc_array_i8 * const restrict h,
    365      1.1  mrg 	const GFC_INTEGER_8 * const restrict pwhich,
    366      1.1  mrg 	GFC_INTEGER_4);
    367      1.1  mrg export_proto(cshift1_8_char4);
    368      1.1  mrg 
    369      1.1  mrg void
    370      1.1  mrg cshift1_8_char4 (gfc_array_char * const restrict ret,
    371      1.1  mrg 	GFC_INTEGER_4 ret_length __attribute__((unused)),
    372      1.1  mrg 	const gfc_array_char * const restrict array,
    373      1.1  mrg 	const gfc_array_i8 * const restrict h,
    374      1.1  mrg 	const GFC_INTEGER_8 * const restrict pwhich,
    375      1.1  mrg 	GFC_INTEGER_4 array_length __attribute__((unused)))
    376      1.1  mrg {
    377      1.1  mrg   cshift1 (ret, array, h, pwhich);
    378      1.1  mrg }
    379      1.1  mrg 
    380      1.1  mrg #endif
    381