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"
32 unpack_internal (gfc_array_char
*ret
, const gfc_array_char
*vector
,
33 const gfc_array_l1
*mask
, const gfc_array_char
*field
,
34 index_type size
, index_type fsize
)
36 /* r.* indicates the return array. */
37 index_type rstride
[GFC_MAX_DIMENSIONS
];
41 /* v.* indicates the vector array. */
44 /* f.* indicates the field array. */
45 index_type fstride
[GFC_MAX_DIMENSIONS
];
48 /* m.* indicates the mask array. */
49 index_type mstride
[GFC_MAX_DIMENSIONS
];
51 const GFC_LOGICAL_1
*mptr
;
53 index_type count
[GFC_MAX_DIMENSIONS
];
54 index_type extent
[GFC_MAX_DIMENSIONS
];
65 /* Use the same loop for all logical types, by using GFC_LOGICAL_1
66 and using shifting to address size and endian issues. */
68 mask_kind
= GFC_DESCRIPTOR_SIZE (mask
);
70 if (mask_kind
== 1 || mask_kind
== 2 || mask_kind
== 4 || mask_kind
== 8
71 #ifdef HAVE_GFC_LOGICAL_16
76 /* Don't convert a NULL pointer as we use test for NULL below. */
78 mptr
= GFOR_POINTER_TO_L1 (mptr
, mask_kind
);
81 runtime_error ("Funny sized logical array");
83 if (ret
->data
== NULL
)
85 /* The front end has signalled that we need to populate the
86 return array descriptor. */
87 dim
= GFC_DESCRIPTOR_RANK (mask
);
89 for (n
= 0; n
< dim
; n
++)
92 ret
->dim
[n
].stride
= rs
;
93 ret
->dim
[n
].lbound
= 0;
94 ret
->dim
[n
].ubound
= mask
->dim
[n
].ubound
- mask
->dim
[n
].lbound
;
95 extent
[n
] = ret
->dim
[n
].ubound
+ 1;
96 empty
= empty
|| extent
[n
] <= 0;
97 rstride
[n
] = ret
->dim
[n
].stride
* size
;
98 fstride
[n
] = field
->dim
[n
].stride
* fsize
;
99 mstride
[n
] = mask
->dim
[n
].stride
* mask_kind
;
103 ret
->data
= internal_malloc_size (rs
* size
);
107 dim
= GFC_DESCRIPTOR_RANK (ret
);
108 for (n
= 0; n
< dim
; n
++)
111 extent
[n
] = ret
->dim
[n
].ubound
+ 1 - ret
->dim
[n
].lbound
;
112 empty
= empty
|| extent
[n
] <= 0;
113 rstride
[n
] = ret
->dim
[n
].stride
* size
;
114 fstride
[n
] = field
->dim
[n
].stride
* fsize
;
115 mstride
[n
] = mask
->dim
[n
].stride
* mask_kind
;
129 vstride0
= vector
->dim
[0].stride
* size
;
132 rstride0
= rstride
[0];
133 fstride0
= fstride
[0];
134 mstride0
= mstride
[0];
144 memcpy (rptr
, vptr
, size
);
150 memcpy (rptr
, fptr
, size
);
152 /* Advance to the next element. */
158 while (count
[n
] == extent
[n
])
160 /* When we get to the end of a dimension, reset it and increment
161 the next dimension. */
163 /* We could precalculate these products, but this is a less
164 frequently used path so probably not worth it. */
165 rptr
-= rstride
[n
] * extent
[n
];
166 fptr
-= fstride
[n
] * extent
[n
];
167 mptr
-= mstride
[n
] * extent
[n
];
171 /* Break out of the loop. */
186 extern void unpack1 (gfc_array_char
*, const gfc_array_char
*,
187 const gfc_array_l1
*, const gfc_array_char
*);
188 export_proto(unpack1
);
191 unpack1 (gfc_array_char
*ret
, const gfc_array_char
*vector
,
192 const gfc_array_l1
*mask
, const gfc_array_char
*field
)
194 index_type type_size
;
197 type_size
= GFC_DTYPE_TYPE_SIZE (vector
);
198 size
= GFC_DESCRIPTOR_SIZE (vector
);
202 case GFC_DTYPE_LOGICAL_1
:
203 case GFC_DTYPE_INTEGER_1
:
204 case GFC_DTYPE_DERIVED_1
:
205 unpack1_i1 ((gfc_array_i1
*) ret
, (gfc_array_i1
*) vector
,
206 mask
, (gfc_array_i1
*) field
);
209 case GFC_DTYPE_LOGICAL_2
:
210 case GFC_DTYPE_INTEGER_2
:
211 unpack1_i2 ((gfc_array_i2
*) ret
, (gfc_array_i2
*) vector
,
212 mask
, (gfc_array_i2
*) field
);
215 case GFC_DTYPE_LOGICAL_4
:
216 case GFC_DTYPE_INTEGER_4
:
217 unpack1_i4 ((gfc_array_i4
*) ret
, (gfc_array_i4
*) vector
,
218 mask
, (gfc_array_i4
*) field
);
221 case GFC_DTYPE_LOGICAL_8
:
222 case GFC_DTYPE_INTEGER_8
:
223 unpack1_i8 ((gfc_array_i8
*) ret
, (gfc_array_i8
*) vector
,
224 mask
, (gfc_array_i8
*) field
);
227 #ifdef HAVE_GFC_INTEGER_16
228 case GFC_DTYPE_LOGICAL_16
:
229 case GFC_DTYPE_INTEGER_16
:
230 unpack1_i16 ((gfc_array_i16
*) ret
, (gfc_array_i16
*) vector
,
231 mask
, (gfc_array_i16
*) field
);
234 case GFC_DTYPE_REAL_4
:
235 unpack1_r4 ((gfc_array_r4
*) ret
, (gfc_array_r4
*) vector
,
236 mask
, (gfc_array_r4
*) field
);
239 case GFC_DTYPE_REAL_8
:
240 unpack1_r8 ((gfc_array_r8
*) ret
, (gfc_array_r8
*) vector
,
241 mask
, (gfc_array_r8
*) field
);
244 #ifdef HAVE_GFC_REAL_10
245 case GFC_DTYPE_REAL_10
:
246 unpack1_r10 ((gfc_array_r10
*) ret
, (gfc_array_r10
*) vector
,
247 mask
, (gfc_array_r10
*) field
);
251 #ifdef HAVE_GFC_REAL_16
252 case GFC_DTYPE_REAL_16
:
253 unpack1_r16 ((gfc_array_r16
*) ret
, (gfc_array_r16
*) vector
,
254 mask
, (gfc_array_r16
*) field
);
258 case GFC_DTYPE_COMPLEX_4
:
259 unpack1_c4 ((gfc_array_c4
*) ret
, (gfc_array_c4
*) vector
,
260 mask
, (gfc_array_c4
*) field
);
263 case GFC_DTYPE_COMPLEX_8
:
264 unpack1_c8 ((gfc_array_c8
*) ret
, (gfc_array_c8
*) vector
,
265 mask
, (gfc_array_c8
*) field
);
268 #ifdef HAVE_GFC_COMPLEX_10
269 case GFC_DTYPE_COMPLEX_10
:
270 unpack1_c10 ((gfc_array_c10
*) ret
, (gfc_array_c10
*) vector
,
271 mask
, (gfc_array_c10
*) field
);
275 #ifdef HAVE_GFC_COMPLEX_16
276 case GFC_DTYPE_COMPLEX_16
:
277 unpack1_c16 ((gfc_array_c16
*) ret
, (gfc_array_c16
*) vector
,
278 mask
, (gfc_array_c16
*) field
);
282 case GFC_DTYPE_DERIVED_2
:
283 if (GFC_UNALIGNED_2(ret
->data
) || GFC_UNALIGNED_2(vector
->data
)
284 || GFC_UNALIGNED_2(field
->data
))
288 unpack1_i2 ((gfc_array_i2
*) ret
, (gfc_array_i2
*) vector
,
289 mask
, (gfc_array_i2
*) field
);
293 case GFC_DTYPE_DERIVED_4
:
294 if (GFC_UNALIGNED_4(ret
->data
) || GFC_UNALIGNED_4(vector
->data
)
295 || GFC_UNALIGNED_4(field
->data
))
299 unpack1_i4 ((gfc_array_i4
*) ret
, (gfc_array_i4
*) vector
,
300 mask
, (gfc_array_i4
*) field
);
304 case GFC_DTYPE_DERIVED_8
:
305 if (GFC_UNALIGNED_8(ret
->data
) || GFC_UNALIGNED_8(vector
->data
)
306 || GFC_UNALIGNED_8(field
->data
))
310 unpack1_i8 ((gfc_array_i8
*) ret
, (gfc_array_i8
*) vector
,
311 mask
, (gfc_array_i8
*) field
);
315 #ifdef HAVE_GFC_INTEGER_16
316 case GFC_DTYPE_DERIVED_16
:
317 if (GFC_UNALIGNED_16(ret
->data
) || GFC_UNALIGNED_16(vector
->data
)
318 || GFC_UNALIGNED_16(field
->data
))
322 unpack1_i16 ((gfc_array_i16
*) ret
, (gfc_array_i16
*) vector
,
323 mask
, (gfc_array_i16
*) field
);
329 unpack_internal (ret
, vector
, mask
, field
, size
,
330 GFC_DESCRIPTOR_SIZE (field
));
334 extern void unpack1_char (gfc_array_char
*, GFC_INTEGER_4
,
335 const gfc_array_char
*, const gfc_array_l1
*,
336 const gfc_array_char
*, GFC_INTEGER_4
,
338 export_proto(unpack1_char
);
341 unpack1_char (gfc_array_char
*ret
,
342 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
343 const gfc_array_char
*vector
, const gfc_array_l1
*mask
,
344 const gfc_array_char
*field
, GFC_INTEGER_4 vector_length
,
345 GFC_INTEGER_4 field_length
)
347 unpack_internal (ret
, vector
, mask
, field
, vector_length
, field_length
);
351 extern void unpack1_char4 (gfc_array_char
*, GFC_INTEGER_4
,
352 const gfc_array_char
*, const gfc_array_l1
*,
353 const gfc_array_char
*, GFC_INTEGER_4
,
355 export_proto(unpack1_char4
);
358 unpack1_char4 (gfc_array_char
*ret
,
359 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
360 const gfc_array_char
*vector
, const gfc_array_l1
*mask
,
361 const gfc_array_char
*field
, GFC_INTEGER_4 vector_length
,
362 GFC_INTEGER_4 field_length
)
364 unpack_internal (ret
, vector
, mask
, field
,
365 vector_length
* sizeof (gfc_char4_t
),
366 field_length
* sizeof (gfc_char4_t
));
370 extern void unpack0 (gfc_array_char
*, const gfc_array_char
*,
371 const gfc_array_l1
*, char *);
372 export_proto(unpack0
);
375 unpack0 (gfc_array_char
*ret
, const gfc_array_char
*vector
,
376 const gfc_array_l1
*mask
, char *field
)
380 index_type type_size
;
383 type_size
= GFC_DTYPE_TYPE_SIZE (vector
);
384 size
= GFC_DESCRIPTOR_SIZE (vector
);
388 case GFC_DTYPE_LOGICAL_1
:
389 case GFC_DTYPE_INTEGER_1
:
390 case GFC_DTYPE_DERIVED_1
:
391 unpack0_i1 ((gfc_array_i1
*) ret
, (gfc_array_i1
*) vector
,
392 mask
, (GFC_INTEGER_1
*) field
);
395 case GFC_DTYPE_LOGICAL_2
:
396 case GFC_DTYPE_INTEGER_2
:
397 unpack0_i2 ((gfc_array_i2
*) ret
, (gfc_array_i2
*) vector
,
398 mask
, (GFC_INTEGER_2
*) field
);
401 case GFC_DTYPE_LOGICAL_4
:
402 case GFC_DTYPE_INTEGER_4
:
403 unpack0_i4 ((gfc_array_i4
*) ret
, (gfc_array_i4
*) vector
,
404 mask
, (GFC_INTEGER_4
*) field
);
407 case GFC_DTYPE_LOGICAL_8
:
408 case GFC_DTYPE_INTEGER_8
:
409 unpack0_i8 ((gfc_array_i8
*) ret
, (gfc_array_i8
*) vector
,
410 mask
, (GFC_INTEGER_8
*) field
);
413 #ifdef HAVE_GFC_INTEGER_16
414 case GFC_DTYPE_LOGICAL_16
:
415 case GFC_DTYPE_INTEGER_16
:
416 unpack0_i16 ((gfc_array_i16
*) ret
, (gfc_array_i16
*) vector
,
417 mask
, (GFC_INTEGER_16
*) field
);
420 case GFC_DTYPE_REAL_4
:
421 unpack0_r4 ((gfc_array_r4
*) ret
, (gfc_array_r4
*) vector
,
422 mask
, (GFC_REAL_4
*) field
);
425 case GFC_DTYPE_REAL_8
:
426 unpack0_r8 ((gfc_array_r8
*) ret
, (gfc_array_r8
*) vector
,
427 mask
, (GFC_REAL_8
*) field
);
430 #ifdef HAVE_GFC_REAL_10
431 case GFC_DTYPE_REAL_10
:
432 unpack0_r10 ((gfc_array_r10
*) ret
, (gfc_array_r10
*) vector
,
433 mask
, (GFC_REAL_10
*) field
);
437 #ifdef HAVE_GFC_REAL_16
438 case GFC_DTYPE_REAL_16
:
439 unpack0_r16 ((gfc_array_r16
*) ret
, (gfc_array_r16
*) vector
,
440 mask
, (GFC_REAL_16
*) field
);
444 case GFC_DTYPE_COMPLEX_4
:
445 unpack0_c4 ((gfc_array_c4
*) ret
, (gfc_array_c4
*) vector
,
446 mask
, (GFC_COMPLEX_4
*) field
);
449 case GFC_DTYPE_COMPLEX_8
:
450 unpack0_c8 ((gfc_array_c8
*) ret
, (gfc_array_c8
*) vector
,
451 mask
, (GFC_COMPLEX_8
*) field
);
454 #ifdef HAVE_GFC_COMPLEX_10
455 case GFC_DTYPE_COMPLEX_10
:
456 unpack0_c10 ((gfc_array_c10
*) ret
, (gfc_array_c10
*) vector
,
457 mask
, (GFC_COMPLEX_10
*) field
);
461 #ifdef HAVE_GFC_COMPLEX_16
462 case GFC_DTYPE_COMPLEX_16
:
463 unpack0_c16 ((gfc_array_c16
*) ret
, (gfc_array_c16
*) vector
,
464 mask
, (GFC_COMPLEX_16
*) field
);
467 case GFC_DTYPE_DERIVED_2
:
468 if (GFC_UNALIGNED_2(ret
->data
) || GFC_UNALIGNED_2(vector
->data
)
469 || GFC_UNALIGNED_2(field
))
473 unpack0_i2 ((gfc_array_i2
*) ret
, (gfc_array_i2
*) vector
,
474 mask
, (GFC_INTEGER_2
*) field
);
478 case GFC_DTYPE_DERIVED_4
:
479 if (GFC_UNALIGNED_4(ret
->data
) || GFC_UNALIGNED_4(vector
->data
)
480 || GFC_UNALIGNED_4(field
))
484 unpack0_i4 ((gfc_array_i4
*) ret
, (gfc_array_i4
*) vector
,
485 mask
, (GFC_INTEGER_4
*) field
);
489 case GFC_DTYPE_DERIVED_8
:
490 if (GFC_UNALIGNED_8(ret
->data
) || GFC_UNALIGNED_8(vector
->data
)
491 || GFC_UNALIGNED_8(field
))
495 unpack0_i8 ((gfc_array_i8
*) ret
, (gfc_array_i8
*) vector
,
496 mask
, (GFC_INTEGER_8
*) field
);
499 #ifdef HAVE_GFC_INTEGER_16
500 case GFC_DTYPE_DERIVED_16
:
501 if (GFC_UNALIGNED_16(ret
->data
) || GFC_UNALIGNED_16(vector
->data
)
502 || GFC_UNALIGNED_16(field
))
506 unpack0_i16 ((gfc_array_i16
*) ret
, (gfc_array_i16
*) vector
,
507 mask
, (GFC_INTEGER_16
*) field
);
513 memset (&tmp
, 0, sizeof (tmp
));
516 unpack_internal (ret
, vector
, mask
, &tmp
, GFC_DESCRIPTOR_SIZE (vector
), 0);
520 extern void unpack0_char (gfc_array_char
*, GFC_INTEGER_4
,
521 const gfc_array_char
*, const gfc_array_l1
*,
522 char *, GFC_INTEGER_4
, GFC_INTEGER_4
);
523 export_proto(unpack0_char
);
526 unpack0_char (gfc_array_char
*ret
,
527 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
528 const gfc_array_char
*vector
, const gfc_array_l1
*mask
,
529 char *field
, GFC_INTEGER_4 vector_length
,
530 GFC_INTEGER_4 field_length
__attribute__((unused
)))
534 memset (&tmp
, 0, sizeof (tmp
));
537 unpack_internal (ret
, vector
, mask
, &tmp
, vector_length
, 0);
541 extern void unpack0_char4 (gfc_array_char
*, GFC_INTEGER_4
,
542 const gfc_array_char
*, const gfc_array_l1
*,
543 char *, GFC_INTEGER_4
, GFC_INTEGER_4
);
544 export_proto(unpack0_char4
);
547 unpack0_char4 (gfc_array_char
*ret
,
548 GFC_INTEGER_4 ret_length
__attribute__((unused
)),
549 const gfc_array_char
*vector
, const gfc_array_l1
*mask
,
550 char *field
, GFC_INTEGER_4 vector_length
,
551 GFC_INTEGER_4 field_length
__attribute__((unused
)))
555 memset (&tmp
, 0, sizeof (tmp
));
558 unpack_internal (ret
, vector
, mask
, &tmp
,
559 vector_length
* sizeof (gfc_char4_t
), 0);