1 //===-- runtime/numeric.cpp -----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "terminator.h"
10 #include "flang/Runtime/numeric.h"
11 #include "flang/Common/long-double.h"
12 #include <climits>
13 #include <cmath>
14 #include <limits>
15 
16 namespace Fortran::runtime {
17 
18 // AINT
19 template <typename RESULT, typename ARG> inline RESULT Aint(ARG x) {
20   return std::trunc(x);
21 }
22 
23 // ANINT & NINT
24 template <typename RESULT, typename ARG> inline RESULT Anint(ARG x) {
25   if (x >= 0) {
26     return std::trunc(x + ARG{0.5});
27   } else {
28     return std::trunc(x - ARG{0.5});
29   }
30 }
31 
32 // CEILING & FLOOR (16.9.43, .79)
33 template <typename RESULT, typename ARG> inline RESULT Ceiling(ARG x) {
34   return std::ceil(x);
35 }
36 template <typename RESULT, typename ARG> inline RESULT Floor(ARG x) {
37   return std::floor(x);
38 }
39 
40 // EXPONENT (16.9.75)
41 template <typename RESULT, typename ARG> inline RESULT Exponent(ARG x) {
42   if (std::isinf(x) || std::isnan(x)) {
43     return std::numeric_limits<RESULT>::max(); // +/-Inf, NaN -> HUGE(0)
44   } else if (x == 0) {
45     return 0; // 0 -> 0
46   } else {
47     return std::ilogb(x) + 1;
48   }
49 }
50 
51 // FRACTION (16.9.80)
52 template <typename T> inline T Fraction(T x) {
53   if (std::isnan(x)) {
54     return x; // NaN -> same NaN
55   } else if (std::isinf(x)) {
56     return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN
57   } else if (x == 0) {
58     return 0; // 0 -> 0
59   } else {
60     int ignoredExp;
61     return std::frexp(x, &ignoredExp);
62   }
63 }
64 
65 // MOD & MODULO (16.9.135, .136)
66 template <bool IS_MODULO, typename T>
67 inline T IntMod(T x, T p, const char *sourceFile, int sourceLine) {
68   if (p == 0) {
69     Terminator{sourceFile, sourceLine}.Crash(
70         IS_MODULO ? "MODULO with P==0" : "MOD with P==0");
71   }
72   auto mod{x - (x / p) * p};
73   if (IS_MODULO && (x > 0) != (p > 0)) {
74     mod += p;
75   }
76   return mod;
77 }
78 template <bool IS_MODULO, typename T>
79 inline T RealMod(T x, T p, const char *sourceFile, int sourceLine) {
80   if (p == 0) {
81     Terminator{sourceFile, sourceLine}.Crash(
82         IS_MODULO ? "MODULO with P==0" : "MOD with P==0");
83   }
84   if constexpr (IS_MODULO) {
85     return x - std::floor(x / p) * p;
86   } else {
87     return x - std::trunc(x / p) * p;
88   }
89 }
90 
91 // RRSPACING (16.9.164)
92 template <int PREC, typename T> inline T RRSpacing(T x) {
93   if (std::isnan(x)) {
94     return x; // NaN -> same NaN
95   } else if (std::isinf(x)) {
96     return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN
97   } else if (x == 0) {
98     return 0; // 0 -> 0
99   } else {
100     return std::ldexp(std::abs(x), PREC - (std::ilogb(x) + 1));
101   }
102 }
103 
104 // SCALE (16.9.166)
105 template <typename T> inline T Scale(T x, std::int64_t p) {
106   auto ip{static_cast<int>(p)};
107   if (ip != p) {
108     ip = p < 0 ? std::numeric_limits<int>::min()
109                : std::numeric_limits<int>::max();
110   }
111   return std::ldexp(x, p); // x*2**p
112 }
113 
114 // SET_EXPONENT (16.9.171)
115 template <typename T> inline T SetExponent(T x, std::int64_t p) {
116   if (std::isnan(x)) {
117     return x; // NaN -> same NaN
118   } else if (std::isinf(x)) {
119     return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN
120   } else if (x == 0) {
121     return 0; // 0 -> 0
122   } else {
123     int expo{std::ilogb(x) + 1};
124     auto ip{static_cast<int>(p - expo)};
125     if (ip != p - expo) {
126       ip = p < 0 ? std::numeric_limits<int>::min()
127                  : std::numeric_limits<int>::max();
128     }
129     return std::ldexp(x, ip); // x*2**(p-e)
130   }
131 }
132 
133 // SPACING (16.9.180)
134 template <int PREC, typename T> inline T Spacing(T x) {
135   if (std::isnan(x)) {
136     return x; // NaN -> same NaN
137   } else if (std::isinf(x)) {
138     return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN
139   } else if (x == 0) {
140     // The standard-mandated behavior seems broken, since TINY() can't be
141     // subnormal.
142     return std::numeric_limits<T>::min(); // 0 -> TINY(x)
143   } else {
144     return std::ldexp(
145         static_cast<T>(1.0), std::ilogb(x) + 1 - PREC); // 2**(e-p)
146   }
147 }
148 
149 // NEAREST (16.9.139)
150 template <int PREC, typename T> inline T Nearest(T x, bool positive) {
151   auto spacing{Spacing<PREC>(x)};
152   if (x == 0) {
153     auto least{std::numeric_limits<T>::denorm_min()};
154     return positive ? least : -least;
155   } else {
156     return positive ? x + spacing : x - spacing;
157   }
158 }
159 
160 extern "C" {
161 
162 CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint4_4)(
163     CppTypeFor<TypeCategory::Real, 4> x) {
164   return Aint<CppTypeFor<TypeCategory::Real, 4>>(x);
165 }
166 CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint4_8)(
167     CppTypeFor<TypeCategory::Real, 4> x) {
168   return Aint<CppTypeFor<TypeCategory::Real, 8>>(x);
169 }
170 CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint8_4)(
171     CppTypeFor<TypeCategory::Real, 8> x) {
172   return Aint<CppTypeFor<TypeCategory::Real, 4>>(x);
173 }
174 CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint8_8)(
175     CppTypeFor<TypeCategory::Real, 8> x) {
176   return Aint<CppTypeFor<TypeCategory::Real, 8>>(x);
177 }
178 #if LONG_DOUBLE == 80
179 CppTypeFor<TypeCategory::Real, 10> RTNAME(Aint4_10)(
180     CppTypeFor<TypeCategory::Real, 4> x) {
181   return Aint<CppTypeFor<TypeCategory::Real, 10>>(x);
182 }
183 CppTypeFor<TypeCategory::Real, 10> RTNAME(Aint8_10)(
184     CppTypeFor<TypeCategory::Real, 8> x) {
185   return Aint<CppTypeFor<TypeCategory::Real, 10>>(x);
186 }
187 CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint10_4)(
188     CppTypeFor<TypeCategory::Real, 10> x) {
189   return Aint<CppTypeFor<TypeCategory::Real, 4>>(x);
190 }
191 CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint10_8)(
192     CppTypeFor<TypeCategory::Real, 10> x) {
193   return Aint<CppTypeFor<TypeCategory::Real, 8>>(x);
194 }
195 CppTypeFor<TypeCategory::Real, 10> RTNAME(Aint10_10)(
196     CppTypeFor<TypeCategory::Real, 10> x) {
197   return Aint<CppTypeFor<TypeCategory::Real, 10>>(x);
198 }
199 #elif LONG_DOUBLE == 128
200 CppTypeFor<TypeCategory::Real, 16> RTNAME(Aint4_16)(
201     CppTypeFor<TypeCategory::Real, 4> x) {
202   return Aint<CppTypeFor<TypeCategory::Real, 16>>(x);
203 }
204 CppTypeFor<TypeCategory::Real, 16> RTNAME(Aint8_16)(
205     CppTypeFor<TypeCategory::Real, 8> x) {
206   return Aint<CppTypeFor<TypeCategory::Real, 16>>(x);
207 }
208 CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint16_4)(
209     CppTypeFor<TypeCategory::Real, 16> x) {
210   return Aint<CppTypeFor<TypeCategory::Real, 4>>(x);
211 }
212 CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint16_8)(
213     CppTypeFor<TypeCategory::Real, 16> x) {
214   return Aint<CppTypeFor<TypeCategory::Real, 8>>(x);
215 }
216 CppTypeFor<TypeCategory::Real, 16> RTNAME(Aint16_16)(
217     CppTypeFor<TypeCategory::Real, 16> x) {
218   return Aint<CppTypeFor<TypeCategory::Real, 16>>(x);
219 }
220 #endif
221 
222 CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint4_4)(
223     CppTypeFor<TypeCategory::Real, 4> x) {
224   return Anint<CppTypeFor<TypeCategory::Real, 4>>(x);
225 }
226 CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint4_8)(
227     CppTypeFor<TypeCategory::Real, 4> x) {
228   return Anint<CppTypeFor<TypeCategory::Real, 8>>(x);
229 }
230 CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint8_4)(
231     CppTypeFor<TypeCategory::Real, 8> x) {
232   return Anint<CppTypeFor<TypeCategory::Real, 4>>(x);
233 }
234 CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint8_8)(
235     CppTypeFor<TypeCategory::Real, 8> x) {
236   return Anint<CppTypeFor<TypeCategory::Real, 8>>(x);
237 }
238 #if LONG_DOUBLE == 80
239 CppTypeFor<TypeCategory::Real, 10> RTNAME(Anint4_10)(
240     CppTypeFor<TypeCategory::Real, 4> x) {
241   return Anint<CppTypeFor<TypeCategory::Real, 10>>(x);
242 }
243 CppTypeFor<TypeCategory::Real, 10> RTNAME(Anint8_10)(
244     CppTypeFor<TypeCategory::Real, 8> x) {
245   return Anint<CppTypeFor<TypeCategory::Real, 10>>(x);
246 }
247 CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint10_4)(
248     CppTypeFor<TypeCategory::Real, 10> x) {
249   return Anint<CppTypeFor<TypeCategory::Real, 4>>(x);
250 }
251 CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint10_8)(
252     CppTypeFor<TypeCategory::Real, 10> x) {
253   return Anint<CppTypeFor<TypeCategory::Real, 8>>(x);
254 }
255 CppTypeFor<TypeCategory::Real, 10> RTNAME(Anint10_10)(
256     CppTypeFor<TypeCategory::Real, 10> x) {
257   return Anint<CppTypeFor<TypeCategory::Real, 10>>(x);
258 }
259 #elif LONG_DOUBLE == 128
260 CppTypeFor<TypeCategory::Real, 16> RTNAME(Anint4_16)(
261     CppTypeFor<TypeCategory::Real, 4> x) {
262   return Anint<CppTypeFor<TypeCategory::Real, 16>>(x);
263 }
264 CppTypeFor<TypeCategory::Real, 16> RTNAME(Anint8_16)(
265     CppTypeFor<TypeCategory::Real, 8> x) {
266   return Anint<CppTypeFor<TypeCategory::Real, 16>>(x);
267 }
268 CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint16_4)(
269     CppTypeFor<TypeCategory::Real, 16> x) {
270   return Anint<CppTypeFor<TypeCategory::Real, 4>>(x);
271 }
272 CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint16_8)(
273     CppTypeFor<TypeCategory::Real, 16> x) {
274   return Anint<CppTypeFor<TypeCategory::Real, 8>>(x);
275 }
276 CppTypeFor<TypeCategory::Real, 16> RTNAME(Anint16_16)(
277     CppTypeFor<TypeCategory::Real, 16> x) {
278   return Anint<CppTypeFor<TypeCategory::Real, 16>>(x);
279 }
280 #endif
281 
282 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling4_1)(
283     CppTypeFor<TypeCategory::Real, 4> x) {
284   return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
285 }
286 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling4_2)(
287     CppTypeFor<TypeCategory::Real, 4> x) {
288   return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
289 }
290 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling4_4)(
291     CppTypeFor<TypeCategory::Real, 4> x) {
292   return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
293 }
294 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling4_8)(
295     CppTypeFor<TypeCategory::Real, 4> x) {
296   return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
297 }
298 #ifdef __SIZEOF_INT128__
299 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling4_16)(
300     CppTypeFor<TypeCategory::Real, 4> x) {
301   return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
302 }
303 #endif
304 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling8_1)(
305     CppTypeFor<TypeCategory::Real, 8> x) {
306   return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
307 }
308 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling8_2)(
309     CppTypeFor<TypeCategory::Real, 8> x) {
310   return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
311 }
312 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling8_4)(
313     CppTypeFor<TypeCategory::Real, 8> x) {
314   return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
315 }
316 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling8_8)(
317     CppTypeFor<TypeCategory::Real, 8> x) {
318   return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
319 }
320 #ifdef __SIZEOF_INT128__
321 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling8_16)(
322     CppTypeFor<TypeCategory::Real, 8> x) {
323   return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
324 }
325 #endif
326 #if LONG_DOUBLE == 80
327 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling10_1)(
328     CppTypeFor<TypeCategory::Real, 10> x) {
329   return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
330 }
331 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling10_2)(
332     CppTypeFor<TypeCategory::Real, 10> x) {
333   return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
334 }
335 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling10_4)(
336     CppTypeFor<TypeCategory::Real, 10> x) {
337   return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
338 }
339 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling10_8)(
340     CppTypeFor<TypeCategory::Real, 10> x) {
341   return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
342 }
343 #ifdef __SIZEOF_INT128__
344 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling10_16)(
345     CppTypeFor<TypeCategory::Real, 10> x) {
346   return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
347 }
348 #endif
349 #else
350 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling16_1)(
351     CppTypeFor<TypeCategory::Real, 16> x) {
352   return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
353 }
354 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling16_2)(
355     CppTypeFor<TypeCategory::Real, 16> x) {
356   return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
357 }
358 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling16_4)(
359     CppTypeFor<TypeCategory::Real, 16> x) {
360   return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
361 }
362 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling16_8)(
363     CppTypeFor<TypeCategory::Real, 16> x) {
364   return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
365 }
366 #ifdef __SIZEOF_INT128__
367 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling16_16)(
368     CppTypeFor<TypeCategory::Real, 16> x) {
369   return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
370 }
371 #endif
372 #endif
373 
374 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent4_4)(
375     CppTypeFor<TypeCategory::Real, 4> x) {
376   return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
377 }
378 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent4_8)(
379     CppTypeFor<TypeCategory::Real, 4> x) {
380   return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
381 }
382 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent8_4)(
383     CppTypeFor<TypeCategory::Real, 8> x) {
384   return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
385 }
386 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent8_8)(
387     CppTypeFor<TypeCategory::Real, 8> x) {
388   return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
389 }
390 #if LONG_DOUBLE == 80
391 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent10_4)(
392     CppTypeFor<TypeCategory::Real, 10> x) {
393   return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
394 }
395 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent10_8)(
396     CppTypeFor<TypeCategory::Real, 10> x) {
397   return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
398 }
399 #elif LONG_DOUBLE == 128
400 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent16_4)(
401     CppTypeFor<TypeCategory::Real, 16> x) {
402   return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
403 }
404 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent16_8)(
405     CppTypeFor<TypeCategory::Real, 16> x) {
406   return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
407 }
408 #endif
409 
410 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor4_1)(
411     CppTypeFor<TypeCategory::Real, 4> x) {
412   return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
413 }
414 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor4_2)(
415     CppTypeFor<TypeCategory::Real, 4> x) {
416   return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
417 }
418 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor4_4)(
419     CppTypeFor<TypeCategory::Real, 4> x) {
420   return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
421 }
422 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor4_8)(
423     CppTypeFor<TypeCategory::Real, 4> x) {
424   return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
425 }
426 #ifdef __SIZEOF_INT128__
427 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor4_16)(
428     CppTypeFor<TypeCategory::Real, 4> x) {
429   return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
430 }
431 #endif
432 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor8_1)(
433     CppTypeFor<TypeCategory::Real, 8> x) {
434   return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
435 }
436 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor8_2)(
437     CppTypeFor<TypeCategory::Real, 8> x) {
438   return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
439 }
440 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor8_4)(
441     CppTypeFor<TypeCategory::Real, 8> x) {
442   return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
443 }
444 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor8_8)(
445     CppTypeFor<TypeCategory::Real, 8> x) {
446   return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
447 }
448 #ifdef __SIZEOF_INT128__
449 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor8_16)(
450     CppTypeFor<TypeCategory::Real, 8> x) {
451   return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
452 }
453 #endif
454 #if LONG_DOUBLE == 80
455 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor10_1)(
456     CppTypeFor<TypeCategory::Real, 10> x) {
457   return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
458 }
459 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor10_2)(
460     CppTypeFor<TypeCategory::Real, 10> x) {
461   return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
462 }
463 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor10_4)(
464     CppTypeFor<TypeCategory::Real, 10> x) {
465   return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
466 }
467 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor10_8)(
468     CppTypeFor<TypeCategory::Real, 10> x) {
469   return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
470 }
471 #ifdef __SIZEOF_INT128__
472 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor10_16)(
473     CppTypeFor<TypeCategory::Real, 10> x) {
474   return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
475 }
476 #endif
477 #else
478 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor16_1)(
479     CppTypeFor<TypeCategory::Real, 16> x) {
480   return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
481 }
482 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor16_2)(
483     CppTypeFor<TypeCategory::Real, 16> x) {
484   return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
485 }
486 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor16_4)(
487     CppTypeFor<TypeCategory::Real, 16> x) {
488   return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
489 }
490 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor16_8)(
491     CppTypeFor<TypeCategory::Real, 16> x) {
492   return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
493 }
494 #ifdef __SIZEOF_INT128__
495 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor16_16)(
496     CppTypeFor<TypeCategory::Real, 16> x) {
497   return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
498 }
499 #endif
500 #endif
501 
502 CppTypeFor<TypeCategory::Real, 4> RTNAME(Fraction4)(
503     CppTypeFor<TypeCategory::Real, 4> x) {
504   return Fraction(x);
505 }
506 CppTypeFor<TypeCategory::Real, 8> RTNAME(Fraction8)(
507     CppTypeFor<TypeCategory::Real, 8> x) {
508   return Fraction(x);
509 }
510 #if LONG_DOUBLE == 80
511 CppTypeFor<TypeCategory::Real, 10> RTNAME(Fraction10)(
512     CppTypeFor<TypeCategory::Real, 10> x) {
513   return Fraction(x);
514 }
515 #elif LONG_DOUBLE == 128
516 CppTypeFor<TypeCategory::Real, 16> RTNAME(Fraction16)(
517     CppTypeFor<TypeCategory::Real, 16> x) {
518   return Fraction(x);
519 }
520 #endif
521 
522 bool RTNAME(IsFinite4)(CppTypeFor<TypeCategory::Real, 4> x) {
523   return std::isfinite(x);
524 }
525 bool RTNAME(IsFinite8)(CppTypeFor<TypeCategory::Real, 8> x) {
526   return std::isfinite(x);
527 }
528 #if LONG_DOUBLE == 80
529 bool RTNAME(IsFinite10)(CppTypeFor<TypeCategory::Real, 10> x) {
530   return std::isfinite(x);
531 }
532 #elif LONG_DOUBLE == 128
533 bool RTNAME(IsFinite16)(CppTypeFor<TypeCategory::Real, 16> x) {
534   return std::isfinite(x);
535 }
536 #endif
537 
538 bool RTNAME(IsNaN4)(CppTypeFor<TypeCategory::Real, 4> x) {
539   return std::isnan(x);
540 }
541 bool RTNAME(IsNaN8)(CppTypeFor<TypeCategory::Real, 8> x) {
542   return std::isnan(x);
543 }
544 #if LONG_DOUBLE == 80
545 bool RTNAME(IsNaN10)(CppTypeFor<TypeCategory::Real, 10> x) {
546   return std::isnan(x);
547 }
548 #elif LONG_DOUBLE == 128
549 bool RTNAME(IsNaN16)(CppTypeFor<TypeCategory::Real, 16> x) {
550   return std::isnan(x);
551 }
552 #endif
553 
554 CppTypeFor<TypeCategory::Integer, 1> RTNAME(ModInteger1)(
555     CppTypeFor<TypeCategory::Integer, 1> x,
556     CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile,
557     int sourceLine) {
558   return IntMod<false>(x, p, sourceFile, sourceLine);
559 }
560 CppTypeFor<TypeCategory::Integer, 2> RTNAME(ModInteger2)(
561     CppTypeFor<TypeCategory::Integer, 2> x,
562     CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile,
563     int sourceLine) {
564   return IntMod<false>(x, p, sourceFile, sourceLine);
565 }
566 CppTypeFor<TypeCategory::Integer, 4> RTNAME(ModInteger4)(
567     CppTypeFor<TypeCategory::Integer, 4> x,
568     CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile,
569     int sourceLine) {
570   return IntMod<false>(x, p, sourceFile, sourceLine);
571 }
572 CppTypeFor<TypeCategory::Integer, 8> RTNAME(ModInteger8)(
573     CppTypeFor<TypeCategory::Integer, 8> x,
574     CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile,
575     int sourceLine) {
576   return IntMod<false>(x, p, sourceFile, sourceLine);
577 }
578 #ifdef __SIZEOF_INT128__
579 CppTypeFor<TypeCategory::Integer, 16> RTNAME(ModInteger16)(
580     CppTypeFor<TypeCategory::Integer, 16> x,
581     CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile,
582     int sourceLine) {
583   return IntMod<false>(x, p, sourceFile, sourceLine);
584 }
585 #endif
586 CppTypeFor<TypeCategory::Real, 4> RTNAME(ModReal4)(
587     CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p,
588     const char *sourceFile, int sourceLine) {
589   return RealMod<false>(x, p, sourceFile, sourceLine);
590 }
591 CppTypeFor<TypeCategory::Real, 8> RTNAME(ModReal8)(
592     CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p,
593     const char *sourceFile, int sourceLine) {
594   return RealMod<false>(x, p, sourceFile, sourceLine);
595 }
596 #if LONG_DOUBLE == 80
597 CppTypeFor<TypeCategory::Real, 10> RTNAME(ModReal10)(
598     CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p,
599     const char *sourceFile, int sourceLine) {
600   return RealMod<false>(x, p, sourceFile, sourceLine);
601 }
602 #elif LONG_DOUBLE == 128
603 CppTypeFor<TypeCategory::Real, 16> RTNAME(ModReal16)(
604     CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p,
605     const char *sourceFile, int sourceLine) {
606   return RealMod<false>(x, p, sourceFile, sourceLine);
607 }
608 #endif
609 
610 CppTypeFor<TypeCategory::Integer, 1> RTNAME(ModuloInteger1)(
611     CppTypeFor<TypeCategory::Integer, 1> x,
612     CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile,
613     int sourceLine) {
614   return IntMod<true>(x, p, sourceFile, sourceLine);
615 }
616 CppTypeFor<TypeCategory::Integer, 2> RTNAME(ModuloInteger2)(
617     CppTypeFor<TypeCategory::Integer, 2> x,
618     CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile,
619     int sourceLine) {
620   return IntMod<true>(x, p, sourceFile, sourceLine);
621 }
622 CppTypeFor<TypeCategory::Integer, 4> RTNAME(ModuloInteger4)(
623     CppTypeFor<TypeCategory::Integer, 4> x,
624     CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile,
625     int sourceLine) {
626   return IntMod<true>(x, p, sourceFile, sourceLine);
627 }
628 CppTypeFor<TypeCategory::Integer, 8> RTNAME(ModuloInteger8)(
629     CppTypeFor<TypeCategory::Integer, 8> x,
630     CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile,
631     int sourceLine) {
632   return IntMod<true>(x, p, sourceFile, sourceLine);
633 }
634 #ifdef __SIZEOF_INT128__
635 CppTypeFor<TypeCategory::Integer, 16> RTNAME(ModuloInteger16)(
636     CppTypeFor<TypeCategory::Integer, 16> x,
637     CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile,
638     int sourceLine) {
639   return IntMod<true>(x, p, sourceFile, sourceLine);
640 }
641 #endif
642 CppTypeFor<TypeCategory::Real, 4> RTNAME(ModuloReal4)(
643     CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p,
644     const char *sourceFile, int sourceLine) {
645   return RealMod<true>(x, p, sourceFile, sourceLine);
646 }
647 CppTypeFor<TypeCategory::Real, 8> RTNAME(ModuloReal8)(
648     CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p,
649     const char *sourceFile, int sourceLine) {
650   return RealMod<true>(x, p, sourceFile, sourceLine);
651 }
652 #if LONG_DOUBLE == 80
653 CppTypeFor<TypeCategory::Real, 10> RTNAME(ModuloReal10)(
654     CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p,
655     const char *sourceFile, int sourceLine) {
656   return RealMod<true>(x, p, sourceFile, sourceLine);
657 }
658 #elif LONG_DOUBLE == 128
659 CppTypeFor<TypeCategory::Real, 16> RTNAME(ModuloReal16)(
660     CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p,
661     const char *sourceFile, int sourceLine) {
662   return RealMod<true>(x, p, sourceFile, sourceLine);
663 }
664 #endif
665 
666 CppTypeFor<TypeCategory::Real, 4> RTNAME(Nearest4)(
667     CppTypeFor<TypeCategory::Real, 4> x, bool positive) {
668   return Nearest<24>(x, positive);
669 }
670 CppTypeFor<TypeCategory::Real, 8> RTNAME(Nearest8)(
671     CppTypeFor<TypeCategory::Real, 8> x, bool positive) {
672   return Nearest<53>(x, positive);
673 }
674 #if LONG_DOUBLE == 80
675 CppTypeFor<TypeCategory::Real, 10> RTNAME(Nearest10)(
676     CppTypeFor<TypeCategory::Real, 10> x, bool positive) {
677   return Nearest<64>(x, positive);
678 }
679 #elif LONG_DOUBLE == 128
680 CppTypeFor<TypeCategory::Real, 16> RTNAME(Nearest16)(
681     CppTypeFor<TypeCategory::Real, 16> x, bool positive) {
682   return Nearest<113>(x, positive);
683 }
684 #endif
685 
686 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint4_1)(
687     CppTypeFor<TypeCategory::Real, 4> x) {
688   return Anint<CppTypeFor<TypeCategory::Integer, 1>>(x);
689 }
690 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint4_2)(
691     CppTypeFor<TypeCategory::Real, 4> x) {
692   return Anint<CppTypeFor<TypeCategory::Integer, 2>>(x);
693 }
694 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint4_4)(
695     CppTypeFor<TypeCategory::Real, 4> x) {
696   return Anint<CppTypeFor<TypeCategory::Integer, 4>>(x);
697 }
698 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint4_8)(
699     CppTypeFor<TypeCategory::Real, 4> x) {
700   return Anint<CppTypeFor<TypeCategory::Integer, 8>>(x);
701 }
702 #ifdef __SIZEOF_INT128__
703 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint4_16)(
704     CppTypeFor<TypeCategory::Real, 4> x) {
705   return Anint<CppTypeFor<TypeCategory::Integer, 16>>(x);
706 }
707 #endif
708 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint8_1)(
709     CppTypeFor<TypeCategory::Real, 8> x) {
710   return Anint<CppTypeFor<TypeCategory::Integer, 1>>(x);
711 }
712 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint8_2)(
713     CppTypeFor<TypeCategory::Real, 8> x) {
714   return Anint<CppTypeFor<TypeCategory::Integer, 2>>(x);
715 }
716 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint8_4)(
717     CppTypeFor<TypeCategory::Real, 8> x) {
718   return Anint<CppTypeFor<TypeCategory::Integer, 4>>(x);
719 }
720 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint8_8)(
721     CppTypeFor<TypeCategory::Real, 8> x) {
722   return Anint<CppTypeFor<TypeCategory::Integer, 8>>(x);
723 }
724 #ifdef __SIZEOF_INT128__
725 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint8_16)(
726     CppTypeFor<TypeCategory::Real, 8> x) {
727   return Anint<CppTypeFor<TypeCategory::Integer, 16>>(x);
728 }
729 #endif
730 #if LONG_DOUBLE == 80
731 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint10_1)(
732     CppTypeFor<TypeCategory::Real, 10> x) {
733   return Anint<CppTypeFor<TypeCategory::Integer, 1>>(x);
734 }
735 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint10_2)(
736     CppTypeFor<TypeCategory::Real, 10> x) {
737   return Anint<CppTypeFor<TypeCategory::Integer, 2>>(x);
738 }
739 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint10_4)(
740     CppTypeFor<TypeCategory::Real, 10> x) {
741   return Anint<CppTypeFor<TypeCategory::Integer, 4>>(x);
742 }
743 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint10_8)(
744     CppTypeFor<TypeCategory::Real, 10> x) {
745   return Anint<CppTypeFor<TypeCategory::Integer, 8>>(x);
746 }
747 #ifdef __SIZEOF_INT128__
748 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint10_16)(
749     CppTypeFor<TypeCategory::Real, 10> x) {
750   return Anint<CppTypeFor<TypeCategory::Integer, 16>>(x);
751 }
752 #endif
753 #else
754 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint16_1)(
755     CppTypeFor<TypeCategory::Real, 16> x) {
756   return Anint<CppTypeFor<TypeCategory::Integer, 1>>(x);
757 }
758 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint16_2)(
759     CppTypeFor<TypeCategory::Real, 16> x) {
760   return Anint<CppTypeFor<TypeCategory::Integer, 2>>(x);
761 }
762 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint16_4)(
763     CppTypeFor<TypeCategory::Real, 16> x) {
764   return Anint<CppTypeFor<TypeCategory::Integer, 4>>(x);
765 }
766 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint16_8)(
767     CppTypeFor<TypeCategory::Real, 16> x) {
768   return Anint<CppTypeFor<TypeCategory::Integer, 8>>(x);
769 }
770 #ifdef __SIZEOF_INT128__
771 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint16_16)(
772     CppTypeFor<TypeCategory::Real, 16> x) {
773   return Anint<CppTypeFor<TypeCategory::Integer, 16>>(x);
774 }
775 #endif
776 #endif
777 
778 CppTypeFor<TypeCategory::Real, 4> RTNAME(RRSpacing4)(
779     CppTypeFor<TypeCategory::Real, 4> x) {
780   return RRSpacing<24>(x);
781 }
782 CppTypeFor<TypeCategory::Real, 8> RTNAME(RRSpacing8)(
783     CppTypeFor<TypeCategory::Real, 8> x) {
784   return RRSpacing<53>(x);
785 }
786 #if LONG_DOUBLE == 80
787 CppTypeFor<TypeCategory::Real, 10> RTNAME(RRSpacing10)(
788     CppTypeFor<TypeCategory::Real, 10> x) {
789   return RRSpacing<64>(x);
790 }
791 #elif LONG_DOUBLE == 128
792 CppTypeFor<TypeCategory::Real, 16> RTNAME(RRSpacing16)(
793     CppTypeFor<TypeCategory::Real, 16> x) {
794   return RRSpacing<113>(x);
795 }
796 #endif
797 
798 CppTypeFor<TypeCategory::Real, 4> RTNAME(SetExponent4)(
799     CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) {
800   return SetExponent(x, p);
801 }
802 CppTypeFor<TypeCategory::Real, 8> RTNAME(SetExponent8)(
803     CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) {
804   return SetExponent(x, p);
805 }
806 #if LONG_DOUBLE == 80
807 CppTypeFor<TypeCategory::Real, 10> RTNAME(SetExponent10)(
808     CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) {
809   return SetExponent(x, p);
810 }
811 #elif LONG_DOUBLE == 128
812 CppTypeFor<TypeCategory::Real, 16> RTNAME(SetExponent16)(
813     CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) {
814   return SetExponent(x, p);
815 }
816 #endif
817 
818 CppTypeFor<TypeCategory::Real, 4> RTNAME(Scale4)(
819     CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) {
820   return Scale(x, p);
821 }
822 CppTypeFor<TypeCategory::Real, 8> RTNAME(Scale8)(
823     CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) {
824   return Scale(x, p);
825 }
826 #if LONG_DOUBLE == 80
827 CppTypeFor<TypeCategory::Real, 10> RTNAME(Scale10)(
828     CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) {
829   return Scale(x, p);
830 }
831 #elif LONG_DOUBLE == 128
832 CppTypeFor<TypeCategory::Real, 16> RTNAME(Scale16)(
833     CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) {
834   return Scale(x, p);
835 }
836 #endif
837 
838 CppTypeFor<TypeCategory::Real, 4> RTNAME(Spacing4)(
839     CppTypeFor<TypeCategory::Real, 4> x) {
840   return Spacing<24>(x);
841 }
842 CppTypeFor<TypeCategory::Real, 8> RTNAME(Spacing8)(
843     CppTypeFor<TypeCategory::Real, 8> x) {
844   return Spacing<53>(x);
845 }
846 #if LONG_DOUBLE == 80
847 CppTypeFor<TypeCategory::Real, 10> RTNAME(Spacing10)(
848     CppTypeFor<TypeCategory::Real, 10> x) {
849   return Spacing<64>(x);
850 }
851 #elif LONG_DOUBLE == 128
852 CppTypeFor<TypeCategory::Real, 16> RTNAME(Spacing16)(
853     CppTypeFor<TypeCategory::Real, 16> x) {
854   return Spacing<113>(x);
855 }
856 #endif
857 } // extern "C"
858 } // namespace Fortran::runtime
859