Home | History | Annotate | Line # | Download | only in m4
      1      1.1  mrg `/* Implementation of the EOSHIFT intrinsic
      2  1.1.1.4  mrg    Copyright (C) 2002-2024 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Paul Brook <paul (a] 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 Libgfortran 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 include(iparm.m4)dnl
     30      1.1  mrg 
     31      1.1  mrg `#if defined (HAVE_'atype_name`)
     32      1.1  mrg 
     33      1.1  mrg static void
     34      1.1  mrg eoshift1 (gfc_array_char * const restrict ret, 
     35      1.1  mrg 	const gfc_array_char * const restrict array, 
     36      1.1  mrg 	const 'atype` * const restrict h,
     37      1.1  mrg 	const char * const restrict pbound, 
     38      1.1  mrg 	const 'atype_name` * const restrict pwhich, 
     39      1.1  mrg 	const char * filler, index_type filler_len)
     40      1.1  mrg {
     41      1.1  mrg   /* r.* indicates the return array.  */
     42      1.1  mrg   index_type rstride[GFC_MAX_DIMENSIONS];
     43      1.1  mrg   index_type rstride0;
     44      1.1  mrg   index_type roffset;
     45      1.1  mrg   char *rptr;
     46      1.1  mrg   char * restrict dest;
     47      1.1  mrg   /* s.* indicates the source array.  */
     48      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     49      1.1  mrg   index_type sstride0;
     50      1.1  mrg   index_type soffset;
     51      1.1  mrg   const char *sptr;
     52      1.1  mrg   const char *src;
     53      1.1  mrg   /* h.* indicates the shift array.  */
     54      1.1  mrg   index_type hstride[GFC_MAX_DIMENSIONS];
     55      1.1  mrg   index_type hstride0;
     56      1.1  mrg   const 'atype_name` *hptr;
     57      1.1  mrg 
     58      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     59      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     60      1.1  mrg   index_type dim;
     61      1.1  mrg   index_type len;
     62      1.1  mrg   index_type n;
     63      1.1  mrg   index_type size;
     64      1.1  mrg   index_type arraysize;
     65      1.1  mrg   int which;
     66      1.1  mrg   'atype_name` sh;
     67      1.1  mrg   'atype_name` delta;
     68      1.1  mrg 
     69      1.1  mrg   /* The compiler cannot figure out that these are set, initialize
     70      1.1  mrg      them to avoid warnings.  */
     71      1.1  mrg   len = 0;
     72      1.1  mrg   soffset = 0;
     73      1.1  mrg   roffset = 0;
     74      1.1  mrg 
     75      1.1  mrg   size = GFC_DESCRIPTOR_SIZE(array);
     76      1.1  mrg 
     77      1.1  mrg   if (pwhich)
     78      1.1  mrg     which = *pwhich - 1;
     79      1.1  mrg   else
     80      1.1  mrg     which = 0;
     81      1.1  mrg 
     82      1.1  mrg   extent[0] = 1;
     83      1.1  mrg   count[0] = 0;
     84      1.1  mrg 
     85      1.1  mrg   arraysize = size0 ((array_t *) array);
     86      1.1  mrg   if (ret->base_addr == NULL)
     87      1.1  mrg     {
     88      1.1  mrg       ret->offset = 0;
     89      1.1  mrg       GFC_DTYPE_COPY(ret,array);
     90      1.1  mrg       for (index_type i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
     91      1.1  mrg         {
     92      1.1  mrg 	  index_type ub, str;
     93      1.1  mrg 
     94      1.1  mrg 	  ub = GFC_DESCRIPTOR_EXTENT(array,i) - 1;
     95      1.1  mrg 
     96      1.1  mrg           if (i == 0)
     97      1.1  mrg             str = 1;
     98      1.1  mrg           else
     99      1.1  mrg             str = GFC_DESCRIPTOR_EXTENT(ret,i-1)
    100      1.1  mrg 	      * GFC_DESCRIPTOR_STRIDE(ret,i-1);
    101      1.1  mrg 
    102      1.1  mrg 	  GFC_DIMENSION_SET(ret->dim[i], 0, ub, str);
    103      1.1  mrg 
    104      1.1  mrg         }
    105      1.1  mrg       /* xmallocarray allocates a single byte for zero size.  */
    106      1.1  mrg       ret->base_addr = xmallocarray (arraysize, size);
    107      1.1  mrg 
    108      1.1  mrg     }
    109      1.1  mrg   else if (unlikely (compile_options.bounds_check))
    110      1.1  mrg     {
    111      1.1  mrg       bounds_equal_extents ((array_t *) ret, (array_t *) array,
    112      1.1  mrg 				 "return value", "EOSHIFT");
    113      1.1  mrg     }
    114      1.1  mrg 
    115      1.1  mrg   if (unlikely (compile_options.bounds_check))
    116      1.1  mrg     {
    117      1.1  mrg       bounds_reduced_extents ((array_t *) h, (array_t *) array, which,
    118      1.1  mrg       			      "SHIFT argument", "EOSHIFT");
    119      1.1  mrg     }
    120      1.1  mrg 
    121      1.1  mrg   if (arraysize == 0)
    122      1.1  mrg     return;
    123      1.1  mrg 
    124      1.1  mrg   n = 0;
    125      1.1  mrg   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
    126      1.1  mrg     {
    127      1.1  mrg       if (dim == which)
    128      1.1  mrg         {
    129      1.1  mrg           roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
    130      1.1  mrg           if (roffset == 0)
    131      1.1  mrg             roffset = size;
    132      1.1  mrg           soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
    133      1.1  mrg           if (soffset == 0)
    134      1.1  mrg             soffset = size;
    135      1.1  mrg           len = GFC_DESCRIPTOR_EXTENT(array,dim);
    136      1.1  mrg         }
    137      1.1  mrg       else
    138      1.1  mrg         {
    139      1.1  mrg           count[n] = 0;
    140      1.1  mrg           extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
    141      1.1  mrg           rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
    142      1.1  mrg           sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
    143      1.1  mrg 
    144      1.1  mrg           hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
    145      1.1  mrg           n++;
    146      1.1  mrg         }
    147      1.1  mrg     }
    148      1.1  mrg   if (sstride[0] == 0)
    149      1.1  mrg     sstride[0] = size;
    150      1.1  mrg   if (rstride[0] == 0)
    151      1.1  mrg     rstride[0] = size;
    152      1.1  mrg   if (hstride[0] == 0)
    153      1.1  mrg     hstride[0] = 1;
    154      1.1  mrg 
    155      1.1  mrg   dim = GFC_DESCRIPTOR_RANK (array);
    156      1.1  mrg   rstride0 = rstride[0];
    157      1.1  mrg   sstride0 = sstride[0];
    158      1.1  mrg   hstride0 = hstride[0];
    159      1.1  mrg   rptr = ret->base_addr;
    160      1.1  mrg   sptr = array->base_addr;
    161      1.1  mrg   hptr = h->base_addr;
    162      1.1  mrg 
    163      1.1  mrg   while (rptr)
    164      1.1  mrg     {
    165      1.1  mrg       /* Do the shift for this dimension.  */
    166      1.1  mrg       sh = *hptr;
    167      1.1  mrg       if (( sh >= 0 ? sh : -sh ) > len)
    168      1.1  mrg 	{
    169      1.1  mrg 	  delta = len;
    170      1.1  mrg 	  sh = len;
    171      1.1  mrg 	}
    172      1.1  mrg       else
    173      1.1  mrg 	delta = (sh >= 0) ? sh: -sh;
    174      1.1  mrg 
    175      1.1  mrg       if (sh > 0)
    176      1.1  mrg         {
    177      1.1  mrg           src = &sptr[delta * soffset];
    178      1.1  mrg           dest = rptr;
    179      1.1  mrg         }
    180      1.1  mrg       else
    181      1.1  mrg         {
    182      1.1  mrg           src = sptr;
    183      1.1  mrg           dest = &rptr[delta * roffset];
    184      1.1  mrg         }
    185      1.1  mrg 
    186      1.1  mrg       /* If the elements are contiguous, perform a single block move.  */
    187      1.1  mrg       if (soffset == size && roffset == size)
    188      1.1  mrg 	{
    189      1.1  mrg 	  size_t chunk = size * (len - delta);
    190      1.1  mrg 	  memcpy (dest, src, chunk);
    191      1.1  mrg 	  dest += chunk;
    192      1.1  mrg 	}
    193      1.1  mrg       else
    194      1.1  mrg 	{
    195      1.1  mrg 	  for (n = 0; n < len - delta; n++)
    196      1.1  mrg 	    {
    197      1.1  mrg 	      memcpy (dest, src, size);
    198      1.1  mrg 	      dest += roffset;
    199      1.1  mrg 	      src += soffset;
    200      1.1  mrg 	    }
    201      1.1  mrg 	}
    202      1.1  mrg       if (sh < 0)
    203      1.1  mrg         dest = rptr;
    204      1.1  mrg       n = delta;
    205      1.1  mrg 
    206      1.1  mrg       if (pbound)
    207      1.1  mrg 	while (n--)
    208      1.1  mrg 	  {
    209      1.1  mrg 	    memcpy (dest, pbound, size);
    210      1.1  mrg 	    dest += roffset;
    211      1.1  mrg 	  }
    212      1.1  mrg       else
    213      1.1  mrg 	while (n--)
    214      1.1  mrg 	  {
    215      1.1  mrg 	    index_type i;
    216      1.1  mrg 
    217      1.1  mrg 	    if (filler_len == 1)
    218      1.1  mrg 	      memset (dest, filler[0], size);
    219      1.1  mrg 	    else
    220      1.1  mrg 	      for (i = 0; i < size; i += filler_len)
    221      1.1  mrg 		memcpy (&dest[i], filler, filler_len);
    222      1.1  mrg 
    223      1.1  mrg 	    dest += roffset;
    224      1.1  mrg 	  }
    225      1.1  mrg 
    226      1.1  mrg       /* Advance to the next section.  */
    227      1.1  mrg       rptr += rstride0;
    228      1.1  mrg       sptr += sstride0;
    229      1.1  mrg       hptr += hstride0;
    230      1.1  mrg       count[0]++;
    231      1.1  mrg       n = 0;
    232      1.1  mrg       while (count[n] == extent[n])
    233      1.1  mrg         {
    234      1.1  mrg           /* When we get to the end of a dimension, reset it and increment
    235      1.1  mrg              the next dimension.  */
    236      1.1  mrg           count[n] = 0;
    237      1.1  mrg           /* We could precalculate these products, but this is a less
    238      1.1  mrg              frequently used path so probably not worth it.  */
    239      1.1  mrg           rptr -= rstride[n] * extent[n];
    240      1.1  mrg           sptr -= sstride[n] * extent[n];
    241      1.1  mrg 	  hptr -= hstride[n] * extent[n];
    242      1.1  mrg           n++;
    243      1.1  mrg           if (n >= dim - 1)
    244      1.1  mrg             {
    245      1.1  mrg               /* Break out of the loop.  */
    246      1.1  mrg               rptr = NULL;
    247      1.1  mrg               break;
    248      1.1  mrg             }
    249      1.1  mrg           else
    250      1.1  mrg             {
    251      1.1  mrg               count[n]++;
    252      1.1  mrg               rptr += rstride[n];
    253      1.1  mrg               sptr += sstride[n];
    254      1.1  mrg 	      hptr += hstride[n];
    255      1.1  mrg             }
    256      1.1  mrg         }
    257      1.1  mrg     }
    258      1.1  mrg }
    259      1.1  mrg 
    260      1.1  mrg void eoshift1_'atype_kind` (gfc_array_char * const restrict, 
    261      1.1  mrg 	const gfc_array_char * const restrict,
    262      1.1  mrg 	const 'atype` * const restrict, const char * const restrict, 
    263      1.1  mrg 	const 'atype_name` * const restrict);
    264      1.1  mrg export_proto(eoshift1_'atype_kind`);
    265      1.1  mrg 
    266      1.1  mrg void
    267      1.1  mrg eoshift1_'atype_kind` (gfc_array_char * const restrict ret, 
    268      1.1  mrg 	const gfc_array_char * const restrict array,
    269      1.1  mrg 	const 'atype` * const restrict h, 
    270      1.1  mrg 	const char * const restrict pbound,
    271      1.1  mrg 	const 'atype_name` * const restrict pwhich)
    272      1.1  mrg {
    273      1.1  mrg   eoshift1 (ret, array, h, pbound, pwhich, "\0", 1);
    274      1.1  mrg }
    275      1.1  mrg 
    276      1.1  mrg 
    277      1.1  mrg void eoshift1_'atype_kind`_char (gfc_array_char * const restrict, 
    278      1.1  mrg 	GFC_INTEGER_4,
    279      1.1  mrg 	const gfc_array_char * const restrict, 
    280      1.1  mrg 	const 'atype` * const restrict,
    281      1.1  mrg 	const char * const restrict, 
    282      1.1  mrg 	const 'atype_name` * const restrict,
    283      1.1  mrg 	GFC_INTEGER_4, GFC_INTEGER_4);
    284      1.1  mrg export_proto(eoshift1_'atype_kind`_char);
    285      1.1  mrg 
    286      1.1  mrg void
    287      1.1  mrg eoshift1_'atype_kind`_char (gfc_array_char * const restrict ret,
    288      1.1  mrg 	GFC_INTEGER_4 ret_length __attribute__((unused)),
    289      1.1  mrg 	const gfc_array_char * const restrict array, 
    290      1.1  mrg 	const 'atype` * const restrict h,
    291      1.1  mrg 	const char *  const restrict pbound, 
    292      1.1  mrg 	const 'atype_name` * const restrict pwhich,
    293      1.1  mrg 	GFC_INTEGER_4 array_length __attribute__((unused)),
    294      1.1  mrg 	GFC_INTEGER_4 bound_length __attribute__((unused)))
    295      1.1  mrg {
    296      1.1  mrg   eoshift1 (ret, array, h, pbound, pwhich, " ", 1);
    297      1.1  mrg }
    298      1.1  mrg 
    299      1.1  mrg 
    300      1.1  mrg void eoshift1_'atype_kind`_char4 (gfc_array_char * const restrict, 
    301      1.1  mrg 	GFC_INTEGER_4,
    302      1.1  mrg 	const gfc_array_char * const restrict, 
    303      1.1  mrg 	const 'atype` * const restrict,
    304      1.1  mrg 	const char * const restrict, 
    305      1.1  mrg 	const 'atype_name` * const restrict,
    306      1.1  mrg 	GFC_INTEGER_4, GFC_INTEGER_4);
    307      1.1  mrg export_proto(eoshift1_'atype_kind`_char4);
    308      1.1  mrg 
    309      1.1  mrg void
    310      1.1  mrg eoshift1_'atype_kind`_char4 (gfc_array_char * const restrict ret,
    311      1.1  mrg 	GFC_INTEGER_4 ret_length __attribute__((unused)),
    312      1.1  mrg 	const gfc_array_char * const restrict array, 
    313      1.1  mrg 	const 'atype` * const restrict h,
    314      1.1  mrg 	const char *  const restrict pbound, 
    315      1.1  mrg 	const 'atype_name` * const restrict pwhich,
    316      1.1  mrg 	GFC_INTEGER_4 array_length __attribute__((unused)),
    317      1.1  mrg 	GFC_INTEGER_4 bound_length __attribute__((unused)))
    318      1.1  mrg {
    319      1.1  mrg   static const gfc_char4_t space = (unsigned char) ''` ''`;
    320      1.1  mrg   eoshift1 (ret, array, h, pbound, pwhich,
    321      1.1  mrg 	    (const char *) &space, sizeof (gfc_char4_t));
    322      1.1  mrg }
    323      1.1  mrg 
    324      1.1  mrg #endif'
    325