/* Specific implementation of the PACK intrinsic
- Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Paul Brook <paul@nowt.org>
This file is part of the GNU Fortran 95 runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
-version 2 of the License, or (at your option) any later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file. (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
+version 3 of the License, or (at your option) any later version.
Ligbfortran is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-You should have received a copy of the GNU General Public
-License along with libgfortran; see the file COPYING. If not,
-write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
#include "libgfortran.h"
#include <stdlib.h>
{
/* r.* indicates the return array. */
index_type rstride0;
- GFC_COMPLEX_8 *rptr;
+ GFC_COMPLEX_8 * restrict rptr;
/* s.* indicates the source array. */
index_type sstride[GFC_MAX_DIMENSIONS];
index_type sstride0;
for (n = 0; n < dim; n++)
{
count[n] = 0;
- extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+ extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
if (extent[n] <= 0)
zero_sized = 1;
- sstride[n] = array->dim[n].stride;
- mstride[n] = mask->dim[n].stride * mask_kind;
+ sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
+ mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
}
if (sstride[0] == 0)
sstride[0] = 1;
else
sptr = array->data;
- if (ret->data == NULL || compile_options.bounds_check)
+ if (ret->data == NULL || unlikely (compile_options.bounds_check))
{
/* Count the elements, either for allocating memory or
for bounds checking. */
{
/* The return array will have as many
elements as there are in VECTOR. */
- total = vector->dim[0].ubound + 1 - vector->dim[0].lbound;
+ total = GFC_DESCRIPTOR_EXTENT(vector,0);
if (total < 0)
{
total = 0;
}
}
else
- {
- /* We have to count the true elements in MASK. */
-
- /* TODO: We could speed up pack easily in the case of only
- few .TRUE. entries in MASK, by keeping track of where we
- would be in the source array during the initial traversal
- of MASK, and caching the pointers to those elements. Then,
- supposed the number of elements is small enough, we would
- only have to traverse the list, and copy those elements
- into the result array. In the case of datatypes which fit
- in one of the integer types we could also cache the
- value instead of a pointer to it.
- This approach might be bad from the point of view of
- cache behavior in the case where our cache is not big
- enough to hold all elements that have to be copied. */
-
- const GFC_LOGICAL_1 *m = mptr;
-
- total = 0;
- if (zero_sized)
- m = NULL;
-
- while (m)
- {
- /* Test this element. */
- if (*m)
- total++;
-
- /* Advance to the next element. */
- m += mstride[0];
- count[0]++;
- n = 0;
- while (count[n] == extent[n])
- {
- /* When we get to the end of a dimension, reset it
- and increment the next dimension. */
- count[n] = 0;
- /* We could precalculate this product, but this is a
- less frequently used path so probably not worth
- it. */
- m -= mstride[n] * extent[n];
- n++;
- if (n >= dim)
- {
- /* Break out of the loop. */
- m = NULL;
- break;
- }
- else
- {
- count[n]++;
- m += mstride[n];
- }
- }
- }
- }
+ {
+ /* We have to count the true elements in MASK. */
+ total = count_0 (mask);
+ }
if (ret->data == NULL)
{
/* Setup the array descriptor. */
- ret->dim[0].lbound = 0;
- ret->dim[0].ubound = total - 1;
- ret->dim[0].stride = 1;
+ GFC_DIMENSION_SET(ret->dim[0], 0, total-1, 1);
ret->offset = 0;
if (total == 0)
/* We come here because of range checking. */
index_type ret_extent;
- ret_extent = ret->dim[0].ubound + 1 - ret->dim[0].lbound;
+ ret_extent = GFC_DESCRIPTOR_EXTENT(ret,0);
if (total != ret_extent)
runtime_error ("Incorrect extent in return value of PACK intrinsic;"
" is %ld, should be %ld", (long int) total,
}
}
- rstride0 = ret->dim[0].stride;
+ rstride0 = GFC_DESCRIPTOR_STRIDE(ret,0);
if (rstride0 == 0)
rstride0 = 1;
sstride0 = sstride[0];
/* Add any remaining elements from VECTOR. */
if (vector)
{
- n = vector->dim[0].ubound + 1 - vector->dim[0].lbound;
+ n = GFC_DESCRIPTOR_EXTENT(vector,0);
nelem = ((rptr - ret->data) / rstride0);
if (n > nelem)
{
- sstride0 = vector->dim[0].stride;
+ sstride0 = GFC_DESCRIPTOR_STRIDE(vector,0);
if (sstride0 == 0)
sstride0 = 1;