Home | History | Annotate | Line # | Download | only in intrinsics
      1      1.1  mrg /* Generic implementation of the SPREAD intrinsic
      2  1.1.1.4  mrg    Copyright (C) 2002-2024 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by Paul Brook <paul (at) 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 Ligbfortran 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 #include <string.h>
     28      1.1  mrg 
     29      1.1  mrg static void
     30      1.1  mrg spread_internal (gfc_array_char *ret, const gfc_array_char *source,
     31      1.1  mrg 		 const index_type *along, const index_type *pncopies)
     32      1.1  mrg {
     33      1.1  mrg   /* r.* indicates the return array.  */
     34      1.1  mrg   index_type rstride[GFC_MAX_DIMENSIONS];
     35      1.1  mrg   index_type rstride0;
     36      1.1  mrg   index_type rdelta = 0;
     37      1.1  mrg   index_type rrank;
     38      1.1  mrg   index_type rs;
     39      1.1  mrg   char *rptr;
     40      1.1  mrg   char *dest;
     41      1.1  mrg   /* s.* indicates the source array.  */
     42      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     43      1.1  mrg   index_type sstride0;
     44      1.1  mrg   index_type srank;
     45      1.1  mrg   const char *sptr;
     46      1.1  mrg 
     47      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     48      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     49      1.1  mrg   index_type n;
     50      1.1  mrg   index_type dim;
     51      1.1  mrg   index_type ncopies;
     52      1.1  mrg   index_type size;
     53      1.1  mrg 
     54      1.1  mrg   size = GFC_DESCRIPTOR_SIZE(source);
     55      1.1  mrg 
     56      1.1  mrg   srank = GFC_DESCRIPTOR_RANK(source);
     57      1.1  mrg 
     58  1.1.1.4  mrg   sstride[0] = 0; /* Avoid warnings if not initialized.  */
     59  1.1.1.4  mrg 
     60      1.1  mrg   rrank = srank + 1;
     61      1.1  mrg   if (rrank > GFC_MAX_DIMENSIONS)
     62      1.1  mrg     runtime_error ("return rank too large in spread()");
     63      1.1  mrg 
     64      1.1  mrg   if (*along > rrank)
     65      1.1  mrg       runtime_error ("dim outside of rank in spread()");
     66      1.1  mrg 
     67      1.1  mrg   ncopies = *pncopies;
     68      1.1  mrg 
     69      1.1  mrg   if (ret->base_addr == NULL)
     70      1.1  mrg     {
     71      1.1  mrg       /* The front end has signalled that we need to populate the
     72      1.1  mrg 	 return array descriptor.  */
     73      1.1  mrg 
     74      1.1  mrg       size_t ub, stride;
     75      1.1  mrg 
     76      1.1  mrg       ret->dtype.rank = rrank;
     77      1.1  mrg 
     78      1.1  mrg       dim = 0;
     79      1.1  mrg       rs = 1;
     80      1.1  mrg       for (n = 0; n < rrank; n++)
     81      1.1  mrg 	{
     82      1.1  mrg 	  stride = rs;
     83      1.1  mrg 	  if (n == *along - 1)
     84      1.1  mrg 	    {
     85      1.1  mrg 	      ub = ncopies - 1;
     86      1.1  mrg 	      rdelta = rs * size;
     87      1.1  mrg 	      rs *= ncopies;
     88      1.1  mrg 	    }
     89      1.1  mrg 	  else
     90      1.1  mrg 	    {
     91      1.1  mrg 	      count[dim] = 0;
     92      1.1  mrg 	      extent[dim] = GFC_DESCRIPTOR_EXTENT(source,dim);
     93      1.1  mrg 	      sstride[dim] = GFC_DESCRIPTOR_STRIDE_BYTES(source,dim);
     94      1.1  mrg 	      rstride[dim] = rs * size;
     95      1.1  mrg 
     96      1.1  mrg 	      ub = extent[dim]-1;
     97      1.1  mrg 	      rs *= extent[dim];
     98      1.1  mrg 	      dim++;
     99      1.1  mrg 	    }
    100      1.1  mrg 
    101      1.1  mrg 	  GFC_DIMENSION_SET(ret->dim[n], 0, ub, stride);
    102      1.1  mrg 	}
    103      1.1  mrg       ret->offset = 0;
    104      1.1  mrg       ret->base_addr = xmallocarray (rs, size);
    105      1.1  mrg 
    106      1.1  mrg       if (rs <= 0)
    107      1.1  mrg 	return;
    108      1.1  mrg     }
    109      1.1  mrg   else
    110      1.1  mrg     {
    111      1.1  mrg       int zero_sized;
    112      1.1  mrg 
    113      1.1  mrg       zero_sized = 0;
    114      1.1  mrg 
    115      1.1  mrg       dim = 0;
    116      1.1  mrg       if (GFC_DESCRIPTOR_RANK(ret) != rrank)
    117      1.1  mrg 	runtime_error ("rank mismatch in spread()");
    118      1.1  mrg 
    119      1.1  mrg       if (compile_options.bounds_check)
    120      1.1  mrg 	{
    121      1.1  mrg 	  for (n = 0; n < rrank; n++)
    122      1.1  mrg 	    {
    123      1.1  mrg 	      index_type ret_extent;
    124      1.1  mrg 
    125      1.1  mrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(ret,n);
    126      1.1  mrg 	      if (n == *along - 1)
    127      1.1  mrg 		{
    128      1.1  mrg 		  rdelta = GFC_DESCRIPTOR_STRIDE_BYTES(ret,n);
    129      1.1  mrg 
    130      1.1  mrg 		  if (ret_extent != ncopies)
    131      1.1  mrg 		    runtime_error("Incorrect extent in return value of SPREAD"
    132      1.1  mrg 				  " intrinsic in dimension %ld: is %ld,"
    133      1.1  mrg 				  " should be %ld", (long int) n+1,
    134      1.1  mrg 				  (long int) ret_extent, (long int) ncopies);
    135      1.1  mrg 		}
    136      1.1  mrg 	      else
    137      1.1  mrg 		{
    138      1.1  mrg 		  count[dim] = 0;
    139      1.1  mrg 		  extent[dim] = GFC_DESCRIPTOR_EXTENT(source,dim);
    140      1.1  mrg 		  if (ret_extent != extent[dim])
    141      1.1  mrg 		    runtime_error("Incorrect extent in return value of SPREAD"
    142      1.1  mrg 				  " intrinsic in dimension %ld: is %ld,"
    143      1.1  mrg 				  " should be %ld", (long int) n+1,
    144      1.1  mrg 				  (long int) ret_extent,
    145      1.1  mrg 				  (long int) extent[dim]);
    146      1.1  mrg 
    147      1.1  mrg 		  if (extent[dim] <= 0)
    148      1.1  mrg 		    zero_sized = 1;
    149      1.1  mrg 		  sstride[dim] = GFC_DESCRIPTOR_STRIDE_BYTES(source,dim);
    150      1.1  mrg 		  rstride[dim] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,n);
    151      1.1  mrg 		  dim++;
    152      1.1  mrg 		}
    153      1.1  mrg 	    }
    154      1.1  mrg 	}
    155      1.1  mrg       else
    156      1.1  mrg 	{
    157      1.1  mrg 	  for (n = 0; n < rrank; n++)
    158      1.1  mrg 	    {
    159      1.1  mrg 	      if (n == *along - 1)
    160      1.1  mrg 		{
    161      1.1  mrg 		  rdelta = GFC_DESCRIPTOR_STRIDE_BYTES(ret,n);
    162      1.1  mrg 		}
    163      1.1  mrg 	      else
    164      1.1  mrg 		{
    165      1.1  mrg 		  count[dim] = 0;
    166      1.1  mrg 		  extent[dim] = GFC_DESCRIPTOR_EXTENT(source,dim);
    167      1.1  mrg 		  if (extent[dim] <= 0)
    168      1.1  mrg 		    zero_sized = 1;
    169      1.1  mrg 		  sstride[dim] = GFC_DESCRIPTOR_STRIDE_BYTES(source,dim);
    170      1.1  mrg 		  rstride[dim] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,n);
    171      1.1  mrg 		  dim++;
    172      1.1  mrg 		}
    173      1.1  mrg 	    }
    174      1.1  mrg 	}
    175      1.1  mrg 
    176      1.1  mrg       if (zero_sized)
    177      1.1  mrg 	return;
    178      1.1  mrg 
    179      1.1  mrg       if (sstride[0] == 0)
    180      1.1  mrg 	sstride[0] = size;
    181      1.1  mrg     }
    182      1.1  mrg   sstride0 = sstride[0];
    183      1.1  mrg   rstride0 = rstride[0];
    184      1.1  mrg   rptr = ret->base_addr;
    185      1.1  mrg   sptr = source->base_addr;
    186      1.1  mrg 
    187      1.1  mrg   while (sptr)
    188      1.1  mrg     {
    189      1.1  mrg       /* Spread this element.  */
    190      1.1  mrg       dest = rptr;
    191      1.1  mrg       for (n = 0; n < ncopies; n++)
    192      1.1  mrg         {
    193      1.1  mrg           memcpy (dest, sptr, size);
    194      1.1  mrg           dest += rdelta;
    195      1.1  mrg         }
    196      1.1  mrg       /* Advance to the next element.  */
    197      1.1  mrg       sptr += sstride0;
    198      1.1  mrg       rptr += rstride0;
    199      1.1  mrg       count[0]++;
    200      1.1  mrg       n = 0;
    201      1.1  mrg       while (count[n] == extent[n])
    202      1.1  mrg         {
    203      1.1  mrg           /* When we get to the end of a dimension, reset it and increment
    204      1.1  mrg              the next dimension.  */
    205      1.1  mrg           count[n] = 0;
    206      1.1  mrg           /* We could precalculate these products, but this is a less
    207      1.1  mrg              frequently used path so probably not worth it.  */
    208      1.1  mrg           sptr -= sstride[n] * extent[n];
    209      1.1  mrg           rptr -= rstride[n] * extent[n];
    210      1.1  mrg           n++;
    211      1.1  mrg           if (n >= srank)
    212      1.1  mrg             {
    213      1.1  mrg               /* Break out of the loop.  */
    214      1.1  mrg               sptr = NULL;
    215      1.1  mrg               break;
    216      1.1  mrg             }
    217      1.1  mrg           else
    218      1.1  mrg             {
    219      1.1  mrg               count[n]++;
    220      1.1  mrg               sptr += sstride[n];
    221      1.1  mrg               rptr += rstride[n];
    222      1.1  mrg             }
    223      1.1  mrg         }
    224      1.1  mrg     }
    225      1.1  mrg }
    226      1.1  mrg 
    227      1.1  mrg /* This version of spread_internal treats the special case of a scalar
    228      1.1  mrg    source.  This is much simpler than the more general case above.  */
    229      1.1  mrg 
    230      1.1  mrg static void
    231      1.1  mrg spread_internal_scalar (gfc_array_char *ret, const char *source,
    232      1.1  mrg 			const index_type *along, const index_type *pncopies)
    233      1.1  mrg {
    234      1.1  mrg   int n;
    235      1.1  mrg   int ncopies = *pncopies;
    236      1.1  mrg   char * dest;
    237      1.1  mrg   size_t size;
    238      1.1  mrg 
    239      1.1  mrg   size = GFC_DESCRIPTOR_SIZE(ret);
    240      1.1  mrg 
    241      1.1  mrg   if (GFC_DESCRIPTOR_RANK (ret) != 1)
    242      1.1  mrg     runtime_error ("incorrect destination rank in spread()");
    243      1.1  mrg 
    244      1.1  mrg   if (*along > 1)
    245      1.1  mrg     runtime_error ("dim outside of rank in spread()");
    246      1.1  mrg 
    247      1.1  mrg   if (ret->base_addr == NULL)
    248      1.1  mrg     {
    249      1.1  mrg       ret->base_addr = xmallocarray (ncopies, size);
    250      1.1  mrg       ret->offset = 0;
    251      1.1  mrg       GFC_DIMENSION_SET(ret->dim[0], 0, ncopies - 1, 1);
    252      1.1  mrg     }
    253      1.1  mrg   else
    254      1.1  mrg     {
    255      1.1  mrg       if (ncopies - 1 > (GFC_DESCRIPTOR_EXTENT(ret,0)  - 1)
    256      1.1  mrg 			   / GFC_DESCRIPTOR_STRIDE(ret,0))
    257      1.1  mrg 	runtime_error ("dim too large in spread()");
    258      1.1  mrg     }
    259      1.1  mrg 
    260      1.1  mrg   for (n = 0; n < ncopies; n++)
    261      1.1  mrg     {
    262      1.1  mrg       dest = (char*)(ret->base_addr + n * GFC_DESCRIPTOR_STRIDE_BYTES(ret,0));
    263      1.1  mrg       memcpy (dest , source, size);
    264      1.1  mrg     }
    265      1.1  mrg }
    266      1.1  mrg 
    267      1.1  mrg extern void spread (gfc_array_char *, const gfc_array_char *,
    268      1.1  mrg 		    const index_type *, const index_type *);
    269      1.1  mrg export_proto(spread);
    270      1.1  mrg 
    271      1.1  mrg void
    272      1.1  mrg spread (gfc_array_char *ret, const gfc_array_char *source,
    273      1.1  mrg 	const index_type *along, const index_type *pncopies)
    274      1.1  mrg {
    275      1.1  mrg   index_type type_size;
    276      1.1  mrg 
    277      1.1  mrg   type_size = GFC_DTYPE_TYPE_SIZE(ret);
    278      1.1  mrg   switch(type_size)
    279      1.1  mrg     {
    280      1.1  mrg     case GFC_DTYPE_LOGICAL_1:
    281      1.1  mrg     case GFC_DTYPE_INTEGER_1:
    282      1.1  mrg       spread_i1 ((gfc_array_i1 *) ret, (gfc_array_i1 *) source,
    283      1.1  mrg 		 *along, *pncopies);
    284      1.1  mrg       return;
    285      1.1  mrg 
    286      1.1  mrg     case GFC_DTYPE_LOGICAL_2:
    287      1.1  mrg     case GFC_DTYPE_INTEGER_2:
    288      1.1  mrg       spread_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) source,
    289      1.1  mrg 		 *along, *pncopies);
    290      1.1  mrg       return;
    291      1.1  mrg 
    292      1.1  mrg     case GFC_DTYPE_LOGICAL_4:
    293      1.1  mrg     case GFC_DTYPE_INTEGER_4:
    294      1.1  mrg       spread_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) source,
    295      1.1  mrg 		 *along, *pncopies);
    296      1.1  mrg       return;
    297      1.1  mrg 
    298      1.1  mrg     case GFC_DTYPE_LOGICAL_8:
    299      1.1  mrg     case GFC_DTYPE_INTEGER_8:
    300      1.1  mrg       spread_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) source,
    301      1.1  mrg 		 *along, *pncopies);
    302      1.1  mrg       return;
    303      1.1  mrg 
    304      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
    305      1.1  mrg     case GFC_DTYPE_LOGICAL_16:
    306      1.1  mrg     case GFC_DTYPE_INTEGER_16:
    307      1.1  mrg       spread_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) source,
    308      1.1  mrg 		 *along, *pncopies);
    309      1.1  mrg       return;
    310      1.1  mrg #endif
    311      1.1  mrg 
    312      1.1  mrg     case GFC_DTYPE_REAL_4:
    313      1.1  mrg       spread_r4 ((gfc_array_r4 *) ret, (gfc_array_r4 *) source,
    314      1.1  mrg 		 *along, *pncopies);
    315      1.1  mrg       return;
    316      1.1  mrg 
    317      1.1  mrg     case GFC_DTYPE_REAL_8:
    318      1.1  mrg       spread_r8 ((gfc_array_r8 *) ret, (gfc_array_r8 *) source,
    319      1.1  mrg 		 *along, *pncopies);
    320      1.1  mrg       return;
    321      1.1  mrg 
    322      1.1  mrg /* FIXME: This here is a hack, which will have to be removed when
    323      1.1  mrg    the array descriptor is reworked.  Currently, we don't store the
    324      1.1  mrg    kind value for the type, but only the size.  Because on targets with
    325  1.1.1.4  mrg    _Float128, we have sizeof(long double) == sizeof(_Float128),
    326      1.1  mrg    we cannot discriminate here and have to fall back to the generic
    327      1.1  mrg    handling (which is suboptimal).  */
    328      1.1  mrg #if !defined(GFC_REAL_16_IS_FLOAT128)
    329      1.1  mrg # ifdef GFC_HAVE_REAL_10
    330      1.1  mrg     case GFC_DTYPE_REAL_10:
    331      1.1  mrg       spread_r10 ((gfc_array_r10 *) ret, (gfc_array_r10 *) source,
    332      1.1  mrg 		 *along, *pncopies);
    333      1.1  mrg       return;
    334      1.1  mrg # endif
    335      1.1  mrg 
    336      1.1  mrg # ifdef GFC_HAVE_REAL_16
    337      1.1  mrg     case GFC_DTYPE_REAL_16:
    338      1.1  mrg       spread_r16 ((gfc_array_r16 *) ret, (gfc_array_r16 *) source,
    339      1.1  mrg 		 *along, *pncopies);
    340      1.1  mrg       return;
    341      1.1  mrg # endif
    342      1.1  mrg #endif
    343      1.1  mrg 
    344      1.1  mrg     case GFC_DTYPE_COMPLEX_4:
    345      1.1  mrg       spread_c4 ((gfc_array_c4 *) ret, (gfc_array_c4 *) source,
    346      1.1  mrg 		 *along, *pncopies);
    347      1.1  mrg       return;
    348      1.1  mrg 
    349      1.1  mrg     case GFC_DTYPE_COMPLEX_8:
    350      1.1  mrg       spread_c8 ((gfc_array_c8 *) ret, (gfc_array_c8 *) source,
    351      1.1  mrg 		 *along, *pncopies);
    352      1.1  mrg       return;
    353      1.1  mrg 
    354      1.1  mrg /* FIXME: This here is a hack, which will have to be removed when
    355      1.1  mrg    the array descriptor is reworked.  Currently, we don't store the
    356      1.1  mrg    kind value for the type, but only the size.  Because on targets with
    357  1.1.1.4  mrg    _Float128, we have sizeof(long double) == sizeof(_Float128),
    358      1.1  mrg    we cannot discriminate here and have to fall back to the generic
    359      1.1  mrg    handling (which is suboptimal).  */
    360      1.1  mrg #if !defined(GFC_REAL_16_IS_FLOAT128)
    361      1.1  mrg # ifdef GFC_HAVE_COMPLEX_10
    362      1.1  mrg     case GFC_DTYPE_COMPLEX_10:
    363      1.1  mrg       spread_c10 ((gfc_array_c10 *) ret, (gfc_array_c10 *) source,
    364      1.1  mrg 		 *along, *pncopies);
    365      1.1  mrg       return;
    366      1.1  mrg # endif
    367      1.1  mrg 
    368      1.1  mrg # ifdef GFC_HAVE_COMPLEX_16
    369      1.1  mrg     case GFC_DTYPE_COMPLEX_16:
    370      1.1  mrg       spread_c16 ((gfc_array_c16 *) ret, (gfc_array_c16 *) source,
    371      1.1  mrg 		 *along, *pncopies);
    372      1.1  mrg       return;
    373      1.1  mrg # endif
    374      1.1  mrg #endif
    375      1.1  mrg 
    376      1.1  mrg     }
    377      1.1  mrg 
    378      1.1  mrg   switch (GFC_DESCRIPTOR_SIZE (ret))
    379      1.1  mrg     {
    380      1.1  mrg     case 1:
    381      1.1  mrg       spread_i1 ((gfc_array_i1 *) ret, (gfc_array_i1 *) source,
    382      1.1  mrg 		 *along, *pncopies);
    383      1.1  mrg       return;
    384      1.1  mrg 
    385      1.1  mrg     case 2:
    386      1.1  mrg       if (GFC_UNALIGNED_2(ret->base_addr) || GFC_UNALIGNED_2(source->base_addr))
    387      1.1  mrg 	break;
    388      1.1  mrg       else
    389      1.1  mrg 	{
    390      1.1  mrg 	  spread_i2 ((gfc_array_i2 *) ret, (gfc_array_i2 *) source,
    391      1.1  mrg 		     *along, *pncopies);
    392      1.1  mrg 	  return;
    393      1.1  mrg 	}
    394      1.1  mrg 
    395      1.1  mrg     case 4:
    396      1.1  mrg       if (GFC_UNALIGNED_4(ret->base_addr) || GFC_UNALIGNED_4(source->base_addr))
    397      1.1  mrg 	break;
    398      1.1  mrg       else
    399      1.1  mrg 	{
    400      1.1  mrg 	  spread_i4 ((gfc_array_i4 *) ret, (gfc_array_i4 *) source,
    401      1.1  mrg 		     *along, *pncopies);
    402      1.1  mrg 	  return;
    403      1.1  mrg 	}
    404      1.1  mrg 
    405      1.1  mrg     case 8:
    406      1.1  mrg       if (GFC_UNALIGNED_8(ret->base_addr) || GFC_UNALIGNED_8(source->base_addr))
    407      1.1  mrg 	break;
    408      1.1  mrg       else
    409      1.1  mrg 	{
    410      1.1  mrg 	  spread_i8 ((gfc_array_i8 *) ret, (gfc_array_i8 *) source,
    411      1.1  mrg 		     *along, *pncopies);
    412      1.1  mrg 	  return;
    413      1.1  mrg 	}
    414      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
    415      1.1  mrg     case 16:
    416      1.1  mrg       if (GFC_UNALIGNED_16(ret->base_addr)
    417      1.1  mrg 	  || GFC_UNALIGNED_16(source->base_addr))
    418      1.1  mrg 	break;
    419      1.1  mrg       else
    420      1.1  mrg 	{
    421      1.1  mrg 	  spread_i16 ((gfc_array_i16 *) ret, (gfc_array_i16 *) source,
    422      1.1  mrg 		      *along, *pncopies);
    423      1.1  mrg 	  return;
    424      1.1  mrg 	    }
    425      1.1  mrg #endif
    426      1.1  mrg 
    427      1.1  mrg     }
    428      1.1  mrg 
    429      1.1  mrg   spread_internal (ret, source, along, pncopies);
    430      1.1  mrg }
    431      1.1  mrg 
    432      1.1  mrg 
    433      1.1  mrg extern void spread_char (gfc_array_char *, GFC_INTEGER_4,
    434      1.1  mrg 			 const gfc_array_char *, const index_type *,
    435      1.1  mrg 			 const index_type *, GFC_INTEGER_4);
    436      1.1  mrg export_proto(spread_char);
    437      1.1  mrg 
    438      1.1  mrg void
    439      1.1  mrg spread_char (gfc_array_char *ret,
    440      1.1  mrg 	     GFC_INTEGER_4 ret_length __attribute__((unused)),
    441      1.1  mrg 	     const gfc_array_char *source, const index_type *along,
    442      1.1  mrg 	     const index_type *pncopies,
    443      1.1  mrg 	     GFC_INTEGER_4 source_length __attribute__((unused)))
    444      1.1  mrg {
    445      1.1  mrg   spread_internal (ret, source, along, pncopies);
    446      1.1  mrg }
    447      1.1  mrg 
    448      1.1  mrg 
    449      1.1  mrg extern void spread_char4 (gfc_array_char *, GFC_INTEGER_4,
    450      1.1  mrg 			  const gfc_array_char *, const index_type *,
    451      1.1  mrg 			  const index_type *, GFC_INTEGER_4);
    452      1.1  mrg export_proto(spread_char4);
    453      1.1  mrg 
    454      1.1  mrg void
    455      1.1  mrg spread_char4 (gfc_array_char *ret,
    456      1.1  mrg 	      GFC_INTEGER_4 ret_length __attribute__((unused)),
    457      1.1  mrg 	      const gfc_array_char *source, const index_type *along,
    458      1.1  mrg 	      const index_type *pncopies,
    459      1.1  mrg 	      GFC_INTEGER_4 source_length __attribute__((unused)))
    460      1.1  mrg {
    461      1.1  mrg   spread_internal (ret, source, along, pncopies);
    462      1.1  mrg }
    463      1.1  mrg 
    464      1.1  mrg 
    465      1.1  mrg /* The following are the prototypes for the versions of spread with a
    466      1.1  mrg    scalar source.  */
    467      1.1  mrg 
    468      1.1  mrg extern void spread_scalar (gfc_array_char *, const char *,
    469      1.1  mrg 			   const index_type *, const index_type *);
    470      1.1  mrg export_proto(spread_scalar);
    471      1.1  mrg 
    472      1.1  mrg void
    473      1.1  mrg spread_scalar (gfc_array_char *ret, const char *source,
    474      1.1  mrg 	       const index_type *along, const index_type *pncopies)
    475      1.1  mrg {
    476      1.1  mrg   index_type type_size;
    477      1.1  mrg 
    478      1.1  mrg   if (GFC_DTYPE_IS_UNSET(ret))
    479      1.1  mrg     runtime_error ("return array missing descriptor in spread()");
    480      1.1  mrg 
    481      1.1  mrg   type_size = GFC_DTYPE_TYPE_SIZE(ret);
    482      1.1  mrg   switch(type_size)
    483      1.1  mrg     {
    484      1.1  mrg     case GFC_DTYPE_LOGICAL_1:
    485      1.1  mrg     case GFC_DTYPE_INTEGER_1:
    486      1.1  mrg       spread_scalar_i1 ((gfc_array_i1 *) ret, (GFC_INTEGER_1 *) source,
    487      1.1  mrg 			*along, *pncopies);
    488      1.1  mrg       return;
    489      1.1  mrg 
    490      1.1  mrg     case GFC_DTYPE_LOGICAL_2:
    491      1.1  mrg     case GFC_DTYPE_INTEGER_2:
    492      1.1  mrg       spread_scalar_i2 ((gfc_array_i2 *) ret, (GFC_INTEGER_2 *) source,
    493      1.1  mrg 			*along, *pncopies);
    494      1.1  mrg       return;
    495      1.1  mrg 
    496      1.1  mrg     case GFC_DTYPE_LOGICAL_4:
    497      1.1  mrg     case GFC_DTYPE_INTEGER_4:
    498      1.1  mrg       spread_scalar_i4 ((gfc_array_i4 *) ret, (GFC_INTEGER_4 *) source,
    499      1.1  mrg 			*along, *pncopies);
    500      1.1  mrg       return;
    501      1.1  mrg 
    502      1.1  mrg     case GFC_DTYPE_LOGICAL_8:
    503      1.1  mrg     case GFC_DTYPE_INTEGER_8:
    504      1.1  mrg       spread_scalar_i8 ((gfc_array_i8 *) ret, (GFC_INTEGER_8 *) source,
    505      1.1  mrg 			*along, *pncopies);
    506      1.1  mrg       return;
    507      1.1  mrg 
    508      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
    509      1.1  mrg     case GFC_DTYPE_LOGICAL_16:
    510      1.1  mrg     case GFC_DTYPE_INTEGER_16:
    511      1.1  mrg       spread_scalar_i16 ((gfc_array_i16 *) ret, (GFC_INTEGER_16 *) source,
    512      1.1  mrg 			*along, *pncopies);
    513      1.1  mrg       return;
    514      1.1  mrg #endif
    515      1.1  mrg 
    516      1.1  mrg     case GFC_DTYPE_REAL_4:
    517      1.1  mrg       spread_scalar_r4 ((gfc_array_r4 *) ret, (GFC_REAL_4 *) source,
    518      1.1  mrg 			*along, *pncopies);
    519      1.1  mrg       return;
    520      1.1  mrg 
    521      1.1  mrg     case GFC_DTYPE_REAL_8:
    522      1.1  mrg       spread_scalar_r8 ((gfc_array_r8 *) ret, (GFC_REAL_8 *) source,
    523      1.1  mrg 			*along, *pncopies);
    524      1.1  mrg       return;
    525      1.1  mrg 
    526      1.1  mrg /* FIXME: This here is a hack, which will have to be removed when
    527      1.1  mrg    the array descriptor is reworked.  Currently, we don't store the
    528      1.1  mrg    kind value for the type, but only the size.  Because on targets with
    529  1.1.1.4  mrg    _Float128, we have sizeof(long double) == sizeof(_Float128),
    530      1.1  mrg    we cannot discriminate here and have to fall back to the generic
    531      1.1  mrg    handling (which is suboptimal).  */
    532      1.1  mrg #if !defined(GFC_REAL_16_IS_FLOAT128)
    533      1.1  mrg # ifdef HAVE_GFC_REAL_10
    534      1.1  mrg     case GFC_DTYPE_REAL_10:
    535      1.1  mrg       spread_scalar_r10 ((gfc_array_r10 *) ret, (GFC_REAL_10 *) source,
    536      1.1  mrg 			*along, *pncopies);
    537      1.1  mrg       return;
    538      1.1  mrg # endif
    539      1.1  mrg 
    540      1.1  mrg # ifdef HAVE_GFC_REAL_16
    541      1.1  mrg     case GFC_DTYPE_REAL_16:
    542      1.1  mrg       spread_scalar_r16 ((gfc_array_r16 *) ret, (GFC_REAL_16 *) source,
    543      1.1  mrg 			*along, *pncopies);
    544      1.1  mrg       return;
    545      1.1  mrg # endif
    546      1.1  mrg #endif
    547      1.1  mrg 
    548      1.1  mrg     case GFC_DTYPE_COMPLEX_4:
    549      1.1  mrg       spread_scalar_c4 ((gfc_array_c4 *) ret, (GFC_COMPLEX_4 *) source,
    550      1.1  mrg 			*along, *pncopies);
    551      1.1  mrg       return;
    552      1.1  mrg 
    553      1.1  mrg     case GFC_DTYPE_COMPLEX_8:
    554      1.1  mrg       spread_scalar_c8 ((gfc_array_c8 *) ret, (GFC_COMPLEX_8 *) source,
    555      1.1  mrg 			*along, *pncopies);
    556      1.1  mrg       return;
    557      1.1  mrg 
    558      1.1  mrg /* FIXME: This here is a hack, which will have to be removed when
    559      1.1  mrg    the array descriptor is reworked.  Currently, we don't store the
    560      1.1  mrg    kind value for the type, but only the size.  Because on targets with
    561  1.1.1.4  mrg    _Float128, we have sizeof(long double) == sizeof(_Float128),
    562      1.1  mrg    we cannot discriminate here and have to fall back to the generic
    563      1.1  mrg    handling (which is suboptimal).  */
    564      1.1  mrg #if !defined(GFC_REAL_16_IS_FLOAT128)
    565      1.1  mrg # ifdef HAVE_GFC_COMPLEX_10
    566      1.1  mrg     case GFC_DTYPE_COMPLEX_10:
    567      1.1  mrg       spread_scalar_c10 ((gfc_array_c10 *) ret, (GFC_COMPLEX_10 *) source,
    568      1.1  mrg 			*along, *pncopies);
    569      1.1  mrg       return;
    570      1.1  mrg # endif
    571      1.1  mrg 
    572      1.1  mrg # ifdef HAVE_GFC_COMPLEX_16
    573      1.1  mrg     case GFC_DTYPE_COMPLEX_16:
    574      1.1  mrg       spread_scalar_c16 ((gfc_array_c16 *) ret, (GFC_COMPLEX_16 *) source,
    575      1.1  mrg 			*along, *pncopies);
    576      1.1  mrg       return;
    577      1.1  mrg # endif
    578      1.1  mrg #endif
    579      1.1  mrg 
    580      1.1  mrg     }
    581      1.1  mrg 
    582      1.1  mrg   switch (GFC_DESCRIPTOR_SIZE(ret))
    583      1.1  mrg     {
    584      1.1  mrg     case 1:
    585      1.1  mrg       spread_scalar_i1 ((gfc_array_i1 *) ret, (GFC_INTEGER_1 *) source,
    586      1.1  mrg 			*along, *pncopies);
    587      1.1  mrg       return;
    588      1.1  mrg 
    589      1.1  mrg     case 2:
    590      1.1  mrg       if (GFC_UNALIGNED_2(ret->base_addr) || GFC_UNALIGNED_2(source))
    591      1.1  mrg 	break;
    592      1.1  mrg       else
    593      1.1  mrg 	{
    594      1.1  mrg 	  spread_scalar_i2 ((gfc_array_i2 *) ret, (GFC_INTEGER_2 *) source,
    595      1.1  mrg 			    *along, *pncopies);
    596      1.1  mrg 	  return;
    597      1.1  mrg 	}
    598      1.1  mrg 
    599      1.1  mrg     case 4:
    600      1.1  mrg       if (GFC_UNALIGNED_4(ret->base_addr) || GFC_UNALIGNED_4(source))
    601      1.1  mrg 	break;
    602      1.1  mrg       else
    603      1.1  mrg 	{
    604      1.1  mrg 	  spread_scalar_i4 ((gfc_array_i4 *) ret, (GFC_INTEGER_4 *) source,
    605      1.1  mrg 			    *along, *pncopies);
    606      1.1  mrg 	  return;
    607      1.1  mrg 	}
    608      1.1  mrg 
    609      1.1  mrg     case 8:
    610      1.1  mrg       if (GFC_UNALIGNED_8(ret->base_addr) || GFC_UNALIGNED_8(source))
    611      1.1  mrg 	break;
    612      1.1  mrg       else
    613      1.1  mrg 	{
    614      1.1  mrg 	  spread_scalar_i8 ((gfc_array_i8 *) ret, (GFC_INTEGER_8 *) source,
    615      1.1  mrg 			    *along, *pncopies);
    616      1.1  mrg 	  return;
    617      1.1  mrg 	}
    618      1.1  mrg #ifdef HAVE_GFC_INTEGER_16
    619      1.1  mrg     case 16:
    620      1.1  mrg       if (GFC_UNALIGNED_16(ret->base_addr) || GFC_UNALIGNED_16(source))
    621      1.1  mrg 	break;
    622      1.1  mrg       else
    623      1.1  mrg 	{
    624      1.1  mrg 	  spread_scalar_i16 ((gfc_array_i16 *) ret, (GFC_INTEGER_16 *) source,
    625      1.1  mrg 			     *along, *pncopies);
    626      1.1  mrg 	  return;
    627      1.1  mrg 	}
    628      1.1  mrg #endif
    629      1.1  mrg     default:
    630      1.1  mrg       break;
    631      1.1  mrg     }
    632      1.1  mrg 
    633      1.1  mrg   spread_internal_scalar (ret, source, along, pncopies);
    634      1.1  mrg }
    635      1.1  mrg 
    636      1.1  mrg 
    637      1.1  mrg extern void spread_char_scalar (gfc_array_char *, GFC_INTEGER_4,
    638      1.1  mrg 				const char *, const index_type *,
    639      1.1  mrg 				const index_type *, GFC_INTEGER_4);
    640      1.1  mrg export_proto(spread_char_scalar);
    641      1.1  mrg 
    642      1.1  mrg void
    643      1.1  mrg spread_char_scalar (gfc_array_char *ret,
    644      1.1  mrg 		    GFC_INTEGER_4 ret_length __attribute__((unused)),
    645      1.1  mrg 		    const char *source, const index_type *along,
    646      1.1  mrg 		    const index_type *pncopies,
    647      1.1  mrg 		    GFC_INTEGER_4 source_length __attribute__((unused)))
    648      1.1  mrg {
    649      1.1  mrg   if (GFC_DTYPE_IS_UNSET(ret))
    650      1.1  mrg     runtime_error ("return array missing descriptor in spread()");
    651      1.1  mrg   spread_internal_scalar (ret, source, along, pncopies);
    652      1.1  mrg }
    653      1.1  mrg 
    654      1.1  mrg 
    655      1.1  mrg extern void spread_char4_scalar (gfc_array_char *, GFC_INTEGER_4,
    656      1.1  mrg 				 const char *, const index_type *,
    657      1.1  mrg 				 const index_type *, GFC_INTEGER_4);
    658      1.1  mrg export_proto(spread_char4_scalar);
    659      1.1  mrg 
    660      1.1  mrg void
    661      1.1  mrg spread_char4_scalar (gfc_array_char *ret,
    662      1.1  mrg 		     GFC_INTEGER_4 ret_length __attribute__((unused)),
    663      1.1  mrg 		     const char *source, const index_type *along,
    664      1.1  mrg 		     const index_type *pncopies,
    665      1.1  mrg 		     GFC_INTEGER_4 source_length __attribute__((unused)))
    666      1.1  mrg {
    667      1.1  mrg   if (GFC_DTYPE_IS_UNSET(ret))
    668      1.1  mrg     runtime_error ("return array missing descriptor in spread()");
    669      1.1  mrg   spread_internal_scalar (ret, source, along, pncopies);
    670      1.1  mrg 
    671      1.1  mrg }
    672      1.1  mrg 
    673