xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/generated/unpack_i8.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg /* Specific implementation of the UNPACK intrinsic
2*4c3eb207Smrg    Copyright (C) 2008-2020 Free Software Foundation, Inc.
3627f7eb2Smrg    Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>, based on
4627f7eb2Smrg    unpack_generic.c by Paul Brook <paul@nowt.org>.
5627f7eb2Smrg 
6627f7eb2Smrg This file is part of the GNU Fortran runtime library (libgfortran).
7627f7eb2Smrg 
8627f7eb2Smrg Libgfortran is free software; you can redistribute it and/or
9627f7eb2Smrg modify it under the terms of the GNU General Public
10627f7eb2Smrg License as published by the Free Software Foundation; either
11627f7eb2Smrg version 3 of the License, or (at your option) any later version.
12627f7eb2Smrg 
13627f7eb2Smrg Ligbfortran is distributed in the hope that it will be useful,
14627f7eb2Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
15627f7eb2Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16627f7eb2Smrg GNU General Public License for more details.
17627f7eb2Smrg 
18627f7eb2Smrg Under Section 7 of GPL version 3, you are granted additional
19627f7eb2Smrg permissions described in the GCC Runtime Library Exception, version
20627f7eb2Smrg 3.1, as published by the Free Software Foundation.
21627f7eb2Smrg 
22627f7eb2Smrg You should have received a copy of the GNU General Public License and
23627f7eb2Smrg a copy of the GCC Runtime Library Exception along with this program;
24627f7eb2Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25627f7eb2Smrg <http://www.gnu.org/licenses/>.  */
26627f7eb2Smrg 
27627f7eb2Smrg #include "libgfortran.h"
28627f7eb2Smrg #include <string.h>
29627f7eb2Smrg 
30627f7eb2Smrg 
31627f7eb2Smrg #if defined (HAVE_GFC_INTEGER_8)
32627f7eb2Smrg 
33627f7eb2Smrg void
unpack0_i8(gfc_array_i8 * ret,const gfc_array_i8 * vector,const gfc_array_l1 * mask,const GFC_INTEGER_8 * fptr)34627f7eb2Smrg unpack0_i8 (gfc_array_i8 *ret, const gfc_array_i8 *vector,
35627f7eb2Smrg 		 const gfc_array_l1 *mask, const GFC_INTEGER_8 *fptr)
36627f7eb2Smrg {
37627f7eb2Smrg   /* r.* indicates the return array.  */
38627f7eb2Smrg   index_type rstride[GFC_MAX_DIMENSIONS];
39627f7eb2Smrg   index_type rstride0;
40627f7eb2Smrg   index_type rs;
41627f7eb2Smrg   GFC_INTEGER_8 * restrict rptr;
42627f7eb2Smrg   /* v.* indicates the vector array.  */
43627f7eb2Smrg   index_type vstride0;
44627f7eb2Smrg   GFC_INTEGER_8 *vptr;
45627f7eb2Smrg   /* Value for field, this is constant.  */
46627f7eb2Smrg   const GFC_INTEGER_8 fval = *fptr;
47627f7eb2Smrg   /* m.* indicates the mask array.  */
48627f7eb2Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
49627f7eb2Smrg   index_type mstride0;
50627f7eb2Smrg   const GFC_LOGICAL_1 *mptr;
51627f7eb2Smrg 
52627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
53627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
54627f7eb2Smrg   index_type n;
55627f7eb2Smrg   index_type dim;
56627f7eb2Smrg 
57627f7eb2Smrg   int empty;
58627f7eb2Smrg   int mask_kind;
59627f7eb2Smrg 
60627f7eb2Smrg   empty = 0;
61627f7eb2Smrg 
62627f7eb2Smrg   mptr = mask->base_addr;
63627f7eb2Smrg 
64627f7eb2Smrg   /* Use the same loop for all logical types, by using GFC_LOGICAL_1
65627f7eb2Smrg      and using shifting to address size and endian issues.  */
66627f7eb2Smrg 
67627f7eb2Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
68627f7eb2Smrg 
69627f7eb2Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
70627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
71627f7eb2Smrg       || mask_kind == 16
72627f7eb2Smrg #endif
73627f7eb2Smrg       )
74627f7eb2Smrg     {
75627f7eb2Smrg       /*  Do not convert a NULL pointer as we use test for NULL below.  */
76627f7eb2Smrg       if (mptr)
77627f7eb2Smrg 	mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind);
78627f7eb2Smrg     }
79627f7eb2Smrg   else
80627f7eb2Smrg     runtime_error ("Funny sized logical array");
81627f7eb2Smrg 
82627f7eb2Smrg   if (ret->base_addr == NULL)
83627f7eb2Smrg     {
84627f7eb2Smrg       /* The front end has signalled that we need to populate the
85627f7eb2Smrg 	 return array descriptor.  */
86627f7eb2Smrg       dim = GFC_DESCRIPTOR_RANK (mask);
87627f7eb2Smrg       rs = 1;
88627f7eb2Smrg       for (n = 0; n < dim; n++)
89627f7eb2Smrg 	{
90627f7eb2Smrg 	  count[n] = 0;
91627f7eb2Smrg 	  GFC_DIMENSION_SET(ret->dim[n], 0,
92627f7eb2Smrg 			    GFC_DESCRIPTOR_EXTENT(mask,n) - 1, rs);
93627f7eb2Smrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
94627f7eb2Smrg 	  empty = empty || extent[n] <= 0;
95627f7eb2Smrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
96627f7eb2Smrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
97627f7eb2Smrg 	  rs *= extent[n];
98627f7eb2Smrg 	}
99627f7eb2Smrg       ret->offset = 0;
100627f7eb2Smrg       ret->base_addr = xmallocarray (rs, sizeof (GFC_INTEGER_8));
101627f7eb2Smrg     }
102627f7eb2Smrg   else
103627f7eb2Smrg     {
104627f7eb2Smrg       dim = GFC_DESCRIPTOR_RANK (ret);
105627f7eb2Smrg       /* Initialize to avoid -Wmaybe-uninitialized complaints.  */
106627f7eb2Smrg       rstride[0] = 1;
107627f7eb2Smrg       for (n = 0; n < dim; n++)
108627f7eb2Smrg 	{
109627f7eb2Smrg 	  count[n] = 0;
110627f7eb2Smrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
111627f7eb2Smrg 	  empty = empty || extent[n] <= 0;
112627f7eb2Smrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
113627f7eb2Smrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
114627f7eb2Smrg 	}
115627f7eb2Smrg       if (rstride[0] == 0)
116627f7eb2Smrg 	rstride[0] = 1;
117627f7eb2Smrg     }
118627f7eb2Smrg 
119627f7eb2Smrg   if (empty)
120627f7eb2Smrg     return;
121627f7eb2Smrg 
122627f7eb2Smrg   if (mstride[0] == 0)
123627f7eb2Smrg     mstride[0] = 1;
124627f7eb2Smrg 
125627f7eb2Smrg   vstride0 = GFC_DESCRIPTOR_STRIDE(vector,0);
126627f7eb2Smrg   if (vstride0 == 0)
127627f7eb2Smrg     vstride0 = 1;
128627f7eb2Smrg   rstride0 = rstride[0];
129627f7eb2Smrg   mstride0 = mstride[0];
130627f7eb2Smrg   rptr = ret->base_addr;
131627f7eb2Smrg   vptr = vector->base_addr;
132627f7eb2Smrg 
133627f7eb2Smrg   while (rptr)
134627f7eb2Smrg     {
135627f7eb2Smrg       if (*mptr)
136627f7eb2Smrg         {
137627f7eb2Smrg 	  /* From vector.  */
138627f7eb2Smrg 	  *rptr = *vptr;
139627f7eb2Smrg 	  vptr += vstride0;
140627f7eb2Smrg         }
141627f7eb2Smrg       else
142627f7eb2Smrg         {
143627f7eb2Smrg 	  /* From field.  */
144627f7eb2Smrg 	  *rptr = fval;
145627f7eb2Smrg         }
146627f7eb2Smrg       /* Advance to the next element.  */
147627f7eb2Smrg       rptr += rstride0;
148627f7eb2Smrg       mptr += mstride0;
149627f7eb2Smrg       count[0]++;
150627f7eb2Smrg       n = 0;
151627f7eb2Smrg       while (count[n] == extent[n])
152627f7eb2Smrg         {
153627f7eb2Smrg           /* When we get to the end of a dimension, reset it and increment
154627f7eb2Smrg              the next dimension.  */
155627f7eb2Smrg           count[n] = 0;
156627f7eb2Smrg           /* We could precalculate these products, but this is a less
157627f7eb2Smrg              frequently used path so probably not worth it.  */
158627f7eb2Smrg           rptr -= rstride[n] * extent[n];
159627f7eb2Smrg           mptr -= mstride[n] * extent[n];
160627f7eb2Smrg           n++;
161627f7eb2Smrg           if (n >= dim)
162627f7eb2Smrg             {
163627f7eb2Smrg               /* Break out of the loop.  */
164627f7eb2Smrg               rptr = NULL;
165627f7eb2Smrg               break;
166627f7eb2Smrg             }
167627f7eb2Smrg           else
168627f7eb2Smrg             {
169627f7eb2Smrg               count[n]++;
170627f7eb2Smrg               rptr += rstride[n];
171627f7eb2Smrg               mptr += mstride[n];
172627f7eb2Smrg             }
173627f7eb2Smrg         }
174627f7eb2Smrg     }
175627f7eb2Smrg }
176627f7eb2Smrg 
177627f7eb2Smrg void
unpack1_i8(gfc_array_i8 * ret,const gfc_array_i8 * vector,const gfc_array_l1 * mask,const gfc_array_i8 * field)178627f7eb2Smrg unpack1_i8 (gfc_array_i8 *ret, const gfc_array_i8 *vector,
179627f7eb2Smrg 		 const gfc_array_l1 *mask, const gfc_array_i8 *field)
180627f7eb2Smrg {
181627f7eb2Smrg   /* r.* indicates the return array.  */
182627f7eb2Smrg   index_type rstride[GFC_MAX_DIMENSIONS];
183627f7eb2Smrg   index_type rstride0;
184627f7eb2Smrg   index_type rs;
185627f7eb2Smrg   GFC_INTEGER_8 * restrict rptr;
186627f7eb2Smrg   /* v.* indicates the vector array.  */
187627f7eb2Smrg   index_type vstride0;
188627f7eb2Smrg   GFC_INTEGER_8 *vptr;
189627f7eb2Smrg   /* f.* indicates the field array.  */
190627f7eb2Smrg   index_type fstride[GFC_MAX_DIMENSIONS];
191627f7eb2Smrg   index_type fstride0;
192627f7eb2Smrg   const GFC_INTEGER_8 *fptr;
193627f7eb2Smrg   /* m.* indicates the mask array.  */
194627f7eb2Smrg   index_type mstride[GFC_MAX_DIMENSIONS];
195627f7eb2Smrg   index_type mstride0;
196627f7eb2Smrg   const GFC_LOGICAL_1 *mptr;
197627f7eb2Smrg 
198627f7eb2Smrg   index_type count[GFC_MAX_DIMENSIONS];
199627f7eb2Smrg   index_type extent[GFC_MAX_DIMENSIONS];
200627f7eb2Smrg   index_type n;
201627f7eb2Smrg   index_type dim;
202627f7eb2Smrg 
203627f7eb2Smrg   int empty;
204627f7eb2Smrg   int mask_kind;
205627f7eb2Smrg 
206627f7eb2Smrg   empty = 0;
207627f7eb2Smrg 
208627f7eb2Smrg   mptr = mask->base_addr;
209627f7eb2Smrg 
210627f7eb2Smrg   /* Use the same loop for all logical types, by using GFC_LOGICAL_1
211627f7eb2Smrg      and using shifting to address size and endian issues.  */
212627f7eb2Smrg 
213627f7eb2Smrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
214627f7eb2Smrg 
215627f7eb2Smrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
216627f7eb2Smrg #ifdef HAVE_GFC_LOGICAL_16
217627f7eb2Smrg       || mask_kind == 16
218627f7eb2Smrg #endif
219627f7eb2Smrg       )
220627f7eb2Smrg     {
221627f7eb2Smrg       /*  Do not convert a NULL pointer as we use test for NULL below.  */
222627f7eb2Smrg       if (mptr)
223627f7eb2Smrg 	mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind);
224627f7eb2Smrg     }
225627f7eb2Smrg   else
226627f7eb2Smrg     runtime_error ("Funny sized logical array");
227627f7eb2Smrg 
228627f7eb2Smrg   if (ret->base_addr == NULL)
229627f7eb2Smrg     {
230627f7eb2Smrg       /* The front end has signalled that we need to populate the
231627f7eb2Smrg 	 return array descriptor.  */
232627f7eb2Smrg       dim = GFC_DESCRIPTOR_RANK (mask);
233627f7eb2Smrg       rs = 1;
234627f7eb2Smrg       for (n = 0; n < dim; n++)
235627f7eb2Smrg 	{
236627f7eb2Smrg 	  count[n] = 0;
237627f7eb2Smrg 	  GFC_DIMENSION_SET(ret->dim[n], 0,
238627f7eb2Smrg 			    GFC_DESCRIPTOR_EXTENT(mask,n) - 1, rs);
239627f7eb2Smrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
240627f7eb2Smrg 	  empty = empty || extent[n] <= 0;
241627f7eb2Smrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
242627f7eb2Smrg 	  fstride[n] = GFC_DESCRIPTOR_STRIDE(field,n);
243627f7eb2Smrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
244627f7eb2Smrg 	  rs *= extent[n];
245627f7eb2Smrg 	}
246627f7eb2Smrg       ret->offset = 0;
247627f7eb2Smrg       ret->base_addr = xmallocarray (rs, sizeof (GFC_INTEGER_8));
248627f7eb2Smrg     }
249627f7eb2Smrg   else
250627f7eb2Smrg     {
251627f7eb2Smrg       dim = GFC_DESCRIPTOR_RANK (ret);
252627f7eb2Smrg       /* Initialize to avoid -Wmaybe-uninitialized complaints.  */
253627f7eb2Smrg       rstride[0] = 1;
254627f7eb2Smrg       for (n = 0; n < dim; n++)
255627f7eb2Smrg 	{
256627f7eb2Smrg 	  count[n] = 0;
257627f7eb2Smrg 	  extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
258627f7eb2Smrg 	  empty = empty || extent[n] <= 0;
259627f7eb2Smrg 	  rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,n);
260627f7eb2Smrg 	  fstride[n] = GFC_DESCRIPTOR_STRIDE(field,n);
261627f7eb2Smrg 	  mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
262627f7eb2Smrg 	}
263627f7eb2Smrg       if (rstride[0] == 0)
264627f7eb2Smrg 	rstride[0] = 1;
265627f7eb2Smrg     }
266627f7eb2Smrg 
267627f7eb2Smrg   if (empty)
268627f7eb2Smrg     return;
269627f7eb2Smrg 
270627f7eb2Smrg   if (fstride[0] == 0)
271627f7eb2Smrg     fstride[0] = 1;
272627f7eb2Smrg   if (mstride[0] == 0)
273627f7eb2Smrg     mstride[0] = 1;
274627f7eb2Smrg 
275627f7eb2Smrg   vstride0 = GFC_DESCRIPTOR_STRIDE(vector,0);
276627f7eb2Smrg   if (vstride0 == 0)
277627f7eb2Smrg     vstride0 = 1;
278627f7eb2Smrg   rstride0 = rstride[0];
279627f7eb2Smrg   fstride0 = fstride[0];
280627f7eb2Smrg   mstride0 = mstride[0];
281627f7eb2Smrg   rptr = ret->base_addr;
282627f7eb2Smrg   fptr = field->base_addr;
283627f7eb2Smrg   vptr = vector->base_addr;
284627f7eb2Smrg 
285627f7eb2Smrg   while (rptr)
286627f7eb2Smrg     {
287627f7eb2Smrg       if (*mptr)
288627f7eb2Smrg         {
289627f7eb2Smrg           /* From vector.  */
290627f7eb2Smrg 	  *rptr = *vptr;
291627f7eb2Smrg           vptr += vstride0;
292627f7eb2Smrg         }
293627f7eb2Smrg       else
294627f7eb2Smrg         {
295627f7eb2Smrg           /* From field.  */
296627f7eb2Smrg 	  *rptr = *fptr;
297627f7eb2Smrg         }
298627f7eb2Smrg       /* Advance to the next element.  */
299627f7eb2Smrg       rptr += rstride0;
300627f7eb2Smrg       fptr += fstride0;
301627f7eb2Smrg       mptr += mstride0;
302627f7eb2Smrg       count[0]++;
303627f7eb2Smrg       n = 0;
304627f7eb2Smrg       while (count[n] == extent[n])
305627f7eb2Smrg         {
306627f7eb2Smrg           /* When we get to the end of a dimension, reset it and increment
307627f7eb2Smrg              the next dimension.  */
308627f7eb2Smrg           count[n] = 0;
309627f7eb2Smrg           /* We could precalculate these products, but this is a less
310627f7eb2Smrg              frequently used path so probably not worth it.  */
311627f7eb2Smrg           rptr -= rstride[n] * extent[n];
312627f7eb2Smrg           fptr -= fstride[n] * extent[n];
313627f7eb2Smrg           mptr -= mstride[n] * extent[n];
314627f7eb2Smrg           n++;
315627f7eb2Smrg           if (n >= dim)
316627f7eb2Smrg             {
317627f7eb2Smrg               /* Break out of the loop.  */
318627f7eb2Smrg               rptr = NULL;
319627f7eb2Smrg               break;
320627f7eb2Smrg             }
321627f7eb2Smrg           else
322627f7eb2Smrg             {
323627f7eb2Smrg               count[n]++;
324627f7eb2Smrg               rptr += rstride[n];
325627f7eb2Smrg               fptr += fstride[n];
326627f7eb2Smrg               mptr += mstride[n];
327627f7eb2Smrg             }
328627f7eb2Smrg         }
329627f7eb2Smrg     }
330627f7eb2Smrg }
331627f7eb2Smrg 
332627f7eb2Smrg #endif
333627f7eb2Smrg 
334