xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/generated/unpack_c17.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1*b1e83836Smrg /* Specific implementation of the UNPACK intrinsic
2*b1e83836Smrg    Copyright (C) 2008-2022 Free Software Foundation, Inc.
3*b1e83836Smrg    Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>, based on
4*b1e83836Smrg    unpack_generic.c by Paul Brook <paul@nowt.org>.
5*b1e83836Smrg 
6*b1e83836Smrg This file is part of the GNU Fortran runtime library (libgfortran).
7*b1e83836Smrg 
8*b1e83836Smrg Libgfortran is free software; you can redistribute it and/or
9*b1e83836Smrg modify it under the terms of the GNU General Public
10*b1e83836Smrg License as published by the Free Software Foundation; either
11*b1e83836Smrg version 3 of the License, or (at your option) any later version.
12*b1e83836Smrg 
13*b1e83836Smrg Ligbfortran is distributed in the hope that it will be useful,
14*b1e83836Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
15*b1e83836Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*b1e83836Smrg GNU General Public License for more details.
17*b1e83836Smrg 
18*b1e83836Smrg Under Section 7 of GPL version 3, you are granted additional
19*b1e83836Smrg permissions described in the GCC Runtime Library Exception, version
20*b1e83836Smrg 3.1, as published by the Free Software Foundation.
21*b1e83836Smrg 
22*b1e83836Smrg You should have received a copy of the GNU General Public License and
23*b1e83836Smrg a copy of the GCC Runtime Library Exception along with this program;
24*b1e83836Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25*b1e83836Smrg <http://www.gnu.org/licenses/>.  */
26*b1e83836Smrg 
27*b1e83836Smrg #include "libgfortran.h"
28*b1e83836Smrg #include <string.h>
29*b1e83836Smrg 
30*b1e83836Smrg 
31*b1e83836Smrg #if defined (HAVE_GFC_COMPLEX_17)
32*b1e83836Smrg 
33*b1e83836Smrg void
unpack0_c17(gfc_array_c17 * ret,const gfc_array_c17 * vector,const gfc_array_l1 * mask,const GFC_COMPLEX_17 * fptr)34*b1e83836Smrg unpack0_c17 (gfc_array_c17 *ret, const gfc_array_c17 *vector,
35*b1e83836Smrg 		 const gfc_array_l1 *mask, const GFC_COMPLEX_17 *fptr)
36*b1e83836Smrg {
37*b1e83836Smrg   /* r.* indicates the return array.  */
38*b1e83836Smrg   index_type rstride[GFC_MAX_DIMENSIONS];
39*b1e83836Smrg   index_type rstride0;
40*b1e83836Smrg   index_type rs;
41*b1e83836Smrg   GFC_COMPLEX_17 * restrict rptr;
42*b1e83836Smrg   /* v.* indicates the vector array.  */
43*b1e83836Smrg   index_type vstride0;
44*b1e83836Smrg   GFC_COMPLEX_17 *vptr;
45*b1e83836Smrg   /* Value for field, this is constant.  */
46*b1e83836Smrg   const GFC_COMPLEX_17 fval = *fptr;
47*b1e83836Smrg   /* m.* indicates the mask array.  */
48*b1e83836Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
49*b1e83836Smrg   index_type mstride0;
50*b1e83836Smrg   const GFC_LOGICAL_1 *mptr;
51*b1e83836Smrg 
52*b1e83836Smrg   index_type count[GFC_MAX_DIMENSIONS];
53*b1e83836Smrg   index_type extent[GFC_MAX_DIMENSIONS];
54*b1e83836Smrg   index_type n;
55*b1e83836Smrg   index_type dim;
56*b1e83836Smrg 
57*b1e83836Smrg   int empty;
58*b1e83836Smrg   int mask_kind;
59*b1e83836Smrg 
60*b1e83836Smrg   empty = 0;
61*b1e83836Smrg 
62*b1e83836Smrg   mptr = mask->base_addr;
63*b1e83836Smrg 
64*b1e83836Smrg   /* Use the same loop for all logical types, by using GFC_LOGICAL_1
65*b1e83836Smrg      and using shifting to address size and endian issues.  */
66*b1e83836Smrg 
67*b1e83836Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
68*b1e83836Smrg 
69*b1e83836Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
70*b1e83836Smrg #ifdef HAVE_GFC_LOGICAL_16
71*b1e83836Smrg       || mask_kind == 16
72*b1e83836Smrg #endif
73*b1e83836Smrg       )
74*b1e83836Smrg     {
75*b1e83836Smrg       /*  Do not convert a NULL pointer as we use test for NULL below.  */
76*b1e83836Smrg       if (mptr)
77*b1e83836Smrg 	mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind);
78*b1e83836Smrg     }
79*b1e83836Smrg   else
80*b1e83836Smrg     runtime_error ("Funny sized logical array");
81*b1e83836Smrg 
82*b1e83836Smrg   /* Initialize to avoid -Wmaybe-uninitialized complaints.  */
83*b1e83836Smrg   rstride[0] = 1;
84*b1e83836Smrg   if (ret->base_addr == NULL)
85*b1e83836Smrg     {
86*b1e83836Smrg       /* The front end has signalled that we need to populate the
87*b1e83836Smrg 	 return array descriptor.  */
88*b1e83836Smrg       dim = GFC_DESCRIPTOR_RANK (mask);
89*b1e83836Smrg       rs = 1;
90*b1e83836Smrg       for (n = 0; n < dim; n++)
91*b1e83836Smrg 	{
92*b1e83836Smrg 	  count[n] = 0;
93*b1e83836Smrg 	  GFC_DIMENSION_SET(ret->dim[n], 0,
94*b1e83836Smrg 			    GFC_DESCRIPTOR_EXTENT(mask,n) - 1, rs);
95*b1e83836Smrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
96*b1e83836Smrg 	  empty = empty || extent[n] <= 0;
97*b1e83836Smrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
98*b1e83836Smrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
99*b1e83836Smrg 	  rs *= extent[n];
100*b1e83836Smrg 	}
101*b1e83836Smrg       ret->offset = 0;
102*b1e83836Smrg       ret->base_addr = xmallocarray (rs, sizeof (GFC_COMPLEX_17));
103*b1e83836Smrg     }
104*b1e83836Smrg   else
105*b1e83836Smrg     {
106*b1e83836Smrg       dim = GFC_DESCRIPTOR_RANK (ret);
107*b1e83836Smrg       for (n = 0; n < dim; n++)
108*b1e83836Smrg 	{
109*b1e83836Smrg 	  count[n] = 0;
110*b1e83836Smrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
111*b1e83836Smrg 	  empty = empty || extent[n] <= 0;
112*b1e83836Smrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
113*b1e83836Smrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
114*b1e83836Smrg 	}
115*b1e83836Smrg       if (rstride[0] == 0)
116*b1e83836Smrg 	rstride[0] = 1;
117*b1e83836Smrg     }
118*b1e83836Smrg 
119*b1e83836Smrg   if (empty)
120*b1e83836Smrg     return;
121*b1e83836Smrg 
122*b1e83836Smrg   if (mstride[0] == 0)
123*b1e83836Smrg     mstride[0] = 1;
124*b1e83836Smrg 
125*b1e83836Smrg   vstride0 = GFC_DESCRIPTOR_STRIDE(vector,0);
126*b1e83836Smrg   if (vstride0 == 0)
127*b1e83836Smrg     vstride0 = 1;
128*b1e83836Smrg   rstride0 = rstride[0];
129*b1e83836Smrg   mstride0 = mstride[0];
130*b1e83836Smrg   rptr = ret->base_addr;
131*b1e83836Smrg   vptr = vector->base_addr;
132*b1e83836Smrg 
133*b1e83836Smrg   while (rptr)
134*b1e83836Smrg     {
135*b1e83836Smrg       if (*mptr)
136*b1e83836Smrg         {
137*b1e83836Smrg 	  /* From vector.  */
138*b1e83836Smrg 	  *rptr = *vptr;
139*b1e83836Smrg 	  vptr += vstride0;
140*b1e83836Smrg         }
141*b1e83836Smrg       else
142*b1e83836Smrg         {
143*b1e83836Smrg 	  /* From field.  */
144*b1e83836Smrg 	  *rptr = fval;
145*b1e83836Smrg         }
146*b1e83836Smrg       /* Advance to the next element.  */
147*b1e83836Smrg       rptr += rstride0;
148*b1e83836Smrg       mptr += mstride0;
149*b1e83836Smrg       count[0]++;
150*b1e83836Smrg       n = 0;
151*b1e83836Smrg       while (count[n] == extent[n])
152*b1e83836Smrg         {
153*b1e83836Smrg           /* When we get to the end of a dimension, reset it and increment
154*b1e83836Smrg              the next dimension.  */
155*b1e83836Smrg           count[n] = 0;
156*b1e83836Smrg           /* We could precalculate these products, but this is a less
157*b1e83836Smrg              frequently used path so probably not worth it.  */
158*b1e83836Smrg           rptr -= rstride[n] * extent[n];
159*b1e83836Smrg           mptr -= mstride[n] * extent[n];
160*b1e83836Smrg           n++;
161*b1e83836Smrg           if (n >= dim)
162*b1e83836Smrg             {
163*b1e83836Smrg               /* Break out of the loop.  */
164*b1e83836Smrg               rptr = NULL;
165*b1e83836Smrg               break;
166*b1e83836Smrg             }
167*b1e83836Smrg           else
168*b1e83836Smrg             {
169*b1e83836Smrg               count[n]++;
170*b1e83836Smrg               rptr += rstride[n];
171*b1e83836Smrg               mptr += mstride[n];
172*b1e83836Smrg             }
173*b1e83836Smrg         }
174*b1e83836Smrg     }
175*b1e83836Smrg }
176*b1e83836Smrg 
177*b1e83836Smrg void
unpack1_c17(gfc_array_c17 * ret,const gfc_array_c17 * vector,const gfc_array_l1 * mask,const gfc_array_c17 * field)178*b1e83836Smrg unpack1_c17 (gfc_array_c17 *ret, const gfc_array_c17 *vector,
179*b1e83836Smrg 		 const gfc_array_l1 *mask, const gfc_array_c17 *field)
180*b1e83836Smrg {
181*b1e83836Smrg   /* r.* indicates the return array.  */
182*b1e83836Smrg   index_type rstride[GFC_MAX_DIMENSIONS];
183*b1e83836Smrg   index_type rstride0;
184*b1e83836Smrg   index_type rs;
185*b1e83836Smrg   GFC_COMPLEX_17 * restrict rptr;
186*b1e83836Smrg   /* v.* indicates the vector array.  */
187*b1e83836Smrg   index_type vstride0;
188*b1e83836Smrg   GFC_COMPLEX_17 *vptr;
189*b1e83836Smrg   /* f.* indicates the field array.  */
190*b1e83836Smrg   index_type fstride[GFC_MAX_DIMENSIONS];
191*b1e83836Smrg   index_type fstride0;
192*b1e83836Smrg   const GFC_COMPLEX_17 *fptr;
193*b1e83836Smrg   /* m.* indicates the mask array.  */
194*b1e83836Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
195*b1e83836Smrg   index_type mstride0;
196*b1e83836Smrg   const GFC_LOGICAL_1 *mptr;
197*b1e83836Smrg 
198*b1e83836Smrg   index_type count[GFC_MAX_DIMENSIONS];
199*b1e83836Smrg   index_type extent[GFC_MAX_DIMENSIONS];
200*b1e83836Smrg   index_type n;
201*b1e83836Smrg   index_type dim;
202*b1e83836Smrg 
203*b1e83836Smrg   int empty;
204*b1e83836Smrg   int mask_kind;
205*b1e83836Smrg 
206*b1e83836Smrg   empty = 0;
207*b1e83836Smrg 
208*b1e83836Smrg   mptr = mask->base_addr;
209*b1e83836Smrg 
210*b1e83836Smrg   /* Use the same loop for all logical types, by using GFC_LOGICAL_1
211*b1e83836Smrg      and using shifting to address size and endian issues.  */
212*b1e83836Smrg 
213*b1e83836Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
214*b1e83836Smrg 
215*b1e83836Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
216*b1e83836Smrg #ifdef HAVE_GFC_LOGICAL_16
217*b1e83836Smrg       || mask_kind == 16
218*b1e83836Smrg #endif
219*b1e83836Smrg       )
220*b1e83836Smrg     {
221*b1e83836Smrg       /*  Do not convert a NULL pointer as we use test for NULL below.  */
222*b1e83836Smrg       if (mptr)
223*b1e83836Smrg 	mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind);
224*b1e83836Smrg     }
225*b1e83836Smrg   else
226*b1e83836Smrg     runtime_error ("Funny sized logical array");
227*b1e83836Smrg 
228*b1e83836Smrg   /* Initialize to avoid -Wmaybe-uninitialized complaints.  */
229*b1e83836Smrg   rstride[0] = 1;
230*b1e83836Smrg   if (ret->base_addr == NULL)
231*b1e83836Smrg     {
232*b1e83836Smrg       /* The front end has signalled that we need to populate the
233*b1e83836Smrg 	 return array descriptor.  */
234*b1e83836Smrg       dim = GFC_DESCRIPTOR_RANK (mask);
235*b1e83836Smrg       rs = 1;
236*b1e83836Smrg       for (n = 0; n < dim; n++)
237*b1e83836Smrg 	{
238*b1e83836Smrg 	  count[n] = 0;
239*b1e83836Smrg 	  GFC_DIMENSION_SET(ret->dim[n], 0,
240*b1e83836Smrg 			    GFC_DESCRIPTOR_EXTENT(mask,n) - 1, rs);
241*b1e83836Smrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
242*b1e83836Smrg 	  empty = empty || extent[n] <= 0;
243*b1e83836Smrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
244*b1e83836Smrg 	  fstride[n] = GFC_DESCRIPTOR_STRIDE(field,n);
245*b1e83836Smrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
246*b1e83836Smrg 	  rs *= extent[n];
247*b1e83836Smrg 	}
248*b1e83836Smrg       ret->offset = 0;
249*b1e83836Smrg       ret->base_addr = xmallocarray (rs, sizeof (GFC_COMPLEX_17));
250*b1e83836Smrg     }
251*b1e83836Smrg   else
252*b1e83836Smrg     {
253*b1e83836Smrg       dim = GFC_DESCRIPTOR_RANK (ret);
254*b1e83836Smrg       for (n = 0; n < dim; n++)
255*b1e83836Smrg 	{
256*b1e83836Smrg 	  count[n] = 0;
257*b1e83836Smrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
258*b1e83836Smrg 	  empty = empty || extent[n] <= 0;
259*b1e83836Smrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
260*b1e83836Smrg 	  fstride[n] = GFC_DESCRIPTOR_STRIDE(field,n);
261*b1e83836Smrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
262*b1e83836Smrg 	}
263*b1e83836Smrg       if (rstride[0] == 0)
264*b1e83836Smrg 	rstride[0] = 1;
265*b1e83836Smrg     }
266*b1e83836Smrg 
267*b1e83836Smrg   if (empty)
268*b1e83836Smrg     return;
269*b1e83836Smrg 
270*b1e83836Smrg   if (fstride[0] == 0)
271*b1e83836Smrg     fstride[0] = 1;
272*b1e83836Smrg   if (mstride[0] == 0)
273*b1e83836Smrg     mstride[0] = 1;
274*b1e83836Smrg 
275*b1e83836Smrg   vstride0 = GFC_DESCRIPTOR_STRIDE(vector,0);
276*b1e83836Smrg   if (vstride0 == 0)
277*b1e83836Smrg     vstride0 = 1;
278*b1e83836Smrg   rstride0 = rstride[0];
279*b1e83836Smrg   fstride0 = fstride[0];
280*b1e83836Smrg   mstride0 = mstride[0];
281*b1e83836Smrg   rptr = ret->base_addr;
282*b1e83836Smrg   fptr = field->base_addr;
283*b1e83836Smrg   vptr = vector->base_addr;
284*b1e83836Smrg 
285*b1e83836Smrg   while (rptr)
286*b1e83836Smrg     {
287*b1e83836Smrg       if (*mptr)
288*b1e83836Smrg         {
289*b1e83836Smrg           /* From vector.  */
290*b1e83836Smrg 	  *rptr = *vptr;
291*b1e83836Smrg           vptr += vstride0;
292*b1e83836Smrg         }
293*b1e83836Smrg       else
294*b1e83836Smrg         {
295*b1e83836Smrg           /* From field.  */
296*b1e83836Smrg 	  *rptr = *fptr;
297*b1e83836Smrg         }
298*b1e83836Smrg       /* Advance to the next element.  */
299*b1e83836Smrg       rptr += rstride0;
300*b1e83836Smrg       fptr += fstride0;
301*b1e83836Smrg       mptr += mstride0;
302*b1e83836Smrg       count[0]++;
303*b1e83836Smrg       n = 0;
304*b1e83836Smrg       while (count[n] == extent[n])
305*b1e83836Smrg         {
306*b1e83836Smrg           /* When we get to the end of a dimension, reset it and increment
307*b1e83836Smrg              the next dimension.  */
308*b1e83836Smrg           count[n] = 0;
309*b1e83836Smrg           /* We could precalculate these products, but this is a less
310*b1e83836Smrg              frequently used path so probably not worth it.  */
311*b1e83836Smrg           rptr -= rstride[n] * extent[n];
312*b1e83836Smrg           fptr -= fstride[n] * extent[n];
313*b1e83836Smrg           mptr -= mstride[n] * extent[n];
314*b1e83836Smrg           n++;
315*b1e83836Smrg           if (n >= dim)
316*b1e83836Smrg             {
317*b1e83836Smrg               /* Break out of the loop.  */
318*b1e83836Smrg               rptr = NULL;
319*b1e83836Smrg               break;
320*b1e83836Smrg             }
321*b1e83836Smrg           else
322*b1e83836Smrg             {
323*b1e83836Smrg               count[n]++;
324*b1e83836Smrg               rptr += rstride[n];
325*b1e83836Smrg               fptr += fstride[n];
326*b1e83836Smrg               mptr += mstride[n];
327*b1e83836Smrg             }
328*b1e83836Smrg         }
329*b1e83836Smrg     }
330*b1e83836Smrg }
331*b1e83836Smrg 
332*b1e83836Smrg #endif
333*b1e83836Smrg 
334