xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/generated/cshift1_8_i1.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg /* Implementation of the CSHIFT intrinsic.
2*4c3eb207Smrg    Copyright (C) 2017-2020 Free Software Foundation, Inc.
3627f7eb2Smrg    Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>
4627f7eb2Smrg 
5627f7eb2Smrg This file is part of the GNU Fortran 95 runtime library (libgfortran).
6627f7eb2Smrg 
7627f7eb2Smrg Libgfortran is free software; you can redistribute it and/or
8627f7eb2Smrg modify it under the terms of the GNU General Public
9627f7eb2Smrg License as published by the Free Software Foundation; either
10627f7eb2Smrg version 3 of the License, or (at your option) any later version.
11627f7eb2Smrg 
12627f7eb2Smrg Libgfortran is distributed in the hope that it will be useful,
13627f7eb2Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14627f7eb2Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15627f7eb2Smrg GNU General Public License for more details.
16627f7eb2Smrg 
17627f7eb2Smrg Under Section 7 of GPL version 3, you are granted additional
18627f7eb2Smrg permissions described in the GCC Runtime Library Exception, version
19627f7eb2Smrg 3.1, as published by the Free Software Foundation.
20627f7eb2Smrg 
21627f7eb2Smrg You should have received a copy of the GNU General Public License and
22627f7eb2Smrg a copy of the GCC Runtime Library Exception along with this program;
23627f7eb2Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24627f7eb2Smrg <http://www.gnu.org/licenses/>.  */
25627f7eb2Smrg 
26627f7eb2Smrg #include "libgfortran.h"
27627f7eb2Smrg #include <string.h>
28627f7eb2Smrg 
29627f7eb2Smrg #if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_8)
30627f7eb2Smrg 
31627f7eb2Smrg void
cshift1_8_i1(gfc_array_i1 * const restrict ret,const gfc_array_i1 * const restrict array,const gfc_array_i8 * const restrict h,const GFC_INTEGER_8 * const restrict pwhich)32627f7eb2Smrg cshift1_8_i1 (gfc_array_i1 * const restrict ret,
33627f7eb2Smrg 		const gfc_array_i1 * const restrict array,
34627f7eb2Smrg 		const gfc_array_i8 * const restrict h,
35627f7eb2Smrg 		const GFC_INTEGER_8 * const restrict pwhich)
36627f7eb2Smrg {
37627f7eb2Smrg   /* r.* indicates the return array.  */
38627f7eb2Smrg   index_type rstride[GFC_MAX_DIMENSIONS];
39627f7eb2Smrg   index_type rstride0;
40627f7eb2Smrg   index_type roffset;
41627f7eb2Smrg   GFC_INTEGER_1 *rptr;
42627f7eb2Smrg   GFC_INTEGER_1 *dest;
43627f7eb2Smrg   /* s.* indicates the source array.  */
44627f7eb2Smrg   index_type sstride[GFC_MAX_DIMENSIONS];
45627f7eb2Smrg   index_type sstride0;
46627f7eb2Smrg   index_type soffset;
47627f7eb2Smrg   const GFC_INTEGER_1 *sptr;
48627f7eb2Smrg   const GFC_INTEGER_1 *src;
49627f7eb2Smrg   /* h.* indicates the shift array.  */
50627f7eb2Smrg   index_type hstride[GFC_MAX_DIMENSIONS];
51627f7eb2Smrg   index_type hstride0;
52627f7eb2Smrg   const GFC_INTEGER_8 *hptr;
53627f7eb2Smrg 
54627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
55627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
56627f7eb2Smrg   index_type rs_ex[GFC_MAX_DIMENSIONS];
57627f7eb2Smrg   index_type ss_ex[GFC_MAX_DIMENSIONS];
58627f7eb2Smrg   index_type hs_ex[GFC_MAX_DIMENSIONS];
59627f7eb2Smrg 
60627f7eb2Smrg   index_type dim;
61627f7eb2Smrg   index_type len;
62627f7eb2Smrg   index_type n;
63627f7eb2Smrg   int which;
64627f7eb2Smrg   GFC_INTEGER_8 sh;
65627f7eb2Smrg 
66627f7eb2Smrg   /* Bounds checking etc is already done by the caller.  */
67627f7eb2Smrg 
68627f7eb2Smrg   if (pwhich)
69627f7eb2Smrg     which = *pwhich - 1;
70627f7eb2Smrg   else
71627f7eb2Smrg     which = 0;
72627f7eb2Smrg 
73627f7eb2Smrg   extent[0] = 1;
74627f7eb2Smrg   count[0] = 0;
75627f7eb2Smrg   n = 0;
76627f7eb2Smrg 
77627f7eb2Smrg   /* Initialized for avoiding compiler warnings.  */
78627f7eb2Smrg   roffset = 1;
79627f7eb2Smrg   soffset = 1;
80627f7eb2Smrg   len = 0;
81627f7eb2Smrg 
82627f7eb2Smrg   for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
83627f7eb2Smrg     {
84627f7eb2Smrg       if (dim == which)
85627f7eb2Smrg         {
86627f7eb2Smrg           roffset = GFC_DESCRIPTOR_STRIDE(ret,dim);
87627f7eb2Smrg           if (roffset == 0)
88627f7eb2Smrg             roffset = 1;
89627f7eb2Smrg           soffset = GFC_DESCRIPTOR_STRIDE(array,dim);
90627f7eb2Smrg           if (soffset == 0)
91627f7eb2Smrg             soffset = 1;
92627f7eb2Smrg           len = GFC_DESCRIPTOR_EXTENT(array,dim);
93627f7eb2Smrg         }
94627f7eb2Smrg       else
95627f7eb2Smrg         {
96627f7eb2Smrg           count[n] = 0;
97627f7eb2Smrg           extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
98627f7eb2Smrg           rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,dim);
99627f7eb2Smrg           sstride[n] = GFC_DESCRIPTOR_STRIDE(array,dim);
100627f7eb2Smrg           hstride[n] = GFC_DESCRIPTOR_STRIDE(h,n);
101627f7eb2Smrg 	  rs_ex[n] = rstride[n] * extent[n];
102627f7eb2Smrg 	  ss_ex[n] = sstride[n] * extent[n];
103627f7eb2Smrg 	  hs_ex[n] = hstride[n] * extent[n];
104627f7eb2Smrg           n++;
105627f7eb2Smrg         }
106627f7eb2Smrg     }
107627f7eb2Smrg   if (sstride[0] == 0)
108627f7eb2Smrg     sstride[0] = 1;
109627f7eb2Smrg   if (rstride[0] == 0)
110627f7eb2Smrg     rstride[0] = 1;
111627f7eb2Smrg   if (hstride[0] == 0)
112627f7eb2Smrg     hstride[0] = 1;
113627f7eb2Smrg 
114627f7eb2Smrg   dim = GFC_DESCRIPTOR_RANK (array);
115627f7eb2Smrg   rstride0 = rstride[0];
116627f7eb2Smrg   sstride0 = sstride[0];
117627f7eb2Smrg   hstride0 = hstride[0];
118627f7eb2Smrg   rptr = ret->base_addr;
119627f7eb2Smrg   sptr = array->base_addr;
120627f7eb2Smrg   hptr = h->base_addr;
121627f7eb2Smrg 
122627f7eb2Smrg   while (rptr)
123627f7eb2Smrg     {
124627f7eb2Smrg       /* Do the shift for this dimension.  */
125627f7eb2Smrg       sh = *hptr;
126627f7eb2Smrg       /* Normal case should be -len < sh < len; try to
127627f7eb2Smrg          avoid the expensive remainder operation if possible.  */
128627f7eb2Smrg       if (sh < 0)
129627f7eb2Smrg         sh += len;
130627f7eb2Smrg       if (unlikely(sh >= len || sh < 0))
131627f7eb2Smrg 	{
132627f7eb2Smrg  	  sh = sh % len;
133627f7eb2Smrg 	  if (sh < 0)
134627f7eb2Smrg             sh += len;
135627f7eb2Smrg 	}
136627f7eb2Smrg       src = &sptr[sh * soffset];
137627f7eb2Smrg       dest = rptr;
138627f7eb2Smrg       if (soffset == 1 && roffset == 1)
139627f7eb2Smrg 	{
140627f7eb2Smrg 	  size_t len1 = sh * sizeof (GFC_INTEGER_1);
141627f7eb2Smrg 	  size_t len2 = (len - sh) * sizeof (GFC_INTEGER_1);
142627f7eb2Smrg 	  memcpy (rptr, sptr + sh, len2);
143627f7eb2Smrg 	  memcpy (rptr + (len - sh), sptr, len1);
144627f7eb2Smrg 	}
145627f7eb2Smrg       else
146627f7eb2Smrg         {
147627f7eb2Smrg 	  for (n = 0; n < len - sh; n++)
148627f7eb2Smrg 	    {
149627f7eb2Smrg 	      *dest = *src;
150627f7eb2Smrg 	      dest += roffset;
151627f7eb2Smrg 	      src += soffset;
152627f7eb2Smrg 	    }
153627f7eb2Smrg 	  for (src = sptr, n = 0; n < sh; n++)
154627f7eb2Smrg 	    {
155627f7eb2Smrg 	      *dest = *src;
156627f7eb2Smrg 	      dest += roffset;
157627f7eb2Smrg 	      src += soffset;
158627f7eb2Smrg 	    }
159627f7eb2Smrg 	}
160627f7eb2Smrg 
161627f7eb2Smrg       /* Advance to the next section.  */
162627f7eb2Smrg       rptr += rstride0;
163627f7eb2Smrg       sptr += sstride0;
164627f7eb2Smrg       hptr += hstride0;
165627f7eb2Smrg       count[0]++;
166627f7eb2Smrg       n = 0;
167627f7eb2Smrg       while (count[n] == extent[n])
168627f7eb2Smrg         {
169627f7eb2Smrg           /* When we get to the end of a dimension, reset it and increment
170627f7eb2Smrg              the next dimension.  */
171627f7eb2Smrg           count[n] = 0;
172627f7eb2Smrg           rptr -= rs_ex[n];
173627f7eb2Smrg           sptr -= ss_ex[n];
174627f7eb2Smrg 	  hptr -= hs_ex[n];
175627f7eb2Smrg           n++;
176627f7eb2Smrg           if (n >= dim - 1)
177627f7eb2Smrg             {
178627f7eb2Smrg               /* Break out of the loop.  */
179627f7eb2Smrg               rptr = NULL;
180627f7eb2Smrg               break;
181627f7eb2Smrg             }
182627f7eb2Smrg           else
183627f7eb2Smrg             {
184627f7eb2Smrg               count[n]++;
185627f7eb2Smrg               rptr += rstride[n];
186627f7eb2Smrg               sptr += sstride[n];
187627f7eb2Smrg 	      hptr += hstride[n];
188627f7eb2Smrg             }
189627f7eb2Smrg         }
190627f7eb2Smrg     }
191627f7eb2Smrg }
192627f7eb2Smrg 
193627f7eb2Smrg #endif
194