(root)/
gcc-13.2.0/
libgfortran/
generated/
parity_l8.c
       1  /* Implementation of the PARITY intrinsic
       2     Copyright (C) 2010-2023 Free Software Foundation, Inc.
       3     Contributed by Tobias Burnus  <burnus@net-b.de>
       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_8) && defined (HAVE_GFC_LOGICAL_8)
      30  
      31  
      32  extern void parity_l8 (gfc_array_l8 * const restrict, 
      33  	gfc_array_l8 * const restrict, const index_type * const restrict);
      34  export_proto(parity_l8);
      35  
      36  void
      37  parity_l8 (gfc_array_l8 * const restrict retarray, 
      38  	gfc_array_l8 * 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_8 * restrict base;
      46    GFC_LOGICAL_8 * restrict dest;
      47    index_type rank;
      48    index_type n;
      49    index_type len;
      50    index_type delta;
      51    index_type dim;
      52    int continue_loop;
      53  
      54    /* Make dim zero based to avoid confusion.  */
      55    rank = GFC_DESCRIPTOR_RANK (array) - 1;
      56    dim = (*pdim) - 1;
      57  
      58    if (unlikely (dim < 0 || dim > rank))
      59      {
      60        runtime_error ("Dim argument incorrect in PARITY intrinsic: "
      61   		     "is %ld, should be between 1 and %ld",
      62  		     (long int) dim + 1, (long int) rank + 1);
      63      }
      64  
      65    len = GFC_DESCRIPTOR_EXTENT(array,dim);
      66    if (len < 0)
      67      len = 0;
      68    delta = GFC_DESCRIPTOR_STRIDE(array,dim);
      69  
      70    for (n = 0; n < dim; n++)
      71      {
      72        sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
      73        extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
      74  
      75        if (extent[n] < 0)
      76  	extent[n] = 0;
      77      }
      78    for (n = dim; n < rank; n++)
      79      {
      80        sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
      81        extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
      82  
      83        if (extent[n] < 0)
      84  	extent[n] = 0;
      85      }
      86  
      87    if (retarray->base_addr == NULL)
      88      {
      89        size_t alloc_size, str;
      90  
      91        for (n = 0; n < rank; n++)
      92  	{
      93  	  if (n == 0)
      94  	    str = 1;
      95  	  else
      96  	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
      97  
      98  	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
      99  
     100  	}
     101  
     102        retarray->offset = 0;
     103        retarray->dtype.rank = rank;
     104  
     105        alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
     106  
     107        retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_LOGICAL_8));
     108        if (alloc_size == 0)
     109  	{
     110  	  /* Make sure we have a zero-sized array.  */
     111  	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
     112  	  return;
     113  
     114  	}
     115      }
     116    else
     117      {
     118        if (rank != GFC_DESCRIPTOR_RANK (retarray))
     119  	runtime_error ("rank of return array incorrect in"
     120  		       " PARITY intrinsic: is %ld, should be %ld",
     121  		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
     122  		       (long int) rank);
     123  
     124        if (unlikely (compile_options.bounds_check))
     125  	bounds_ifunction_return ((array_t *) retarray, extent,
     126  				 "return value", "PARITY");
     127      }
     128  
     129    for (n = 0; n < rank; n++)
     130      {
     131        count[n] = 0;
     132        dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
     133        if (extent[n] <= 0)
     134  	return;
     135      }
     136  
     137    base = array->base_addr;
     138    dest = retarray->base_addr;
     139  
     140    continue_loop = 1;
     141    while (continue_loop)
     142      {
     143        const GFC_LOGICAL_8 * restrict src;
     144        GFC_LOGICAL_8 result;
     145        src = base;
     146        {
     147  
     148    result = 0;
     149  	if (len <= 0)
     150  	  *dest = 0;
     151  	else
     152  	  {
     153  #if ! defined HAVE_BACK_ARG
     154  	    for (n = 0; n < len; n++, src += delta)
     155  	      {
     156  #endif
     157  
     158    result = result != *src;
     159  	      }
     160  	    
     161  	    *dest = result;
     162  	  }
     163        }
     164        /* Advance to the next element.  */
     165        count[0]++;
     166        base += sstride[0];
     167        dest += dstride[0];
     168        n = 0;
     169        while (count[n] == extent[n])
     170  	{
     171  	  /* When we get to the end of a dimension, reset it and increment
     172  	     the next dimension.  */
     173  	  count[n] = 0;
     174  	  /* We could precalculate these products, but this is a less
     175  	     frequently used path so probably not worth it.  */
     176  	  base -= sstride[n] * extent[n];
     177  	  dest -= dstride[n] * extent[n];
     178  	  n++;
     179  	  if (n >= rank)
     180  	    {
     181  	      /* Break out of the loop.  */
     182  	      continue_loop = 0;
     183  	      break;
     184  	    }
     185  	  else
     186  	    {
     187  	      count[n]++;
     188  	      base += sstride[n];
     189  	      dest += dstride[n];
     190  	    }
     191  	}
     192      }
     193  }
     194  
     195  #endif