Home | History | Annotate | Line # | Download | only in m4
      1      1.1  mrg `/* Implementation of the CSHIFT intrinsic.
      2  1.1.1.4  mrg    Copyright (C) 2017-2024 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Thomas Koenig <tkoenig (a] gcc.gnu.org>
      4      1.1  mrg 
      5      1.1  mrg This file is part of the GNU Fortran 95 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 include(iparm.m4)dnl
     29      1.1  mrg 
     30      1.1  mrg `#if defined (HAVE_'atype_name`) && defined (HAVE_'rtype_name`)
     31      1.1  mrg 
     32      1.1  mrg void
     33      1.1  mrg cshift1'rtype_qual`_'atype_code` ('atype` * const restrict ret,
     34      1.1  mrg 		const 'atype` * const restrict array,
     35      1.1  mrg 		const 'rtype` * const restrict h,
     36      1.1  mrg 		const 'rtype_name` * 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   'atype_name` *rptr;
     43      1.1  mrg   'atype_name` *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 'atype_name` *sptr;
     49      1.1  mrg   const 'atype_name` *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 'rtype_name` *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 rs_ex[GFC_MAX_DIMENSIONS];
     58      1.1  mrg   index_type ss_ex[GFC_MAX_DIMENSIONS];
     59      1.1  mrg   index_type hs_ex[GFC_MAX_DIMENSIONS];
     60      1.1  mrg 
     61      1.1  mrg   index_type dim;
     62      1.1  mrg   index_type len;
     63      1.1  mrg   index_type n;
     64      1.1  mrg   int which;
     65      1.1  mrg   'rtype_name` sh;
     66      1.1  mrg 
     67      1.1  mrg   /* Bounds checking etc is already done by the caller.  */
     68      1.1  mrg 
     69      1.1  mrg   if (pwhich)
     70      1.1  mrg     which = *pwhich - 1;
     71      1.1  mrg   else
     72      1.1  mrg     which = 0;
     73      1.1  mrg 
     74      1.1  mrg   extent[0] = 1;
     75      1.1  mrg   count[0] = 0;
     76      1.1  mrg   n = 0;
     77      1.1  mrg 
     78      1.1  mrg   /* Initialized for avoiding compiler warnings.  */
     79      1.1  mrg   roffset = 1;
     80      1.1  mrg   soffset = 1;
     81      1.1  mrg   len = 0;
     82      1.1  mrg 
     83      1.1  mrg   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
     84      1.1  mrg     {
     85      1.1  mrg       if (dim == which)
     86      1.1  mrg         {
     87      1.1  mrg           roffset = GFC_DESCRIPTOR_STRIDE(ret,dim);
     88      1.1  mrg           if (roffset == 0)
     89      1.1  mrg             roffset = 1;
     90      1.1  mrg           soffset = GFC_DESCRIPTOR_STRIDE(array,dim);
     91      1.1  mrg           if (soffset == 0)
     92      1.1  mrg             soffset = 1;
     93      1.1  mrg           len = GFC_DESCRIPTOR_EXTENT(array,dim);
     94      1.1  mrg         }
     95      1.1  mrg       else
     96      1.1  mrg         {
     97      1.1  mrg           count[n] = 0;
     98      1.1  mrg           extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
     99      1.1  mrg           rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,dim);
    100      1.1  mrg           sstride[n] = GFC_DESCRIPTOR_STRIDE(array,dim);
    101      1.1  mrg           hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
    102      1.1  mrg 	  rs_ex[n] = rstride[n] * extent[n];
    103      1.1  mrg 	  ss_ex[n] = sstride[n] * extent[n];
    104      1.1  mrg 	  hs_ex[n] = hstride[n] * extent[n];
    105      1.1  mrg           n++;
    106      1.1  mrg         }
    107      1.1  mrg     }
    108      1.1  mrg   if (sstride[0] == 0)
    109      1.1  mrg     sstride[0] = 1;
    110      1.1  mrg   if (rstride[0] == 0)
    111      1.1  mrg     rstride[0] = 1;
    112      1.1  mrg   if (hstride[0] == 0)
    113      1.1  mrg     hstride[0] = 1;
    114      1.1  mrg 
    115      1.1  mrg   dim = GFC_DESCRIPTOR_RANK (array);
    116      1.1  mrg   rstride0 = rstride[0];
    117      1.1  mrg   sstride0 = sstride[0];
    118      1.1  mrg   hstride0 = hstride[0];
    119      1.1  mrg   rptr = ret->base_addr;
    120      1.1  mrg   sptr = array->base_addr;
    121      1.1  mrg   hptr = h->base_addr;
    122      1.1  mrg 
    123      1.1  mrg   while (rptr)
    124      1.1  mrg     {
    125      1.1  mrg       /* Do the shift for this dimension.  */
    126      1.1  mrg       sh = *hptr;
    127      1.1  mrg       /* Normal case should be -len < sh < len; try to
    128      1.1  mrg          avoid the expensive remainder operation if possible.  */
    129      1.1  mrg       if (sh < 0)
    130      1.1  mrg         sh += len;
    131      1.1  mrg       if (unlikely(sh >= len || sh < 0))
    132      1.1  mrg 	{
    133      1.1  mrg  	  sh = sh % len;
    134      1.1  mrg 	  if (sh < 0)
    135      1.1  mrg             sh += len;
    136      1.1  mrg 	}
    137      1.1  mrg       src = &sptr[sh * soffset];
    138      1.1  mrg       dest = rptr;
    139      1.1  mrg       if (soffset == 1 && roffset == 1)
    140      1.1  mrg 	{
    141      1.1  mrg 	  size_t len1 = sh * sizeof ('atype_name`);
    142      1.1  mrg 	  size_t len2 = (len - sh) * sizeof ('atype_name`);
    143      1.1  mrg 	  memcpy (rptr, sptr + sh, len2);
    144      1.1  mrg 	  memcpy (rptr + (len - sh), sptr, len1);
    145      1.1  mrg 	}
    146      1.1  mrg       else
    147      1.1  mrg         {
    148      1.1  mrg 	  for (n = 0; n < len - sh; n++)
    149      1.1  mrg 	    {
    150      1.1  mrg 	      *dest = *src;
    151      1.1  mrg 	      dest += roffset;
    152      1.1  mrg 	      src += soffset;
    153      1.1  mrg 	    }
    154      1.1  mrg 	  for (src = sptr, n = 0; n < sh; n++)
    155      1.1  mrg 	    {
    156      1.1  mrg 	      *dest = *src;
    157      1.1  mrg 	      dest += roffset;
    158      1.1  mrg 	      src += soffset;
    159      1.1  mrg 	    }
    160      1.1  mrg 	}
    161      1.1  mrg 
    162      1.1  mrg       /* Advance to the next section.  */
    163      1.1  mrg       rptr += rstride0;
    164      1.1  mrg       sptr += sstride0;
    165      1.1  mrg       hptr += hstride0;
    166      1.1  mrg       count[0]++;
    167      1.1  mrg       n = 0;
    168      1.1  mrg       while (count[n] == extent[n])
    169      1.1  mrg         {
    170      1.1  mrg           /* When we get to the end of a dimension, reset it and increment
    171      1.1  mrg              the next dimension.  */
    172      1.1  mrg           count[n] = 0;
    173      1.1  mrg           rptr -= rs_ex[n];
    174      1.1  mrg           sptr -= ss_ex[n];
    175      1.1  mrg 	  hptr -= hs_ex[n];
    176      1.1  mrg           n++;
    177      1.1  mrg           if (n >= dim - 1)
    178      1.1  mrg             {
    179      1.1  mrg               /* Break out of the loop.  */
    180      1.1  mrg               rptr = NULL;
    181      1.1  mrg               break;
    182      1.1  mrg             }
    183      1.1  mrg           else
    184      1.1  mrg             {
    185      1.1  mrg               count[n]++;
    186      1.1  mrg               rptr += rstride[n];
    187      1.1  mrg               sptr += sstride[n];
    188      1.1  mrg 	      hptr += hstride[n];
    189      1.1  mrg             }
    190      1.1  mrg         }
    191      1.1  mrg     }
    192      1.1  mrg }
    193      1.1  mrg 
    194      1.1  mrg #endif'
    195