Home | History | Annotate | Line # | Download | only in generated
      1 /* Implementation of the ALL intrinsic
      2    Copyright (C) 2002-2024 Free Software Foundation, Inc.
      3    Contributed by Paul Brook <paul (at) nowt.org>
      4 
      5 This file is part of the GNU Fortran runtime library (libgfortran).
      6 
      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.
     11 
     12 Libgfortran 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.
     16 
     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.
     20 
     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/>.  */
     25 
     26 #include "libgfortran.h"
     27 
     28 
     29 #if defined (HAVE_GFC_LOGICAL_16)
     30 
     31 
     32 extern void all_l16 (gfc_array_l16 * const restrict,
     33 	gfc_array_l1 * const restrict, const index_type * const restrict);
     34 export_proto(all_l16);
     35 
     36 void
     37 all_l16 (gfc_array_l16 * const restrict retarray,
     38 	gfc_array_l1 * const restrict array,
     39 	const index_type * const restrict pdim)
     40 {
     41   index_type count[GFC_MAX_DIMENSIONS];
     42   index_type extent[GFC_MAX_DIMENSIONS];
     43   index_type sstride[GFC_MAX_DIMENSIONS];
     44   index_type dstride[GFC_MAX_DIMENSIONS];
     45   const GFC_LOGICAL_1 * restrict base;
     46   GFC_LOGICAL_16 * restrict dest;
     47   index_type rank;
     48   index_type n;
     49   index_type len;
     50   index_type delta;
     51   index_type dim;
     52   int src_kind;
     53   int continue_loop;
     54 
     55   /* Make dim zero based to avoid confusion.  */
     56   dim = (*pdim) - 1;
     57   rank = GFC_DESCRIPTOR_RANK (array) - 1;
     58 
     59   src_kind = GFC_DESCRIPTOR_SIZE (array);
     60 
     61   len = GFC_DESCRIPTOR_EXTENT(array,dim);
     62   if (len < 0)
     63     len = 0;
     64 
     65   delta = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
     66 
     67   for (n = 0; n < dim; n++)
     68     {
     69       sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n);
     70       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
     71 
     72       if (extent[n] < 0)
     73 	extent[n] = 0;
     74     }
     75   for (n = dim; n < rank; n++)
     76     {
     77       sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n + 1);
     78       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1);
     79 
     80       if (extent[n] < 0)
     81 	extent[n] = 0;
     82     }
     83 
     84   if (retarray->base_addr == NULL)
     85     {
     86       size_t alloc_size, str;
     87 
     88       for (n = 0; n < rank; n++)
     89         {
     90           if (n == 0)
     91             str = 1;
     92           else
     93             str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
     94 
     95 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
     96 
     97         }
     98 
     99       retarray->offset = 0;
    100       retarray->dtype.rank = rank;
    101 
    102       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
    103 
    104       retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_LOGICAL_16));
    105       if (alloc_size == 0)
    106 	return;
    107     }
    108   else
    109     {
    110       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    111 	runtime_error ("rank of return array incorrect in"
    112 		       " ALL intrinsic: is %ld, should be %ld",
    113 		       (long int) GFC_DESCRIPTOR_RANK (retarray),
    114 		       (long int) rank);
    115 
    116       if (unlikely (compile_options.bounds_check))
    117 	{
    118 	  for (n=0; n < rank; n++)
    119 	    {
    120 	      index_type ret_extent;
    121 
    122 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
    123 	      if (extent[n] != ret_extent)
    124 		runtime_error ("Incorrect extent in return value of"
    125 			       " ALL intrinsic in dimension %d:"
    126 			       " is %ld, should be %ld", (int) n + 1,
    127 			       (long int) ret_extent, (long int) extent[n]);
    128 	    }
    129 	}
    130     }
    131 
    132   for (n = 0; n < rank; n++)
    133     {
    134       count[n] = 0;
    135       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
    136       if (extent[n] <= 0)
    137 	return;
    138     }
    139 
    140   base = array->base_addr;
    141 
    142   if (src_kind == 1 || src_kind == 2 || src_kind == 4 || src_kind == 8
    143 #ifdef HAVE_GFC_LOGICAL_16
    144       || src_kind == 16
    145 #endif
    146     )
    147     {
    148       if (base)
    149 	base = GFOR_POINTER_TO_L1 (base, src_kind);
    150     }
    151   else
    152     internal_error (NULL, "Funny sized logical array in ALL intrinsic");
    153 
    154   dest = retarray->base_addr;
    155 
    156   continue_loop = 1;
    157   while (continue_loop)
    158     {
    159       const GFC_LOGICAL_1 * restrict src;
    160       GFC_LOGICAL_16 result;
    161       src = base;
    162       {
    163 
    164   /* Return true only if all the elements are set.  */
    165   result = 1;
    166         if (len <= 0)
    167 	  *dest = 1;
    168 	else
    169 	  {
    170 	    for (n = 0; n < len; n++, src += delta)
    171 	      {
    172 
    173   if (! *src)
    174     {
    175       result = 0;
    176       break;
    177     }
    178           }
    179 	    *dest = result;
    180 	  }
    181       }
    182       /* Advance to the next element.  */
    183       count[0]++;
    184       base += sstride[0];
    185       dest += dstride[0];
    186       n = 0;
    187       while (count[n] == extent[n])
    188         {
    189           /* When we get to the end of a dimension, reset it and increment
    190              the next dimension.  */
    191           count[n] = 0;
    192           /* We could precalculate these products, but this is a less
    193              frequently used path so probably not worth it.  */
    194           base -= sstride[n] * extent[n];
    195           dest -= dstride[n] * extent[n];
    196           n++;
    197           if (n >= rank)
    198             {
    199               /* Break out of the loop.  */
    200               continue_loop = 0;
    201               break;
    202             }
    203           else
    204             {
    205               count[n]++;
    206               base += sstride[n];
    207               dest += dstride[n];
    208             }
    209         }
    210     }
    211 }
    212 
    213 #endif
    214