(root)/
gcc-13.2.0/
libgfortran/
generated/
norm2_r10.c
       1  /* Implementation of the NORM2 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  
      30  #if defined (HAVE_GFC_REAL_10) && defined (HAVE_GFC_REAL_10) && defined (HAVE_SQRTL) && defined (HAVE_FABSL)
      31  
      32  #define MATHFUNC(funcname) funcname ## l
      33  
      34  
      35  extern void norm2_r10 (gfc_array_r10 * const restrict, 
      36  	gfc_array_r10 * const restrict, const index_type * const restrict);
      37  export_proto(norm2_r10);
      38  
      39  void
      40  norm2_r10 (gfc_array_r10 * const restrict retarray, 
      41  	gfc_array_r10 * const restrict array, 
      42  	const index_type * const restrict pdim)
      43  {
      44    index_type count[GFC_MAX_DIMENSIONS];
      45    index_type extent[GFC_MAX_DIMENSIONS];
      46    index_type sstride[GFC_MAX_DIMENSIONS];
      47    index_type dstride[GFC_MAX_DIMENSIONS];
      48    const GFC_REAL_10 * restrict base;
      49    GFC_REAL_10 * restrict dest;
      50    index_type rank;
      51    index_type n;
      52    index_type len;
      53    index_type delta;
      54    index_type dim;
      55    int continue_loop;
      56  
      57    /* Make dim zero based to avoid confusion.  */
      58    rank = GFC_DESCRIPTOR_RANK (array) - 1;
      59    dim = (*pdim) - 1;
      60  
      61    if (unlikely (dim < 0 || dim > rank))
      62      {
      63        runtime_error ("Dim argument incorrect in NORM intrinsic: "
      64   		     "is %ld, should be between 1 and %ld",
      65  		     (long int) dim + 1, (long int) rank + 1);
      66      }
      67  
      68    len = GFC_DESCRIPTOR_EXTENT(array,dim);
      69    if (len < 0)
      70      len = 0;
      71    delta = GFC_DESCRIPTOR_STRIDE(array,dim);
      72  
      73    for (n = 0; n < dim; n++)
      74      {
      75        sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
      76        extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
      77  
      78        if (extent[n] < 0)
      79  	extent[n] = 0;
      80      }
      81    for (n = dim; n < rank; n++)
      82      {
      83        sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
      84        extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
      85  
      86        if (extent[n] < 0)
      87  	extent[n] = 0;
      88      }
      89  
      90    if (retarray->base_addr == NULL)
      91      {
      92        size_t alloc_size, str;
      93  
      94        for (n = 0; n < rank; n++)
      95  	{
      96  	  if (n == 0)
      97  	    str = 1;
      98  	  else
      99  	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
     100  
     101  	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
     102  
     103  	}
     104  
     105        retarray->offset = 0;
     106        retarray->dtype.rank = rank;
     107  
     108        alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
     109  
     110        retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_REAL_10));
     111        if (alloc_size == 0)
     112  	{
     113  	  /* Make sure we have a zero-sized array.  */
     114  	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
     115  	  return;
     116  
     117  	}
     118      }
     119    else
     120      {
     121        if (rank != GFC_DESCRIPTOR_RANK (retarray))
     122  	runtime_error ("rank of return array incorrect in"
     123  		       " NORM intrinsic: is %ld, should be %ld",
     124  		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
     125  		       (long int) rank);
     126  
     127        if (unlikely (compile_options.bounds_check))
     128  	bounds_ifunction_return ((array_t *) retarray, extent,
     129  				 "return value", "NORM");
     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    dest = retarray->base_addr;
     142  
     143    continue_loop = 1;
     144    while (continue_loop)
     145      {
     146        const GFC_REAL_10 * restrict src;
     147        GFC_REAL_10 result;
     148        src = base;
     149        {
     150  
     151  	GFC_REAL_10 scale;
     152  	result = 0;
     153  	scale = 1;
     154  	if (len <= 0)
     155  	  *dest = 0;
     156  	else
     157  	  {
     158  #if ! defined HAVE_BACK_ARG
     159  	    for (n = 0; n < len; n++, src += delta)
     160  	      {
     161  #endif
     162  
     163  	  if (*src != 0)
     164  	    {
     165  	      GFC_REAL_10 absX, val;
     166  	      absX = MATHFUNC(fabs) (*src);
     167  	      if (scale < absX)
     168  		{
     169  		  val = scale / absX;
     170  		  result = 1 + result * val * val;
     171  		  scale = absX;
     172  		}
     173  	      else
     174  		{
     175  		  val = absX / scale;
     176  		  result += val * val;
     177  		}
     178  	    }
     179  	      }
     180  	    result = scale * MATHFUNC(sqrt) (result);
     181  	    *dest = result;
     182  	  }
     183        }
     184        /* Advance to the next element.  */
     185        count[0]++;
     186        base += sstride[0];
     187        dest += dstride[0];
     188        n = 0;
     189        while (count[n] == extent[n])
     190  	{
     191  	  /* When we get to the end of a dimension, reset it and increment
     192  	     the next dimension.  */
     193  	  count[n] = 0;
     194  	  /* We could precalculate these products, but this is a less
     195  	     frequently used path so probably not worth it.  */
     196  	  base -= sstride[n] * extent[n];
     197  	  dest -= dstride[n] * extent[n];
     198  	  n++;
     199  	  if (n >= rank)
     200  	    {
     201  	      /* Break out of the loop.  */
     202  	      continue_loop = 0;
     203  	      break;
     204  	    }
     205  	  else
     206  	    {
     207  	      count[n]++;
     208  	      base += sstride[n];
     209  	      dest += dstride[n];
     210  	    }
     211  	}
     212      }
     213  }
     214  
     215  #endif