Home | History | Annotate | Line # | Download | only in m4
ifindloc0.m4 revision 1.1
      1  1.1  mrg `/* Implementation of the FINDLOC intrinsic
      2  1.1  mrg    Copyright (C) 2018-2019 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Thomas Knig <tk (a] tkoenig.net>
      4  1.1  mrg 
      5  1.1  mrg This file is part of the GNU Fortran 95 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 #include <assert.h>
     28  1.1  mrg 
     29  1.1  mrg #if defined (HAVE_'atype_name`)
     30  1.1  mrg 'header1`
     31  1.1  mrg {
     32  1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     33  1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     34  1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     35  1.1  mrg   index_type dstride;
     36  1.1  mrg   const 'atype_name` *base;
     37  1.1  mrg   index_type * restrict dest;
     38  1.1  mrg   index_type rank;
     39  1.1  mrg   index_type n;
     40  1.1  mrg   index_type sz;
     41  1.1  mrg 
     42  1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array);
     43  1.1  mrg   if (rank <= 0)
     44  1.1  mrg     runtime_error ("Rank of array needs to be > 0");
     45  1.1  mrg 
     46  1.1  mrg   if (retarray->base_addr == NULL)
     47  1.1  mrg     {
     48  1.1  mrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
     49  1.1  mrg       retarray->dtype.rank = 1;
     50  1.1  mrg       retarray->offset = 0;
     51  1.1  mrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
     52  1.1  mrg     }
     53  1.1  mrg   else
     54  1.1  mrg     {
     55  1.1  mrg       if (unlikely (compile_options.bounds_check))
     56  1.1  mrg 	bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
     57  1.1  mrg 				"FINDLOC");
     58  1.1  mrg     }
     59  1.1  mrg 
     60  1.1  mrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
     61  1.1  mrg   dest = retarray->base_addr;
     62  1.1  mrg 
     63  1.1  mrg   /* Set the return value.  */
     64  1.1  mrg   for (n = 0; n < rank; n++)
     65  1.1  mrg     dest[n * dstride] = 0;
     66  1.1  mrg 
     67  1.1  mrg   sz = 1;
     68  1.1  mrg   for (n = 0; n < rank; n++)
     69  1.1  mrg     {
     70  1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
     71  1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
     72  1.1  mrg       sz *= extent[n];
     73  1.1  mrg       if (extent[n] <= 0)
     74  1.1  mrg 	return;
     75  1.1  mrg     }
     76  1.1  mrg 
     77  1.1  mrg     for (n = 0; n < rank; n++)
     78  1.1  mrg       count[n] = 0;
     79  1.1  mrg 
     80  1.1  mrg   if (back)
     81  1.1  mrg     {
     82  1.1  mrg       base = array->base_addr + (sz - 1) * 'base_mult`'`;
     83  1.1  mrg 
     84  1.1  mrg       while (1)
     85  1.1  mrg         {
     86  1.1  mrg 	  do
     87  1.1  mrg 	    {
     88  1.1  mrg 	      if (unlikely('comparison`))
     89  1.1  mrg 	        {
     90  1.1  mrg 		  for (n = 0; n < rank; n++)
     91  1.1  mrg 		    dest[n * dstride] = extent[n] - count[n];
     92  1.1  mrg 
     93  1.1  mrg 		  return;
     94  1.1  mrg 		}
     95  1.1  mrg 	      base -= sstride[0] * 'base_mult`'`;
     96  1.1  mrg 	    } while(++count[0] != extent[0]);
     97  1.1  mrg 
     98  1.1  mrg 	  n = 0;
     99  1.1  mrg 	  do
    100  1.1  mrg 	    {
    101  1.1  mrg 	      /* When we get to the end of a dimension, reset it and increment
    102  1.1  mrg 		 the next dimension.  */
    103  1.1  mrg 	      count[n] = 0;
    104  1.1  mrg 	      /* We could precalculate these products, but this is a less
    105  1.1  mrg 		 frequently used path so probably not worth it.  */
    106  1.1  mrg 	      base += sstride[n] * extent[n] * 'base_mult`'`;
    107  1.1  mrg 	      n++;
    108  1.1  mrg 	      if (n >= rank)
    109  1.1  mrg 	        return;
    110  1.1  mrg 	      else
    111  1.1  mrg 		{
    112  1.1  mrg 		  count[n]++;
    113  1.1  mrg 		  base -= sstride[n] * 'base_mult`'`;
    114  1.1  mrg 		}
    115  1.1  mrg 	    } while (count[n] == extent[n]);      
    116  1.1  mrg 	}
    117  1.1  mrg     }
    118  1.1  mrg   else
    119  1.1  mrg     {
    120  1.1  mrg       base = array->base_addr;
    121  1.1  mrg       while (1)
    122  1.1  mrg         {
    123  1.1  mrg 	  do
    124  1.1  mrg 	    {
    125  1.1  mrg 	      if (unlikely('comparison`))
    126  1.1  mrg 	        {
    127  1.1  mrg 		  for (n = 0; n < rank; n++)
    128  1.1  mrg 		    dest[n * dstride] = count[n] + 1;
    129  1.1  mrg 
    130  1.1  mrg 		  return;
    131  1.1  mrg 		}
    132  1.1  mrg 	      base += sstride[0] * 'base_mult`'`;
    133  1.1  mrg 	    } while(++count[0] != extent[0]);
    134  1.1  mrg 
    135  1.1  mrg 	  n = 0;
    136  1.1  mrg 	  do
    137  1.1  mrg 	    {
    138  1.1  mrg 	      /* When we get to the end of a dimension, reset it and increment
    139  1.1  mrg 		 the next dimension.  */
    140  1.1  mrg 	      count[n] = 0;
    141  1.1  mrg 	      /* We could precalculate these products, but this is a less
    142  1.1  mrg 		 frequently used path so probably not worth it.  */
    143  1.1  mrg 	      base -= sstride[n] * extent[n] * 'base_mult`'`;
    144  1.1  mrg 	      n++;
    145  1.1  mrg 	      if (n >= rank)
    146  1.1  mrg 	        return;
    147  1.1  mrg 	      else
    148  1.1  mrg 		{
    149  1.1  mrg 		  count[n]++;
    150  1.1  mrg 		  base += sstride[n] * 'base_mult`'`;
    151  1.1  mrg 		}
    152  1.1  mrg 	    } while (count[n] == extent[n]);
    153  1.1  mrg 	}
    154  1.1  mrg     }
    155  1.1  mrg   return;
    156  1.1  mrg }
    157  1.1  mrg 
    158  1.1  mrg 'header2`
    159  1.1  mrg {
    160  1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    161  1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    162  1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
    163  1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
    164  1.1  mrg   index_type dstride;
    165  1.1  mrg   const 'atype_name` *base;
    166  1.1  mrg   index_type * restrict dest;
    167  1.1  mrg   GFC_LOGICAL_1 *mbase;
    168  1.1  mrg   index_type rank;
    169  1.1  mrg   index_type n;
    170  1.1  mrg   int mask_kind;
    171  1.1  mrg   index_type sz;
    172  1.1  mrg 
    173  1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array);
    174  1.1  mrg   if (rank <= 0)
    175  1.1  mrg     runtime_error ("Rank of array needs to be > 0");
    176  1.1  mrg 
    177  1.1  mrg   if (retarray->base_addr == NULL)
    178  1.1  mrg     {
    179  1.1  mrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
    180  1.1  mrg       retarray->dtype.rank = 1;
    181  1.1  mrg       retarray->offset = 0;
    182  1.1  mrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
    183  1.1  mrg     }
    184  1.1  mrg   else
    185  1.1  mrg     {
    186  1.1  mrg       if (unlikely (compile_options.bounds_check))
    187  1.1  mrg 	{
    188  1.1  mrg 	  bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
    189  1.1  mrg 				  "FINDLOC");
    190  1.1  mrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
    191  1.1  mrg 				"MASK argument", "FINDLOC");
    192  1.1  mrg 	}
    193  1.1  mrg     }
    194  1.1  mrg 
    195  1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    196  1.1  mrg 
    197  1.1  mrg   mbase = mask->base_addr;
    198  1.1  mrg 
    199  1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    200  1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    201  1.1  mrg       || mask_kind == 16
    202  1.1  mrg #endif
    203  1.1  mrg       )
    204  1.1  mrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    205  1.1  mrg   else
    206  1.1  mrg     internal_error (NULL, "Funny sized logical array");
    207  1.1  mrg 
    208  1.1  mrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
    209  1.1  mrg   dest = retarray->base_addr;
    210  1.1  mrg 
    211  1.1  mrg   /* Set the return value.  */
    212  1.1  mrg   for (n = 0; n < rank; n++)
    213  1.1  mrg     dest[n * dstride] = 0;
    214  1.1  mrg 
    215  1.1  mrg   sz = 1;
    216  1.1  mrg   for (n = 0; n < rank; n++)
    217  1.1  mrg     {
    218  1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
    219  1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    220  1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    221  1.1  mrg       sz *= extent[n];
    222  1.1  mrg       if (extent[n] <= 0)
    223  1.1  mrg 	return;
    224  1.1  mrg     }
    225  1.1  mrg 
    226  1.1  mrg     for (n = 0; n < rank; n++)
    227  1.1  mrg       count[n] = 0;
    228  1.1  mrg 
    229  1.1  mrg   if (back)
    230  1.1  mrg     {
    231  1.1  mrg       base = array->base_addr + (sz - 1) * 'base_mult`'`;
    232  1.1  mrg       mbase = mbase + (sz - 1) * mask_kind;
    233  1.1  mrg       while (1)
    234  1.1  mrg         {
    235  1.1  mrg 	  do
    236  1.1  mrg 	    {
    237  1.1  mrg 	      if (unlikely(*mbase && 'comparison`))
    238  1.1  mrg 	        {
    239  1.1  mrg 		  for (n = 0; n < rank; n++)
    240  1.1  mrg 		    dest[n * dstride] = extent[n] - count[n];
    241  1.1  mrg 
    242  1.1  mrg 		  return;
    243  1.1  mrg 		}
    244  1.1  mrg 	      base -= sstride[0] * 'base_mult`'`;
    245  1.1  mrg 	      mbase -= mstride[0];
    246  1.1  mrg 	    } while(++count[0] != extent[0]);
    247  1.1  mrg 
    248  1.1  mrg 	  n = 0;
    249  1.1  mrg 	  do
    250  1.1  mrg 	    {
    251  1.1  mrg 	      /* When we get to the end of a dimension, reset it and increment
    252  1.1  mrg 		 the next dimension.  */
    253  1.1  mrg 	      count[n] = 0;
    254  1.1  mrg 	      /* We could precalculate these products, but this is a less
    255  1.1  mrg 		 frequently used path so probably not worth it.  */
    256  1.1  mrg 	      base += sstride[n] * extent[n] * 'base_mult`'`;
    257  1.1  mrg 	      mbase -= mstride[n] * extent[n];
    258  1.1  mrg 	      n++;
    259  1.1  mrg 	      if (n >= rank)
    260  1.1  mrg 		return;
    261  1.1  mrg 	      else
    262  1.1  mrg 		{
    263  1.1  mrg 		  count[n]++;
    264  1.1  mrg 		  base -= sstride[n] * 'base_mult`'`;
    265  1.1  mrg 		  mbase += mstride[n];
    266  1.1  mrg 		}
    267  1.1  mrg 	    } while (count[n] == extent[n]);      
    268  1.1  mrg 	}
    269  1.1  mrg     }
    270  1.1  mrg   else
    271  1.1  mrg     {
    272  1.1  mrg       base = array->base_addr;
    273  1.1  mrg       while (1)
    274  1.1  mrg         {
    275  1.1  mrg 	  do
    276  1.1  mrg 	    {
    277  1.1  mrg 	      if (unlikely(*mbase && 'comparison`))
    278  1.1  mrg 	        {
    279  1.1  mrg 		  for (n = 0; n < rank; n++)
    280  1.1  mrg 		    dest[n * dstride] = count[n] + 1;
    281  1.1  mrg 
    282  1.1  mrg 		  return;
    283  1.1  mrg 		}
    284  1.1  mrg 	      base += sstride[0] * 'base_mult`'`;
    285  1.1  mrg 	      mbase += mstride[0];
    286  1.1  mrg 	    } while(++count[0] != extent[0]);
    287  1.1  mrg 
    288  1.1  mrg 	  n = 0;
    289  1.1  mrg 	  do
    290  1.1  mrg 	    {
    291  1.1  mrg 	      /* When we get to the end of a dimension, reset it and increment
    292  1.1  mrg 		 the next dimension.  */
    293  1.1  mrg 	      count[n] = 0;
    294  1.1  mrg 	      /* We could precalculate these products, but this is a less
    295  1.1  mrg 		 frequently used path so probably not worth it.  */
    296  1.1  mrg 	      base -= sstride[n] * extent[n] * 'base_mult`'`;
    297  1.1  mrg 	      mbase -= mstride[n] * extent[n];
    298  1.1  mrg 	      n++;
    299  1.1  mrg 	      if (n >= rank)
    300  1.1  mrg 		return;
    301  1.1  mrg 	      else
    302  1.1  mrg 		{
    303  1.1  mrg 		  count[n]++;
    304  1.1  mrg 		  base += sstride[n]* 'base_mult`'`;
    305  1.1  mrg 		  mbase += mstride[n];
    306  1.1  mrg 		}
    307  1.1  mrg 	    } while (count[n] == extent[n]);
    308  1.1  mrg 	}
    309  1.1  mrg     }
    310  1.1  mrg   return;
    311  1.1  mrg }
    312  1.1  mrg 
    313  1.1  mrg 'header3`
    314  1.1  mrg {
    315  1.1  mrg   index_type rank;
    316  1.1  mrg   index_type dstride;
    317  1.1  mrg   index_type * restrict dest;
    318  1.1  mrg   index_type n;
    319  1.1  mrg 
    320  1.1  mrg   if (mask == NULL || *mask)
    321  1.1  mrg     {
    322  1.1  mrg       findloc0_'atype_code` (retarray, array, value, back'len_arg`);
    323  1.1  mrg       return;
    324  1.1  mrg     }
    325  1.1  mrg 
    326  1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array);
    327  1.1  mrg 
    328  1.1  mrg   if (rank <= 0)
    329  1.1  mrg     internal_error (NULL, "Rank of array needs to be > 0");
    330  1.1  mrg 
    331  1.1  mrg   if (retarray->base_addr == NULL)
    332  1.1  mrg     {
    333  1.1  mrg       GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
    334  1.1  mrg       retarray->dtype.rank = 1;
    335  1.1  mrg       retarray->offset = 0;
    336  1.1  mrg       retarray->base_addr = xmallocarray (rank, sizeof (index_type));
    337  1.1  mrg     }
    338  1.1  mrg   else if (unlikely (compile_options.bounds_check))
    339  1.1  mrg     {
    340  1.1  mrg        bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
    341  1.1  mrg 			       "FINDLOC");
    342  1.1  mrg     }
    343  1.1  mrg 
    344  1.1  mrg   dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
    345  1.1  mrg   dest = retarray->base_addr;
    346  1.1  mrg   for (n = 0; n<rank; n++)
    347  1.1  mrg     dest[n * dstride] = 0 ;
    348  1.1  mrg }
    349  1.1  mrg 
    350  1.1  mrg #endif'
    351