]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/generated/norm2_r16.c
Update copyright years.
[thirdparty/gcc.git] / libgfortran / generated / norm2_r16.c
CommitLineData
0cd0559e 1/* Implementation of the NORM2 intrinsic
a945c346 2 Copyright (C) 2010-2024 Free Software Foundation, Inc.
0cd0559e
TB
3 Contributed by Tobias Burnus <burnus@net-b.de>
4
5This file is part of the GNU Fortran runtime library (libgfortran).
6
7Libgfortran is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public
9License as published by the Free Software Foundation; either
10version 3 of the License, or (at your option) any later version.
11
12Libgfortran is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
25
26#include "libgfortran.h"
0cd0559e
TB
27
28
08fd13d4 29
1ec601bf 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))
08fd13d4
FXC
31
32#if defined(GFC_REAL_16_IS_FLOAT128)
133d0d42
JJ
33#if defined(GFC_REAL_16_USE_IEC_60559)
34#define MATHFUNC(funcname) funcname ## f128
35#else
08fd13d4 36#define MATHFUNC(funcname) funcname ## q
133d0d42 37#endif
08fd13d4
FXC
38#else
39#define MATHFUNC(funcname) funcname ## l
40#endif
0cd0559e
TB
41
42
43extern void norm2_r16 (gfc_array_r16 * const restrict,
44 gfc_array_r16 * const restrict, const index_type * const restrict);
45export_proto(norm2_r16);
46
47void
48norm2_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. */
0cd0559e 66 rank = GFC_DESCRIPTOR_RANK (array) - 1;
cfdf6ff6
TK
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 }
0cd0559e
TB
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
21d1335b 98 if (retarray->base_addr == NULL)
0cd0559e
TB
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;
ca708a2b 114 retarray->dtype.rank = rank;
0cd0559e 115
92e6f3a4 116 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
0cd0559e 117
92e6f3a4 118 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_REAL_16));
0cd0559e 119 if (alloc_size == 0)
62715bf8 120 return;
0cd0559e
TB
121 }
122 else
123 {
124 if (rank != GFC_DESCRIPTOR_RANK (retarray))
125 runtime_error ("rank of return array incorrect in"
126 " NORM intrinsic: is %ld, should be %ld",
127 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
128 (long int) rank);
129
130 if (unlikely (compile_options.bounds_check))
131 bounds_ifunction_return ((array_t *) retarray, extent,
132 "return value", "NORM");
133 }
134
135 for (n = 0; n < rank; n++)
136 {
137 count[n] = 0;
138 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
139 if (extent[n] <= 0)
3d2244b9 140 return;
0cd0559e
TB
141 }
142
21d1335b
TB
143 base = array->base_addr;
144 dest = retarray->base_addr;
0cd0559e
TB
145
146 continue_loop = 1;
147 while (continue_loop)
148 {
149 const GFC_REAL_16 * restrict src;
150 GFC_REAL_16 result;
151 src = base;
152 {
153
154 GFC_REAL_16 scale;
08fd13d4
FXC
155 result = 0;
156 scale = 1;
0cd0559e 157 if (len <= 0)
08fd13d4 158 *dest = 0;
0cd0559e
TB
159 else
160 {
b573f931 161#if ! defined HAVE_BACK_ARG
0cd0559e
TB
162 for (n = 0; n < len; n++, src += delta)
163 {
b573f931 164#endif
0cd0559e 165
08fd13d4 166 if (*src != 0)
0cd0559e
TB
167 {
168 GFC_REAL_16 absX, val;
08fd13d4 169 absX = MATHFUNC(fabs) (*src);
0cd0559e
TB
170 if (scale < absX)
171 {
172 val = scale / absX;
08fd13d4 173 result = 1 + result * val * val;
0cd0559e
TB
174 scale = absX;
175 }
176 else
177 {
178 val = absX / scale;
179 result += val * val;
180 }
181 }
182 }
08fd13d4 183 result = scale * MATHFUNC(sqrt) (result);
0cd0559e
TB
184 *dest = result;
185 }
186 }
187 /* Advance to the next element. */
188 count[0]++;
189 base += sstride[0];
190 dest += dstride[0];
191 n = 0;
192 while (count[n] == extent[n])
193 {
194 /* When we get to the end of a dimension, reset it and increment
195 the next dimension. */
196 count[n] = 0;
197 /* We could precalculate these products, but this is a less
198 frequently used path so probably not worth it. */
199 base -= sstride[n] * extent[n];
200 dest -= dstride[n] * extent[n];
201 n++;
80dd631f 202 if (n >= rank)
0cd0559e 203 {
80dd631f 204 /* Break out of the loop. */
0cd0559e
TB
205 continue_loop = 0;
206 break;
207 }
208 else
209 {
210 count[n]++;
211 base += sstride[n];
212 dest += dstride[n];
213 }
214 }
215 }
216}
217
218#endif