Home | History | Annotate | Line # | Download | only in m4
      1      1.1  mrg `/* Helper function for repacking arrays.
      2  1.1.1.3  mrg    Copyright (C) 2003-2022 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Paul Brook <paul (a] nowt.org>
      4      1.1  mrg 
      5      1.1  mrg This file is part of the GNU Fortran runtime library (libgfortran).
      6      1.1  mrg 
      7      1.1  mrg Libgfortran is free software; you can redistribute it and/or
      8      1.1  mrg modify it under the terms of the GNU General Public
      9      1.1  mrg License as published by the Free Software Foundation; either
     10      1.1  mrg version 3 of the License, or (at your option) any later version.
     11      1.1  mrg 
     12      1.1  mrg Libgfortran is distributed in the hope that it will be useful,
     13      1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1  mrg GNU General Public License for more details.
     16      1.1  mrg 
     17      1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     18      1.1  mrg permissions described in the GCC Runtime Library Exception, version
     19      1.1  mrg 3.1, as published by the Free Software Foundation.
     20      1.1  mrg 
     21      1.1  mrg You should have received a copy of the GNU General Public License and
     22      1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     23      1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24      1.1  mrg <http://www.gnu.org/licenses/>.  */
     25      1.1  mrg 
     26      1.1  mrg #include "libgfortran.h"'
     27      1.1  mrg 
     28      1.1  mrg include(iparm.m4)dnl
     29      1.1  mrg 
     30      1.1  mrg `#if defined (HAVE_'rtype_name`)
     31      1.1  mrg 
     32      1.1  mrg /* Allocates a block of memory with internal_malloc if the array needs
     33      1.1  mrg    repacking.  */
     34      1.1  mrg '
     35      1.1  mrg dnl The kind (ie size) is used to name the function for logicals, integers
     36      1.1  mrg dnl and reals.  For complex, it's c4 or c8.
     37      1.1  mrg rtype_name` *
     38      1.1  mrg internal_pack_'rtype_ccode` ('rtype` * source)
     39      1.1  mrg {
     40      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     41      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     42      1.1  mrg   index_type stride[GFC_MAX_DIMENSIONS];
     43      1.1  mrg   index_type stride0;
     44      1.1  mrg   index_type dim;
     45      1.1  mrg   index_type ssize;
     46      1.1  mrg   const 'rtype_name` *src;
     47      1.1  mrg   'rtype_name` * restrict dest;
     48      1.1  mrg   'rtype_name` *destptr;
     49      1.1  mrg   int packed;
     50      1.1  mrg 
     51      1.1  mrg   /* TODO: Investigate how we can figure out if this is a temporary
     52      1.1  mrg      since the stride=0 thing has been removed from the frontend.  */
     53      1.1  mrg 
     54      1.1  mrg   dim = GFC_DESCRIPTOR_RANK (source);
     55      1.1  mrg   ssize = 1;
     56      1.1  mrg   packed = 1;
     57      1.1  mrg   for (index_type n = 0; n < dim; n++)
     58      1.1  mrg     {
     59      1.1  mrg       count[n] = 0;
     60      1.1  mrg       stride[n] = GFC_DESCRIPTOR_STRIDE(source,n);
     61      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(source,n);
     62      1.1  mrg       if (extent[n] <= 0)
     63      1.1  mrg         {
     64      1.1  mrg           /* Do nothing.  */
     65      1.1  mrg           packed = 1;
     66      1.1  mrg           break;
     67      1.1  mrg         }
     68      1.1  mrg 
     69      1.1  mrg       if (ssize != stride[n])
     70      1.1  mrg         packed = 0;
     71      1.1  mrg 
     72      1.1  mrg       ssize *= extent[n];
     73      1.1  mrg     }
     74      1.1  mrg 
     75      1.1  mrg   if (packed)
     76      1.1  mrg     return source->base_addr;
     77      1.1  mrg 
     78      1.1  mrg   /* Allocate storage for the destination.  */
     79      1.1  mrg   destptr = xmallocarray (ssize, sizeof ('rtype_name`));
     80      1.1  mrg   dest = destptr;
     81      1.1  mrg   src = source->base_addr;
     82      1.1  mrg   stride0 = stride[0];
     83      1.1  mrg 
     84      1.1  mrg 
     85      1.1  mrg   while (src)
     86      1.1  mrg     {
     87      1.1  mrg       /* Copy the data.  */
     88      1.1  mrg       *(dest++) = *src;
     89      1.1  mrg       /* Advance to the next element.  */
     90      1.1  mrg       src += stride0;
     91      1.1  mrg       count[0]++;
     92      1.1  mrg       /* Advance to the next source element.  */
     93      1.1  mrg       index_type n = 0;
     94      1.1  mrg       while (count[n] == extent[n])
     95      1.1  mrg         {
     96      1.1  mrg           /* When we get to the end of a dimension, reset it and increment
     97      1.1  mrg              the next dimension.  */
     98      1.1  mrg           count[n] = 0;
     99      1.1  mrg           /* We could precalculate these products, but this is a less
    100      1.1  mrg              frequently used path so probably not worth it.  */
    101      1.1  mrg           src -= stride[n] * extent[n];
    102      1.1  mrg           n++;
    103      1.1  mrg           if (n == dim)
    104      1.1  mrg             {
    105      1.1  mrg               src = NULL;
    106      1.1  mrg               break;
    107      1.1  mrg             }
    108      1.1  mrg           else
    109      1.1  mrg             {
    110      1.1  mrg               count[n]++;
    111      1.1  mrg               src += stride[n];
    112      1.1  mrg             }
    113      1.1  mrg         }
    114      1.1  mrg     }
    115      1.1  mrg   return destptr;
    116      1.1  mrg }
    117      1.1  mrg 
    118      1.1  mrg #endif
    119      1.1  mrg '
    120