1/* Helper function for repacking arrays.
2   Copyright (C) 2003-2020 Free Software Foundation, Inc.
3   Contributed by Paul Brook <paul@nowt.org>
4
5This file is part of the GNU Fortran runtime library (libgfortran).
6
7Libgfortran is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public
9License as published by the Free Software Foundation; either
10version 3 of the License, or (at your option) any later version.
11
12Libgfortran is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24<http://www.gnu.org/licenses/>.  */
25
26#include "libgfortran.h"
27#include <string.h>
28
29
30#if defined (HAVE_GFC_INTEGER_4)
31
32void
33internal_unpack_4 (gfc_array_i4 * d, const GFC_INTEGER_4 * src)
34{
35  index_type count[GFC_MAX_DIMENSIONS];
36  index_type extent[GFC_MAX_DIMENSIONS];
37  index_type stride[GFC_MAX_DIMENSIONS];
38  index_type stride0;
39  index_type dim;
40  index_type dsize;
41  GFC_INTEGER_4 * restrict dest;
42
43  dest = d->base_addr;
44  if (src == dest || !src)
45    return;
46
47  dim = GFC_DESCRIPTOR_RANK (d);
48  dsize = 1;
49  for (index_type n = 0; n < dim; n++)
50    {
51      count[n] = 0;
52      stride[n] = GFC_DESCRIPTOR_STRIDE(d,n);
53      extent[n] = GFC_DESCRIPTOR_EXTENT(d,n);
54      if (extent[n] <= 0)
55	return;
56
57      if (dsize == stride[n])
58	dsize *= extent[n];
59      else
60	dsize = 0;
61    }
62
63  if (dsize != 0)
64    {
65      memcpy (dest, src, dsize * sizeof (GFC_INTEGER_4));
66      return;
67    }
68
69  stride0 = stride[0];
70
71  while (dest)
72    {
73      /* Copy the data.  */
74      *dest = *(src++);
75      /* Advance to the next element.  */
76      dest += stride0;
77      count[0]++;
78      /* Advance to the next source element.  */
79      index_type n = 0;
80      while (count[n] == extent[n])
81        {
82          /* When we get to the end of a dimension, reset it and increment
83             the next dimension.  */
84          count[n] = 0;
85          /* We could precalculate these products, but this is a less
86             frequently used path so probably not worth it.  */
87          dest -= stride[n] * extent[n];
88          n++;
89          if (n == dim)
90            {
91              dest = NULL;
92              break;
93            }
94          else
95            {
96              count[n]++;
97              dest += stride[n];
98            }
99        }
100    }
101}
102
103#endif
104
105