Home | History | Annotate | Line # | Download | only in m4
      1      1.1  mrg `/* Helper function for cshift functions.
      2  1.1.1.4  mrg    Copyright (C) 2008-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 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_'rtype_name`)
     32      1.1  mrg 
     33      1.1  mrg void
     34      1.1  mrg cshift0_'rtype_code` ('rtype` *ret, const 'rtype` *array, ptrdiff_t shift,
     35      1.1  mrg 		     int which)
     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 roffset;
     41      1.1  mrg   'rtype_name` *rptr;
     42      1.1  mrg 
     43      1.1  mrg   /* s.* indicates the source array.  */
     44      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     45      1.1  mrg   index_type sstride0;
     46      1.1  mrg   index_type soffset;
     47      1.1  mrg   const 'rtype_name` *sptr;
     48      1.1  mrg 
     49      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     50      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     51      1.1  mrg   index_type dim;
     52      1.1  mrg   index_type len;
     53      1.1  mrg   index_type n;
     54      1.1  mrg 
     55      1.1  mrg   bool do_blocked;
     56      1.1  mrg   index_type r_ex, a_ex;
     57      1.1  mrg 
     58      1.1  mrg   which = which - 1;
     59      1.1  mrg   sstride[0] = 0;
     60      1.1  mrg   rstride[0] = 0;
     61      1.1  mrg 
     62      1.1  mrg   extent[0] = 1;
     63      1.1  mrg   count[0] = 0;
     64      1.1  mrg   n = 0;
     65      1.1  mrg   /* Initialized for avoiding compiler warnings.  */
     66      1.1  mrg   roffset = 1;
     67      1.1  mrg   soffset = 1;
     68      1.1  mrg   len = 0;
     69      1.1  mrg 
     70      1.1  mrg   r_ex = 1;
     71      1.1  mrg   a_ex = 1;
     72      1.1  mrg 
     73      1.1  mrg   if (which > 0)
     74      1.1  mrg     {
     75      1.1  mrg       /* Test if both ret and array are contiguous.  */
     76      1.1  mrg       do_blocked = true;
     77      1.1  mrg       dim = GFC_DESCRIPTOR_RANK (array);
     78      1.1  mrg       for (n = 0; n < dim; n ++)
     79      1.1  mrg 	{
     80      1.1  mrg 	  index_type rs, as;
     81      1.1  mrg 	  rs = GFC_DESCRIPTOR_STRIDE (ret, n);
     82      1.1  mrg 	  if (rs != r_ex)
     83      1.1  mrg 	    {
     84      1.1  mrg 	      do_blocked = false;
     85      1.1  mrg 	      break;
     86      1.1  mrg 	    }
     87      1.1  mrg 	  as = GFC_DESCRIPTOR_STRIDE (array, n);
     88      1.1  mrg 	  if (as != a_ex)
     89      1.1  mrg 	    {
     90      1.1  mrg 	      do_blocked = false;
     91      1.1  mrg 	      break;
     92      1.1  mrg 	    }
     93      1.1  mrg 	  r_ex *= GFC_DESCRIPTOR_EXTENT (ret, n);
     94      1.1  mrg 	  a_ex *= GFC_DESCRIPTOR_EXTENT (array, n);
     95      1.1  mrg 	}
     96      1.1  mrg     }
     97      1.1  mrg   else
     98      1.1  mrg     do_blocked = false;
     99      1.1  mrg 
    100      1.1  mrg   n = 0;
    101      1.1  mrg 
    102      1.1  mrg   if (do_blocked)
    103      1.1  mrg     {
    104      1.1  mrg       /* For contiguous arrays, use the relationship that
    105      1.1  mrg 
    106      1.1  mrg          dimension(n1,n2,n3) :: a, b
    107      1.1  mrg 	 b = cshift(a,sh,3)
    108      1.1  mrg 
    109      1.1  mrg          can be dealt with as if
    110      1.1  mrg 
    111      1.1  mrg 	 dimension(n1*n2*n3) :: an, bn
    112      1.1  mrg 	 bn = cshift(a,sh*n1*n2,1)
    113      1.1  mrg 
    114      1.1  mrg 	 we can used a more blocked algorithm for dim>1.  */
    115      1.1  mrg       sstride[0] = 1;
    116      1.1  mrg       rstride[0] = 1;
    117      1.1  mrg       roffset = 1;
    118      1.1  mrg       soffset = 1;
    119      1.1  mrg       len = GFC_DESCRIPTOR_STRIDE(array, which)
    120      1.1  mrg 	* GFC_DESCRIPTOR_EXTENT(array, which);      
    121      1.1  mrg       shift *= GFC_DESCRIPTOR_STRIDE(array, which);
    122      1.1  mrg       for (dim = which + 1; dim < GFC_DESCRIPTOR_RANK (array); dim++)
    123      1.1  mrg 	{
    124      1.1  mrg 	  count[n] = 0;
    125      1.1  mrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
    126      1.1  mrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,dim);
    127      1.1  mrg 	  sstride[n] = GFC_DESCRIPTOR_STRIDE(array,dim);
    128      1.1  mrg 	  n++;
    129      1.1  mrg 	}
    130      1.1  mrg       dim = GFC_DESCRIPTOR_RANK (array) - which;
    131      1.1  mrg     }
    132      1.1  mrg   else
    133      1.1  mrg     {
    134      1.1  mrg       for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
    135      1.1  mrg 	{
    136      1.1  mrg 	  if (dim == which)
    137      1.1  mrg 	    {
    138      1.1  mrg 	      roffset = GFC_DESCRIPTOR_STRIDE(ret,dim);
    139      1.1  mrg 	      if (roffset == 0)
    140      1.1  mrg 		roffset = 1;
    141      1.1  mrg 	      soffset = GFC_DESCRIPTOR_STRIDE(array,dim);
    142      1.1  mrg 	      if (soffset == 0)
    143      1.1  mrg 		soffset = 1;
    144      1.1  mrg 	      len = GFC_DESCRIPTOR_EXTENT(array,dim);
    145      1.1  mrg 	    }
    146      1.1  mrg 	  else
    147      1.1  mrg 	    {
    148      1.1  mrg 	      count[n] = 0;
    149      1.1  mrg 	      extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
    150      1.1  mrg 	      rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,dim);
    151      1.1  mrg 	      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,dim);
    152      1.1  mrg 	      n++;
    153      1.1  mrg 	    }
    154      1.1  mrg 	}
    155      1.1  mrg       if (sstride[0] == 0)
    156      1.1  mrg 	sstride[0] = 1;
    157      1.1  mrg       if (rstride[0] == 0)
    158      1.1  mrg 	rstride[0] = 1;
    159      1.1  mrg 
    160      1.1  mrg       dim = GFC_DESCRIPTOR_RANK (array);
    161      1.1  mrg     }
    162      1.1  mrg 
    163      1.1  mrg   rstride0 = rstride[0];
    164      1.1  mrg   sstride0 = sstride[0];
    165      1.1  mrg   rptr = ret->base_addr;
    166      1.1  mrg   sptr = array->base_addr;
    167      1.1  mrg 
    168      1.1  mrg   /* Avoid the costly modulo for trivially in-bound shifts.  */
    169      1.1  mrg   if (shift < 0 || shift >= len)
    170      1.1  mrg     {
    171      1.1  mrg       shift = len == 0 ? 0 : shift % (ptrdiff_t)len;
    172      1.1  mrg       if (shift < 0)
    173      1.1  mrg 	shift += len;
    174      1.1  mrg     }
    175      1.1  mrg 
    176      1.1  mrg   while (rptr)
    177      1.1  mrg     {
    178      1.1  mrg       /* Do the shift for this dimension.  */
    179      1.1  mrg 
    180      1.1  mrg       /* If elements are contiguous, perform the operation
    181      1.1  mrg 	 in two block moves.  */
    182      1.1  mrg       if (soffset == 1 && roffset == 1)
    183      1.1  mrg 	{
    184      1.1  mrg 	  size_t len1 = shift * sizeof ('rtype_name`);
    185      1.1  mrg 	  size_t len2 = (len - shift) * sizeof ('rtype_name`);
    186      1.1  mrg 	  memcpy (rptr, sptr + shift, len2);
    187      1.1  mrg 	  memcpy (rptr + (len - shift), sptr, len1);
    188      1.1  mrg 	}
    189      1.1  mrg       else
    190      1.1  mrg 	{
    191      1.1  mrg 	  /* Otherwise, we will have to perform the copy one element at
    192      1.1  mrg 	     a time.  */
    193      1.1  mrg 	  'rtype_name` *dest = rptr;
    194      1.1  mrg 	  const 'rtype_name` *src = &sptr[shift * soffset];
    195      1.1  mrg 
    196      1.1  mrg 	  for (n = 0; n < len - shift; n++)
    197      1.1  mrg 	    {
    198      1.1  mrg 	      *dest = *src;
    199      1.1  mrg 	      dest += roffset;
    200      1.1  mrg 	      src += soffset;
    201      1.1  mrg 	    }
    202      1.1  mrg 	  for (src = sptr, n = 0; n < shift; n++)
    203      1.1  mrg 	    {
    204      1.1  mrg 	      *dest = *src;
    205      1.1  mrg 	      dest += roffset;
    206      1.1  mrg 	      src += soffset;
    207      1.1  mrg 	    }
    208      1.1  mrg 	}
    209      1.1  mrg 
    210      1.1  mrg       /* Advance to the next section.  */
    211      1.1  mrg       rptr += rstride0;
    212      1.1  mrg       sptr += sstride0;
    213      1.1  mrg       count[0]++;
    214      1.1  mrg       n = 0;
    215      1.1  mrg       while (count[n] == extent[n])
    216      1.1  mrg         {
    217      1.1  mrg           /* When we get to the end of a dimension, reset it and increment
    218      1.1  mrg              the next dimension.  */
    219      1.1  mrg           count[n] = 0;
    220      1.1  mrg           /* We could precalculate these products, but this is a less
    221      1.1  mrg              frequently used path so probably not worth it.  */
    222      1.1  mrg           rptr -= rstride[n] * extent[n];
    223      1.1  mrg           sptr -= sstride[n] * extent[n];
    224      1.1  mrg           n++;
    225      1.1  mrg           if (n >= dim - 1)
    226      1.1  mrg             {
    227      1.1  mrg               /* Break out of the loop.  */
    228      1.1  mrg               rptr = NULL;
    229      1.1  mrg               break;
    230      1.1  mrg             }
    231      1.1  mrg           else
    232      1.1  mrg             {
    233      1.1  mrg               count[n]++;
    234      1.1  mrg               rptr += rstride[n];
    235      1.1  mrg               sptr += sstride[n];
    236      1.1  mrg             }
    237      1.1  mrg         }
    238      1.1  mrg     }
    239      1.1  mrg 
    240      1.1  mrg   return;
    241      1.1  mrg }
    242      1.1  mrg 
    243      1.1  mrg #endif'
    244