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