* config.gcc (c_target_objs)[i?86-*-pe|i?86-*-cygwin*]: Don't add
[official-gcc.git] / libgfortran / intrinsics / unpack_generic.c
blob0256b25f56a1d63ff2a7bd6593ee996c4bcc8898
1 /* Generic implementation of the UNPACK intrinsic
2 Copyright 2002, 2003, 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 Ligbfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgfortran.h"
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <string.h>
31 /* All the bounds checking for unpack in one function. If field is NULL,
32 we don't check it, for the unpack0 functions. */
34 static void
35 unpack_bounds (gfc_array_char *ret, const gfc_array_char *vector,
36 const gfc_array_l1 *mask, const gfc_array_char *field)
38 index_type vec_size, mask_count;
39 vec_size = size0 ((array_t *) vector);
40 mask_count = count_0 (mask);
41 if (vec_size < mask_count)
42 runtime_error ("Incorrect size of return value in UNPACK"
43 " intrinsic: should be at least %ld, is"
44 " %ld", (long int) mask_count,
45 (long int) vec_size);
47 if (field != NULL)
48 bounds_equal_extents ((array_t *) field, (array_t *) mask,
49 "FIELD", "UNPACK");
51 if (ret->data != NULL)
52 bounds_equal_extents ((array_t *) ret, (array_t *) mask,
53 "return value", "UNPACK");
57 static void
58 unpack_internal (gfc_array_char *ret, const gfc_array_char *vector,
59 const gfc_array_l1 *mask, const gfc_array_char *field,
60 index_type size)
62 /* r.* indicates the return array. */
63 index_type rstride[GFC_MAX_DIMENSIONS];
64 index_type rstride0;
65 index_type rs;
66 char * restrict rptr;
67 /* v.* indicates the vector array. */
68 index_type vstride0;
69 char *vptr;
70 /* f.* indicates the field array. */
71 index_type fstride[GFC_MAX_DIMENSIONS];
72 index_type fstride0;
73 const char *fptr;
74 /* m.* indicates the mask array. */
75 index_type mstride[GFC_MAX_DIMENSIONS];
76 index_type mstride0;
77 const GFC_LOGICAL_1 *mptr;
79 index_type count[GFC_MAX_DIMENSIONS];
80 index_type extent[GFC_MAX_DIMENSIONS];
81 index_type n;
82 index_type dim;
84 int empty;
85 int mask_kind;
87 empty = 0;
89 mptr = mask->data;
91 /* Use the same loop for all logical types, by using GFC_LOGICAL_1
92 and using shifting to address size and endian issues. */
94 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
96 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
97 #ifdef HAVE_GFC_LOGICAL_16
98 || mask_kind == 16
99 #endif
102 /* Don't convert a NULL pointer as we use test for NULL below. */
103 if (mptr)
104 mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind);
106 else
107 runtime_error ("Funny sized logical array");
109 if (ret->data == NULL)
111 /* The front end has signalled that we need to populate the
112 return array descriptor. */
113 dim = GFC_DESCRIPTOR_RANK (mask);
114 rs = 1;
115 for (n = 0; n < dim; n++)
117 count[n] = 0;
118 GFC_DIMENSION_SET(ret->dim[n], 0,
119 GFC_DESCRIPTOR_EXTENT(mask,n) - 1, rs);
120 extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
121 empty = empty || extent[n] <= 0;
122 rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret, n);
123 fstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(field, n);
124 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n);
125 rs *= extent[n];
127 ret->offset = 0;
128 ret->data = internal_malloc_size (rs * size);
130 else
132 dim = GFC_DESCRIPTOR_RANK (ret);
133 for (n = 0; n < dim; n++)
135 count[n] = 0;
136 extent[n] = GFC_DESCRIPTOR_EXTENT(ret,n);
137 empty = empty || extent[n] <= 0;
138 rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret, n);
139 fstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(field, n);
140 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n);
144 if (empty)
145 return;
147 vstride0 = GFC_DESCRIPTOR_STRIDE_BYTES(vector,0);
148 rstride0 = rstride[0];
149 fstride0 = fstride[0];
150 mstride0 = mstride[0];
151 rptr = ret->data;
152 fptr = field->data;
153 vptr = vector->data;
155 while (rptr)
157 if (*mptr)
159 /* From vector. */
160 memcpy (rptr, vptr, size);
161 vptr += vstride0;
163 else
165 /* From field. */
166 memcpy (rptr, fptr, size);
168 /* Advance to the next element. */
169 rptr += rstride0;
170 fptr += fstride0;
171 mptr += mstride0;
172 count[0]++;
173 n = 0;
174 while (count[n] == extent[n])
176 /* When we get to the end of a dimension, reset it and increment
177 the next dimension. */
178 count[n] = 0;
179 /* We could precalculate these products, but this is a less
180 frequently used path so probably not worth it. */
181 rptr -= rstride[n] * extent[n];
182 fptr -= fstride[n] * extent[n];
183 mptr -= mstride[n] * extent[n];
184 n++;
185 if (n >= dim)
187 /* Break out of the loop. */
188 rptr = NULL;
189 break;
191 else
193 count[n]++;
194 rptr += rstride[n];
195 fptr += fstride[n];
196 mptr += mstride[n];
202 extern void unpack1 (gfc_array_char *, const gfc_array_char *,
203 const gfc_array_l1 *, const gfc_array_char *);
204 export_proto(unpack1);
206 void
207 unpack1 (gfc_array_char *ret, const gfc_array_char *vector,
208 const gfc_array_l1 *mask, const gfc_array_char *field)
210 index_type type_size;
211 index_type size;
213 if (unlikely(compile_options.bounds_check))
214 unpack_bounds (ret, vector, mask, field);
216 type_size = GFC_DTYPE_TYPE_SIZE (vector);
217 size = GFC_DESCRIPTOR_SIZE (vector);
219 switch(type_size)
221 case GFC_DTYPE_LOGICAL_1:
222 case GFC_DTYPE_INTEGER_1:
223 case GFC_DTYPE_DERIVED_1:
224 unpack1_i1 ((gfc_array_i1 *) ret, (gfc_array_i1 *) vector,
225 mask, (gfc_array_i1 *) field);
226 return;
228 case GFC_DTYPE_LOGICAL_2:
229 case GFC_DTYPE_INTEGER_2:
230 unpack1_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) vector,
231 mask, (gfc_array_i2 *) field);
232 return;
234 case GFC_DTYPE_LOGICAL_4:
235 case GFC_DTYPE_INTEGER_4:
236 unpack1_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) vector,
237 mask, (gfc_array_i4 *) field);
238 return;
240 case GFC_DTYPE_LOGICAL_8:
241 case GFC_DTYPE_INTEGER_8:
242 unpack1_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) vector,
243 mask, (gfc_array_i8 *) field);
244 return;
246 #ifdef HAVE_GFC_INTEGER_16
247 case GFC_DTYPE_LOGICAL_16:
248 case GFC_DTYPE_INTEGER_16:
249 unpack1_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) vector,
250 mask, (gfc_array_i16 *) field);
251 return;
252 #endif
254 case GFC_DTYPE_REAL_4:
255 unpack1_r4 ((gfc_array_r4 *) ret, (gfc_array_r4 *) vector,
256 mask, (gfc_array_r4 *) field);
257 return;
259 case GFC_DTYPE_REAL_8:
260 unpack1_r8 ((gfc_array_r8 *) ret, (gfc_array_r8 *) vector,
261 mask, (gfc_array_r8 *) field);
262 return;
264 #ifdef HAVE_GFC_REAL_10
265 case GFC_DTYPE_REAL_10:
266 unpack1_r10 ((gfc_array_r10 *) ret, (gfc_array_r10 *) vector,
267 mask, (gfc_array_r10 *) field);
268 return;
269 #endif
271 #ifdef HAVE_GFC_REAL_16
272 case GFC_DTYPE_REAL_16:
273 unpack1_r16 ((gfc_array_r16 *) ret, (gfc_array_r16 *) vector,
274 mask, (gfc_array_r16 *) field);
275 return;
276 #endif
278 case GFC_DTYPE_COMPLEX_4:
279 unpack1_c4 ((gfc_array_c4 *) ret, (gfc_array_c4 *) vector,
280 mask, (gfc_array_c4 *) field);
281 return;
283 case GFC_DTYPE_COMPLEX_8:
284 unpack1_c8 ((gfc_array_c8 *) ret, (gfc_array_c8 *) vector,
285 mask, (gfc_array_c8 *) field);
286 return;
288 #ifdef HAVE_GFC_COMPLEX_10
289 case GFC_DTYPE_COMPLEX_10:
290 unpack1_c10 ((gfc_array_c10 *) ret, (gfc_array_c10 *) vector,
291 mask, (gfc_array_c10 *) field);
292 return;
293 #endif
295 #ifdef HAVE_GFC_COMPLEX_16
296 case GFC_DTYPE_COMPLEX_16:
297 unpack1_c16 ((gfc_array_c16 *) ret, (gfc_array_c16 *) vector,
298 mask, (gfc_array_c16 *) field);
299 return;
300 #endif
302 case GFC_DTYPE_DERIVED_2:
303 if (GFC_UNALIGNED_2(ret->data) || GFC_UNALIGNED_2(vector->data)
304 || GFC_UNALIGNED_2(field->data))
305 break;
306 else
308 unpack1_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) vector,
309 mask, (gfc_array_i2 *) field);
310 return;
313 case GFC_DTYPE_DERIVED_4:
314 if (GFC_UNALIGNED_4(ret->data) || GFC_UNALIGNED_4(vector->data)
315 || GFC_UNALIGNED_4(field->data))
316 break;
317 else
319 unpack1_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) vector,
320 mask, (gfc_array_i4 *) field);
321 return;
324 case GFC_DTYPE_DERIVED_8:
325 if (GFC_UNALIGNED_8(ret->data) || GFC_UNALIGNED_8(vector->data)
326 || GFC_UNALIGNED_8(field->data))
327 break;
328 else
330 unpack1_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) vector,
331 mask, (gfc_array_i8 *) field);
332 return;
335 #ifdef HAVE_GFC_INTEGER_16
336 case GFC_DTYPE_DERIVED_16:
337 if (GFC_UNALIGNED_16(ret->data) || GFC_UNALIGNED_16(vector->data)
338 || GFC_UNALIGNED_16(field->data))
339 break;
340 else
342 unpack1_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) vector,
343 mask, (gfc_array_i16 *) field);
344 return;
346 #endif
349 unpack_internal (ret, vector, mask, field, size);
353 extern void unpack1_char (gfc_array_char *, GFC_INTEGER_4,
354 const gfc_array_char *, const gfc_array_l1 *,
355 const gfc_array_char *, GFC_INTEGER_4,
356 GFC_INTEGER_4);
357 export_proto(unpack1_char);
359 void
360 unpack1_char (gfc_array_char *ret,
361 GFC_INTEGER_4 ret_length __attribute__((unused)),
362 const gfc_array_char *vector, const gfc_array_l1 *mask,
363 const gfc_array_char *field, GFC_INTEGER_4 vector_length,
364 GFC_INTEGER_4 field_length __attribute__((unused)))
367 if (unlikely(compile_options.bounds_check))
368 unpack_bounds (ret, vector, mask, field);
370 unpack_internal (ret, vector, mask, field, vector_length);
374 extern void unpack1_char4 (gfc_array_char *, GFC_INTEGER_4,
375 const gfc_array_char *, const gfc_array_l1 *,
376 const gfc_array_char *, GFC_INTEGER_4,
377 GFC_INTEGER_4);
378 export_proto(unpack1_char4);
380 void
381 unpack1_char4 (gfc_array_char *ret,
382 GFC_INTEGER_4 ret_length __attribute__((unused)),
383 const gfc_array_char *vector, const gfc_array_l1 *mask,
384 const gfc_array_char *field, GFC_INTEGER_4 vector_length,
385 GFC_INTEGER_4 field_length __attribute__((unused)))
388 if (unlikely(compile_options.bounds_check))
389 unpack_bounds (ret, vector, mask, field);
391 unpack_internal (ret, vector, mask, field,
392 vector_length * sizeof (gfc_char4_t));
396 extern void unpack0 (gfc_array_char *, const gfc_array_char *,
397 const gfc_array_l1 *, char *);
398 export_proto(unpack0);
400 void
401 unpack0 (gfc_array_char *ret, const gfc_array_char *vector,
402 const gfc_array_l1 *mask, char *field)
404 gfc_array_char tmp;
406 index_type type_size;
408 if (unlikely(compile_options.bounds_check))
409 unpack_bounds (ret, vector, mask, NULL);
411 type_size = GFC_DTYPE_TYPE_SIZE (vector);
413 switch (type_size)
415 case GFC_DTYPE_LOGICAL_1:
416 case GFC_DTYPE_INTEGER_1:
417 case GFC_DTYPE_DERIVED_1:
418 unpack0_i1 ((gfc_array_i1 *) ret, (gfc_array_i1 *) vector,
419 mask, (GFC_INTEGER_1 *) field);
420 return;
422 case GFC_DTYPE_LOGICAL_2:
423 case GFC_DTYPE_INTEGER_2:
424 unpack0_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) vector,
425 mask, (GFC_INTEGER_2 *) field);
426 return;
428 case GFC_DTYPE_LOGICAL_4:
429 case GFC_DTYPE_INTEGER_4:
430 unpack0_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) vector,
431 mask, (GFC_INTEGER_4 *) field);
432 return;
434 case GFC_DTYPE_LOGICAL_8:
435 case GFC_DTYPE_INTEGER_8:
436 unpack0_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) vector,
437 mask, (GFC_INTEGER_8 *) field);
438 return;
440 #ifdef HAVE_GFC_INTEGER_16
441 case GFC_DTYPE_LOGICAL_16:
442 case GFC_DTYPE_INTEGER_16:
443 unpack0_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) vector,
444 mask, (GFC_INTEGER_16 *) field);
445 return;
446 #endif
448 case GFC_DTYPE_REAL_4:
449 unpack0_r4 ((gfc_array_r4 *) ret, (gfc_array_r4 *) vector,
450 mask, (GFC_REAL_4 *) field);
451 return;
453 case GFC_DTYPE_REAL_8:
454 unpack0_r8 ((gfc_array_r8 *) ret, (gfc_array_r8*) vector,
455 mask, (GFC_REAL_8 *) field);
456 return;
458 #ifdef HAVE_GFC_REAL_10
459 case GFC_DTYPE_REAL_10:
460 unpack0_r10 ((gfc_array_r10 *) ret, (gfc_array_r10 *) vector,
461 mask, (GFC_REAL_10 *) field);
462 return;
463 #endif
465 #ifdef HAVE_GFC_REAL_16
466 case GFC_DTYPE_REAL_16:
467 unpack0_r16 ((gfc_array_r16 *) ret, (gfc_array_r16 *) vector,
468 mask, (GFC_REAL_16 *) field);
469 return;
470 #endif
472 case GFC_DTYPE_COMPLEX_4:
473 unpack0_c4 ((gfc_array_c4 *) ret, (gfc_array_c4 *) vector,
474 mask, (GFC_COMPLEX_4 *) field);
475 return;
477 case GFC_DTYPE_COMPLEX_8:
478 unpack0_c8 ((gfc_array_c8 *) ret, (gfc_array_c8 *) vector,
479 mask, (GFC_COMPLEX_8 *) field);
480 return;
482 #ifdef HAVE_GFC_COMPLEX_10
483 case GFC_DTYPE_COMPLEX_10:
484 unpack0_c10 ((gfc_array_c10 *) ret, (gfc_array_c10 *) vector,
485 mask, (GFC_COMPLEX_10 *) field);
486 return;
487 #endif
489 #ifdef HAVE_GFC_COMPLEX_16
490 case GFC_DTYPE_COMPLEX_16:
491 unpack0_c16 ((gfc_array_c16 *) ret, (gfc_array_c16 *) vector,
492 mask, (GFC_COMPLEX_16 *) field);
493 return;
494 #endif
496 case GFC_DTYPE_DERIVED_2:
497 if (GFC_UNALIGNED_2(ret->data) || GFC_UNALIGNED_2(vector->data)
498 || GFC_UNALIGNED_2(field))
499 break;
500 else
502 unpack0_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) vector,
503 mask, (GFC_INTEGER_2 *) field);
504 return;
507 case GFC_DTYPE_DERIVED_4:
508 if (GFC_UNALIGNED_4(ret->data) || GFC_UNALIGNED_4(vector->data)
509 || GFC_UNALIGNED_4(field))
510 break;
511 else
513 unpack0_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) vector,
514 mask, (GFC_INTEGER_4 *) field);
515 return;
518 case GFC_DTYPE_DERIVED_8:
519 if (GFC_UNALIGNED_8(ret->data) || GFC_UNALIGNED_8(vector->data)
520 || GFC_UNALIGNED_8(field))
521 break;
522 else
524 unpack0_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) vector,
525 mask, (GFC_INTEGER_8 *) field);
526 return;
529 #ifdef HAVE_GFC_INTEGER_16
530 case GFC_DTYPE_DERIVED_16:
531 if (GFC_UNALIGNED_16(ret->data) || GFC_UNALIGNED_16(vector->data)
532 || GFC_UNALIGNED_16(field))
533 break;
534 else
536 unpack0_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) vector,
537 mask, (GFC_INTEGER_16 *) field);
538 return;
540 #endif
544 memset (&tmp, 0, sizeof (tmp));
545 tmp.dtype = 0;
546 tmp.data = field;
547 unpack_internal (ret, vector, mask, &tmp, GFC_DESCRIPTOR_SIZE (vector));
551 extern void unpack0_char (gfc_array_char *, GFC_INTEGER_4,
552 const gfc_array_char *, const gfc_array_l1 *,
553 char *, GFC_INTEGER_4, GFC_INTEGER_4);
554 export_proto(unpack0_char);
556 void
557 unpack0_char (gfc_array_char *ret,
558 GFC_INTEGER_4 ret_length __attribute__((unused)),
559 const gfc_array_char *vector, const gfc_array_l1 *mask,
560 char *field, GFC_INTEGER_4 vector_length,
561 GFC_INTEGER_4 field_length __attribute__((unused)))
563 gfc_array_char tmp;
565 if (unlikely(compile_options.bounds_check))
566 unpack_bounds (ret, vector, mask, NULL);
568 memset (&tmp, 0, sizeof (tmp));
569 tmp.dtype = 0;
570 tmp.data = field;
571 unpack_internal (ret, vector, mask, &tmp, vector_length);
575 extern void unpack0_char4 (gfc_array_char *, GFC_INTEGER_4,
576 const gfc_array_char *, const gfc_array_l1 *,
577 char *, GFC_INTEGER_4, GFC_INTEGER_4);
578 export_proto(unpack0_char4);
580 void
581 unpack0_char4 (gfc_array_char *ret,
582 GFC_INTEGER_4 ret_length __attribute__((unused)),
583 const gfc_array_char *vector, const gfc_array_l1 *mask,
584 char *field, GFC_INTEGER_4 vector_length,
585 GFC_INTEGER_4 field_length __attribute__((unused)))
587 gfc_array_char tmp;
589 if (unlikely(compile_options.bounds_check))
590 unpack_bounds (ret, vector, mask, NULL);
592 memset (&tmp, 0, sizeof (tmp));
593 tmp.dtype = 0;
594 tmp.data = field;
595 unpack_internal (ret, vector, mask, &tmp,
596 vector_length * sizeof (gfc_char4_t));