[AArch64,ELF] Restrict MOVZ/MOVK to non-PIC large code model (#70178)
[llvm-project.git] / flang / runtime / numeric.cpp
blobcd54e6b54a2e536f37ada48f3391fc6b2df1b9f3
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 //===----------------------------------------------------------------------===//
9 #include "flang/Runtime/numeric.h"
10 #include "terminator.h"
11 #include "flang/Common/float128.h"
12 #include <cfloat>
13 #include <climits>
14 #include <cmath>
15 #include <limits>
17 namespace Fortran::runtime {
19 template <typename RES>
20 inline RES getIntArgValue(const char *source, int line, void *arg, int kind,
21 std::int64_t defaultValue, int resKind) {
22 RES res;
23 if (!arg) {
24 res = static_cast<RES>(defaultValue);
25 } else if (kind == 1) {
26 res = static_cast<RES>(
27 *static_cast<CppTypeFor<TypeCategory::Integer, 1> *>(arg));
28 } else if (kind == 2) {
29 res = static_cast<RES>(
30 *static_cast<CppTypeFor<TypeCategory::Integer, 2> *>(arg));
31 } else if (kind == 4) {
32 res = static_cast<RES>(
33 *static_cast<CppTypeFor<TypeCategory::Integer, 4> *>(arg));
34 } else if (kind == 8) {
35 res = static_cast<RES>(
36 *static_cast<CppTypeFor<TypeCategory::Integer, 8> *>(arg));
37 #ifdef __SIZEOF_INT128__
38 } else if (kind == 16) {
39 if (resKind != 16) {
40 Terminator{source, line}.Crash("Unexpected integer kind in runtime");
42 res = static_cast<RES>(
43 *static_cast<CppTypeFor<TypeCategory::Integer, 16> *>(arg));
44 #endif
45 } else {
46 Terminator{source, line}.Crash("Unexpected integer kind in runtime");
48 return res;
51 // NINT (16.9.141)
52 template <typename RESULT, typename ARG> inline RESULT Nint(ARG x) {
53 if (x >= 0) {
54 return std::trunc(x + ARG{0.5});
55 } else {
56 return std::trunc(x - ARG{0.5});
60 // CEILING & FLOOR (16.9.43, .79)
61 template <typename RESULT, typename ARG> inline RESULT Ceiling(ARG x) {
62 return std::ceil(x);
64 template <typename RESULT, typename ARG> inline RESULT Floor(ARG x) {
65 return std::floor(x);
68 // EXPONENT (16.9.75)
69 template <typename RESULT, typename ARG> inline RESULT Exponent(ARG x) {
70 if (std::isinf(x) || std::isnan(x)) {
71 return std::numeric_limits<RESULT>::max(); // +/-Inf, NaN -> HUGE(0)
72 } else if (x == 0) {
73 return 0; // 0 -> 0
74 } else {
75 return std::ilogb(x) + 1;
79 // FRACTION (16.9.80)
80 template <typename T> inline T Fraction(T x) {
81 if (std::isnan(x)) {
82 return x; // NaN -> same NaN
83 } else if (std::isinf(x)) {
84 return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN
85 } else if (x == 0) {
86 return x; // 0 -> same 0
87 } else {
88 int ignoredExp;
89 return std::frexp(x, &ignoredExp);
93 // MOD & MODULO (16.9.135, .136)
94 template <bool IS_MODULO, typename T>
95 inline T IntMod(T x, T p, const char *sourceFile, int sourceLine) {
96 if (p == 0) {
97 Terminator{sourceFile, sourceLine}.Crash(
98 IS_MODULO ? "MODULO with P==0" : "MOD with P==0");
100 auto mod{x - (x / p) * p};
101 if (IS_MODULO && (x > 0) != (p > 0)) {
102 mod += p;
104 return mod;
106 template <bool IS_MODULO, typename T>
107 inline T RealMod(T a, T p, const char *sourceFile, int sourceLine) {
108 if (p == 0) {
109 Terminator{sourceFile, sourceLine}.Crash(
110 IS_MODULO ? "MODULO with P==0" : "MOD with P==0");
112 T quotient{a / p};
113 if (std::isinf(quotient) && std::isfinite(a) && std::isfinite(p)) {
114 // a/p overflowed -- so it must be an integer, and the result
115 // must be a zero of the same sign as one of the operands.
116 return std::copysign(T{}, IS_MODULO ? p : a);
118 T toInt{IS_MODULO ? std::floor(quotient) : std::trunc(quotient)};
119 return a - toInt * p;
122 // RRSPACING (16.9.164)
123 template <int PREC, typename T> inline T RRSpacing(T x) {
124 if (std::isnan(x)) {
125 return x; // NaN -> same NaN
126 } else if (std::isinf(x)) {
127 return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN
128 } else if (x == 0) {
129 return 0; // 0 -> 0
130 } else {
131 return std::ldexp(std::abs(x), PREC - (std::ilogb(x) + 1));
135 // SCALE (16.9.166)
136 template <typename T> inline T Scale(T x, std::int64_t p) {
137 auto ip{static_cast<int>(p)};
138 if (ip != p) {
139 ip = p < 0 ? std::numeric_limits<int>::min()
140 : std::numeric_limits<int>::max();
142 return std::ldexp(x, p); // x*2**p
145 // SELECTED_INT_KIND (16.9.169)
146 template <typename T>
147 inline CppTypeFor<TypeCategory::Integer, 4> SelectedIntKind(T x) {
148 if (x <= 2) {
149 return 1;
150 } else if (x <= 4) {
151 return 2;
152 } else if (x <= 9) {
153 return 4;
154 } else if (x <= 18) {
155 return 8;
156 #ifdef __SIZEOF_INT128__
157 } else if (x <= 38) {
158 return 16;
159 #endif
161 return -1;
164 // SELECTED_REAL_KIND (16.9.170)
165 template <typename P, typename R, typename D>
166 inline CppTypeFor<TypeCategory::Integer, 4> SelectedRealKind(P p, R r, D d) {
167 if (d != 2) {
168 return -5;
171 int error{0};
172 int kind{0};
173 if (p <= 3) {
174 kind = 2;
175 } else if (p <= 6) {
176 kind = 4;
177 } else if (p <= 15) {
178 kind = 8;
179 #if LDBL_MANT_DIG == 64
180 } else if (p <= 18) {
181 kind = 10;
182 } else if (p <= 33) {
183 kind = 16;
184 #elif LDBL_MANT_DIG == 113
185 } else if (p <= 33) {
186 kind = 16;
187 #endif
188 } else {
189 error -= 1;
192 if (r <= 4) {
193 kind = kind < 2 ? 2 : kind;
194 } else if (r <= 37) {
195 kind = kind < 3 ? (p == 3 ? 4 : 3) : kind;
196 } else if (r <= 307) {
197 kind = kind < 8 ? 8 : kind;
198 #if LDBL_MANT_DIG == 64
199 } else if (r <= 4931) {
200 kind = kind < 10 ? 10 : kind;
201 #elif LDBL_MANT_DIG == 113
202 } else if (r <= 4931) {
203 kind = kind < 16 ? 16 : kind;
204 #endif
205 } else {
206 error -= 2;
209 return error ? error : kind;
212 // SET_EXPONENT (16.9.171)
213 template <typename T> inline T SetExponent(T x, std::int64_t p) {
214 if (std::isnan(x)) {
215 return x; // NaN -> same NaN
216 } else if (std::isinf(x)) {
217 return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN
218 } else if (x == 0) {
219 return x; // return negative zero if x is negative zero
220 } else {
221 int expo{std::ilogb(x) + 1};
222 auto ip{static_cast<int>(p - expo)};
223 if (ip != p - expo) {
224 ip = p < 0 ? std::numeric_limits<int>::min()
225 : std::numeric_limits<int>::max();
227 return std::ldexp(x, ip); // x*2**(p-e)
231 // SPACING (16.9.180)
232 template <int PREC, typename T> inline T Spacing(T x) {
233 if (std::isnan(x)) {
234 return x; // NaN -> same NaN
235 } else if (std::isinf(x)) {
236 return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN
237 } else if (x == 0) {
238 // The standard-mandated behavior seems broken, since TINY() can't be
239 // subnormal.
240 return std::numeric_limits<T>::min(); // 0 -> TINY(x)
241 } else {
242 T result{
243 std::ldexp(static_cast<T>(1.0), std::ilogb(x) + 1 - PREC)}; // 2**(e-p)
244 return result == 0 ? /*TINY(x)*/ std::numeric_limits<T>::min() : result;
248 // NEAREST (16.9.139)
249 template <int PREC, typename T> inline T Nearest(T x, bool positive) {
250 auto spacing{Spacing<PREC>(x)};
251 if (x == 0) {
252 auto least{std::numeric_limits<T>::denorm_min()};
253 return positive ? least : -least;
254 } else {
255 return positive ? x + spacing : x - spacing;
259 // Exponentiation operator for (Real ** Integer) cases (10.1.5.2.1).
260 template <typename BTy, typename ETy> BTy FPowI(BTy base, ETy exp) {
261 if (exp == ETy{0})
262 return BTy{1};
263 bool isNegativePower{exp < ETy{0}};
264 bool isMinPower{exp == std::numeric_limits<ETy>::min()};
265 if (isMinPower) {
266 exp = std::numeric_limits<ETy>::max();
267 } else if (isNegativePower) {
268 exp = -exp;
270 BTy result{1};
271 BTy origBase{base};
272 while (true) {
273 if (exp & ETy{1}) {
274 result *= base;
276 exp >>= 1;
277 if (exp == ETy{0}) {
278 break;
280 base *= base;
282 if (isMinPower) {
283 result *= origBase;
285 if (isNegativePower) {
286 result = BTy{1} / result;
288 return result;
291 extern "C" {
293 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling4_1)(
294 CppTypeFor<TypeCategory::Real, 4> x) {
295 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
297 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling4_2)(
298 CppTypeFor<TypeCategory::Real, 4> x) {
299 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
301 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling4_4)(
302 CppTypeFor<TypeCategory::Real, 4> x) {
303 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
305 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling4_8)(
306 CppTypeFor<TypeCategory::Real, 4> x) {
307 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
309 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
310 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling4_16)(
311 CppTypeFor<TypeCategory::Real, 4> x) {
312 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
314 #endif
315 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling8_1)(
316 CppTypeFor<TypeCategory::Real, 8> x) {
317 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
319 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling8_2)(
320 CppTypeFor<TypeCategory::Real, 8> x) {
321 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
323 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling8_4)(
324 CppTypeFor<TypeCategory::Real, 8> x) {
325 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
327 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling8_8)(
328 CppTypeFor<TypeCategory::Real, 8> x) {
329 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
331 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
332 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling8_16)(
333 CppTypeFor<TypeCategory::Real, 8> x) {
334 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
336 #endif
337 #if LDBL_MANT_DIG == 64
338 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling10_1)(
339 CppTypeFor<TypeCategory::Real, 10> x) {
340 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
342 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling10_2)(
343 CppTypeFor<TypeCategory::Real, 10> x) {
344 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
346 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling10_4)(
347 CppTypeFor<TypeCategory::Real, 10> x) {
348 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
350 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling10_8)(
351 CppTypeFor<TypeCategory::Real, 10> x) {
352 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
354 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
355 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling10_16)(
356 CppTypeFor<TypeCategory::Real, 10> x) {
357 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
359 #endif
360 #elif LDBL_MANT_DIG == 113
361 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling16_1)(
362 CppTypeFor<TypeCategory::Real, 16> x) {
363 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
365 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling16_2)(
366 CppTypeFor<TypeCategory::Real, 16> x) {
367 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
369 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling16_4)(
370 CppTypeFor<TypeCategory::Real, 16> x) {
371 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
373 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling16_8)(
374 CppTypeFor<TypeCategory::Real, 16> x) {
375 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
377 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
378 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling16_16)(
379 CppTypeFor<TypeCategory::Real, 16> x) {
380 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
382 #endif
383 #endif
385 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent4_4)(
386 CppTypeFor<TypeCategory::Real, 4> x) {
387 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
389 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent4_8)(
390 CppTypeFor<TypeCategory::Real, 4> x) {
391 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
393 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent8_4)(
394 CppTypeFor<TypeCategory::Real, 8> x) {
395 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
397 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent8_8)(
398 CppTypeFor<TypeCategory::Real, 8> x) {
399 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
401 #if LDBL_MANT_DIG == 64
402 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent10_4)(
403 CppTypeFor<TypeCategory::Real, 10> x) {
404 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
406 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent10_8)(
407 CppTypeFor<TypeCategory::Real, 10> x) {
408 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
410 #elif LDBL_MANT_DIG == 113
411 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent16_4)(
412 CppTypeFor<TypeCategory::Real, 16> x) {
413 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
415 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent16_8)(
416 CppTypeFor<TypeCategory::Real, 16> x) {
417 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
419 #endif
421 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor4_1)(
422 CppTypeFor<TypeCategory::Real, 4> x) {
423 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
425 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor4_2)(
426 CppTypeFor<TypeCategory::Real, 4> x) {
427 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
429 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor4_4)(
430 CppTypeFor<TypeCategory::Real, 4> x) {
431 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
433 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor4_8)(
434 CppTypeFor<TypeCategory::Real, 4> x) {
435 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
437 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
438 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor4_16)(
439 CppTypeFor<TypeCategory::Real, 4> x) {
440 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
442 #endif
443 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor8_1)(
444 CppTypeFor<TypeCategory::Real, 8> x) {
445 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
447 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor8_2)(
448 CppTypeFor<TypeCategory::Real, 8> x) {
449 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
451 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor8_4)(
452 CppTypeFor<TypeCategory::Real, 8> x) {
453 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
455 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor8_8)(
456 CppTypeFor<TypeCategory::Real, 8> x) {
457 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
459 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
460 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor8_16)(
461 CppTypeFor<TypeCategory::Real, 8> x) {
462 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
464 #endif
465 #if LDBL_MANT_DIG == 64
466 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor10_1)(
467 CppTypeFor<TypeCategory::Real, 10> x) {
468 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
470 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor10_2)(
471 CppTypeFor<TypeCategory::Real, 10> x) {
472 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
474 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor10_4)(
475 CppTypeFor<TypeCategory::Real, 10> x) {
476 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
478 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor10_8)(
479 CppTypeFor<TypeCategory::Real, 10> x) {
480 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
482 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
483 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor10_16)(
484 CppTypeFor<TypeCategory::Real, 10> x) {
485 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
487 #endif
488 #elif LDBL_MANT_DIG == 113
489 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor16_1)(
490 CppTypeFor<TypeCategory::Real, 16> x) {
491 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
493 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor16_2)(
494 CppTypeFor<TypeCategory::Real, 16> x) {
495 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
497 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor16_4)(
498 CppTypeFor<TypeCategory::Real, 16> x) {
499 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
501 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor16_8)(
502 CppTypeFor<TypeCategory::Real, 16> x) {
503 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
505 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
506 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor16_16)(
507 CppTypeFor<TypeCategory::Real, 16> x) {
508 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
510 #endif
511 #endif
513 CppTypeFor<TypeCategory::Real, 4> RTNAME(Fraction4)(
514 CppTypeFor<TypeCategory::Real, 4> x) {
515 return Fraction(x);
517 CppTypeFor<TypeCategory::Real, 8> RTNAME(Fraction8)(
518 CppTypeFor<TypeCategory::Real, 8> x) {
519 return Fraction(x);
521 #if LDBL_MANT_DIG == 64
522 CppTypeFor<TypeCategory::Real, 10> RTNAME(Fraction10)(
523 CppTypeFor<TypeCategory::Real, 10> x) {
524 return Fraction(x);
526 #elif LDBL_MANT_DIG == 113
527 CppTypeFor<TypeCategory::Real, 16> RTNAME(Fraction16)(
528 CppTypeFor<TypeCategory::Real, 16> x) {
529 return Fraction(x);
531 #endif
533 bool RTNAME(IsFinite4)(CppTypeFor<TypeCategory::Real, 4> x) {
534 return std::isfinite(x);
536 bool RTNAME(IsFinite8)(CppTypeFor<TypeCategory::Real, 8> x) {
537 return std::isfinite(x);
539 #if LDBL_MANT_DIG == 64
540 bool RTNAME(IsFinite10)(CppTypeFor<TypeCategory::Real, 10> x) {
541 return std::isfinite(x);
543 #elif LDBL_MANT_DIG == 113
544 bool RTNAME(IsFinite16)(CppTypeFor<TypeCategory::Real, 16> x) {
545 return std::isfinite(x);
547 #endif
549 bool RTNAME(IsNaN4)(CppTypeFor<TypeCategory::Real, 4> x) {
550 return std::isnan(x);
552 bool RTNAME(IsNaN8)(CppTypeFor<TypeCategory::Real, 8> x) {
553 return std::isnan(x);
555 #if LDBL_MANT_DIG == 64
556 bool RTNAME(IsNaN10)(CppTypeFor<TypeCategory::Real, 10> x) {
557 return std::isnan(x);
559 #elif LDBL_MANT_DIG == 113
560 bool RTNAME(IsNaN16)(CppTypeFor<TypeCategory::Real, 16> x) {
561 return std::isnan(x);
563 #endif
565 CppTypeFor<TypeCategory::Integer, 1> RTNAME(ModInteger1)(
566 CppTypeFor<TypeCategory::Integer, 1> x,
567 CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile,
568 int sourceLine) {
569 return IntMod<false>(x, p, sourceFile, sourceLine);
571 CppTypeFor<TypeCategory::Integer, 2> RTNAME(ModInteger2)(
572 CppTypeFor<TypeCategory::Integer, 2> x,
573 CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile,
574 int sourceLine) {
575 return IntMod<false>(x, p, sourceFile, sourceLine);
577 CppTypeFor<TypeCategory::Integer, 4> RTNAME(ModInteger4)(
578 CppTypeFor<TypeCategory::Integer, 4> x,
579 CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile,
580 int sourceLine) {
581 return IntMod<false>(x, p, sourceFile, sourceLine);
583 CppTypeFor<TypeCategory::Integer, 8> RTNAME(ModInteger8)(
584 CppTypeFor<TypeCategory::Integer, 8> x,
585 CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile,
586 int sourceLine) {
587 return IntMod<false>(x, p, sourceFile, sourceLine);
589 #ifdef __SIZEOF_INT128__
590 CppTypeFor<TypeCategory::Integer, 16> RTNAME(ModInteger16)(
591 CppTypeFor<TypeCategory::Integer, 16> x,
592 CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile,
593 int sourceLine) {
594 return IntMod<false>(x, p, sourceFile, sourceLine);
596 #endif
597 CppTypeFor<TypeCategory::Real, 4> RTNAME(ModReal4)(
598 CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p,
599 const char *sourceFile, int sourceLine) {
600 return RealMod<false>(x, p, sourceFile, sourceLine);
602 CppTypeFor<TypeCategory::Real, 8> RTNAME(ModReal8)(
603 CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p,
604 const char *sourceFile, int sourceLine) {
605 return RealMod<false>(x, p, sourceFile, sourceLine);
607 #if LDBL_MANT_DIG == 64
608 CppTypeFor<TypeCategory::Real, 10> RTNAME(ModReal10)(
609 CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p,
610 const char *sourceFile, int sourceLine) {
611 return RealMod<false>(x, p, sourceFile, sourceLine);
613 #elif LDBL_MANT_DIG == 113
614 CppTypeFor<TypeCategory::Real, 16> RTNAME(ModReal16)(
615 CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p,
616 const char *sourceFile, int sourceLine) {
617 return RealMod<false>(x, p, sourceFile, sourceLine);
619 #endif
621 CppTypeFor<TypeCategory::Integer, 1> RTNAME(ModuloInteger1)(
622 CppTypeFor<TypeCategory::Integer, 1> x,
623 CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile,
624 int sourceLine) {
625 return IntMod<true>(x, p, sourceFile, sourceLine);
627 CppTypeFor<TypeCategory::Integer, 2> RTNAME(ModuloInteger2)(
628 CppTypeFor<TypeCategory::Integer, 2> x,
629 CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile,
630 int sourceLine) {
631 return IntMod<true>(x, p, sourceFile, sourceLine);
633 CppTypeFor<TypeCategory::Integer, 4> RTNAME(ModuloInteger4)(
634 CppTypeFor<TypeCategory::Integer, 4> x,
635 CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile,
636 int sourceLine) {
637 return IntMod<true>(x, p, sourceFile, sourceLine);
639 CppTypeFor<TypeCategory::Integer, 8> RTNAME(ModuloInteger8)(
640 CppTypeFor<TypeCategory::Integer, 8> x,
641 CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile,
642 int sourceLine) {
643 return IntMod<true>(x, p, sourceFile, sourceLine);
645 #ifdef __SIZEOF_INT128__
646 CppTypeFor<TypeCategory::Integer, 16> RTNAME(ModuloInteger16)(
647 CppTypeFor<TypeCategory::Integer, 16> x,
648 CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile,
649 int sourceLine) {
650 return IntMod<true>(x, p, sourceFile, sourceLine);
652 #endif
653 CppTypeFor<TypeCategory::Real, 4> RTNAME(ModuloReal4)(
654 CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p,
655 const char *sourceFile, int sourceLine) {
656 return RealMod<true>(x, p, sourceFile, sourceLine);
658 CppTypeFor<TypeCategory::Real, 8> RTNAME(ModuloReal8)(
659 CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p,
660 const char *sourceFile, int sourceLine) {
661 return RealMod<true>(x, p, sourceFile, sourceLine);
663 #if LDBL_MANT_DIG == 64
664 CppTypeFor<TypeCategory::Real, 10> RTNAME(ModuloReal10)(
665 CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p,
666 const char *sourceFile, int sourceLine) {
667 return RealMod<true>(x, p, sourceFile, sourceLine);
669 #elif LDBL_MANT_DIG == 113
670 CppTypeFor<TypeCategory::Real, 16> RTNAME(ModuloReal16)(
671 CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p,
672 const char *sourceFile, int sourceLine) {
673 return RealMod<true>(x, p, sourceFile, sourceLine);
675 #endif
677 CppTypeFor<TypeCategory::Real, 4> RTNAME(Nearest4)(
678 CppTypeFor<TypeCategory::Real, 4> x, bool positive) {
679 return Nearest<24>(x, positive);
681 CppTypeFor<TypeCategory::Real, 8> RTNAME(Nearest8)(
682 CppTypeFor<TypeCategory::Real, 8> x, bool positive) {
683 return Nearest<53>(x, positive);
685 #if LDBL_MANT_DIG == 64
686 CppTypeFor<TypeCategory::Real, 10> RTNAME(Nearest10)(
687 CppTypeFor<TypeCategory::Real, 10> x, bool positive) {
688 return Nearest<64>(x, positive);
690 #elif LDBL_MANT_DIG == 113
691 CppTypeFor<TypeCategory::Real, 16> RTNAME(Nearest16)(
692 CppTypeFor<TypeCategory::Real, 16> x, bool positive) {
693 return Nearest<113>(x, positive);
695 #endif
697 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint4_1)(
698 CppTypeFor<TypeCategory::Real, 4> x) {
699 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
701 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint4_2)(
702 CppTypeFor<TypeCategory::Real, 4> x) {
703 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
705 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint4_4)(
706 CppTypeFor<TypeCategory::Real, 4> x) {
707 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
709 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint4_8)(
710 CppTypeFor<TypeCategory::Real, 4> x) {
711 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
713 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
714 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint4_16)(
715 CppTypeFor<TypeCategory::Real, 4> x) {
716 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
718 #endif
719 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint8_1)(
720 CppTypeFor<TypeCategory::Real, 8> x) {
721 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
723 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint8_2)(
724 CppTypeFor<TypeCategory::Real, 8> x) {
725 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
727 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint8_4)(
728 CppTypeFor<TypeCategory::Real, 8> x) {
729 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
731 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint8_8)(
732 CppTypeFor<TypeCategory::Real, 8> x) {
733 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
735 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
736 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint8_16)(
737 CppTypeFor<TypeCategory::Real, 8> x) {
738 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
740 #endif
741 #if LDBL_MANT_DIG == 64
742 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint10_1)(
743 CppTypeFor<TypeCategory::Real, 10> x) {
744 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
746 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint10_2)(
747 CppTypeFor<TypeCategory::Real, 10> x) {
748 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
750 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint10_4)(
751 CppTypeFor<TypeCategory::Real, 10> x) {
752 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
754 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint10_8)(
755 CppTypeFor<TypeCategory::Real, 10> x) {
756 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
758 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
759 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint10_16)(
760 CppTypeFor<TypeCategory::Real, 10> x) {
761 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
763 #endif
764 #elif LDBL_MANT_DIG == 113
765 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint16_1)(
766 CppTypeFor<TypeCategory::Real, 16> x) {
767 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
769 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint16_2)(
770 CppTypeFor<TypeCategory::Real, 16> x) {
771 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
773 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint16_4)(
774 CppTypeFor<TypeCategory::Real, 16> x) {
775 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
777 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint16_8)(
778 CppTypeFor<TypeCategory::Real, 16> x) {
779 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
781 #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T
782 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint16_16)(
783 CppTypeFor<TypeCategory::Real, 16> x) {
784 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
786 #endif
787 #endif
789 CppTypeFor<TypeCategory::Real, 4> RTNAME(RRSpacing4)(
790 CppTypeFor<TypeCategory::Real, 4> x) {
791 return RRSpacing<24>(x);
793 CppTypeFor<TypeCategory::Real, 8> RTNAME(RRSpacing8)(
794 CppTypeFor<TypeCategory::Real, 8> x) {
795 return RRSpacing<53>(x);
797 #if LDBL_MANT_DIG == 64
798 CppTypeFor<TypeCategory::Real, 10> RTNAME(RRSpacing10)(
799 CppTypeFor<TypeCategory::Real, 10> x) {
800 return RRSpacing<64>(x);
802 #elif LDBL_MANT_DIG == 113
803 CppTypeFor<TypeCategory::Real, 16> RTNAME(RRSpacing16)(
804 CppTypeFor<TypeCategory::Real, 16> x) {
805 return RRSpacing<113>(x);
807 #endif
809 CppTypeFor<TypeCategory::Real, 4> RTNAME(SetExponent4)(
810 CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) {
811 return SetExponent(x, p);
813 CppTypeFor<TypeCategory::Real, 8> RTNAME(SetExponent8)(
814 CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) {
815 return SetExponent(x, p);
817 #if LDBL_MANT_DIG == 64
818 CppTypeFor<TypeCategory::Real, 10> RTNAME(SetExponent10)(
819 CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) {
820 return SetExponent(x, p);
822 #elif LDBL_MANT_DIG == 113
823 CppTypeFor<TypeCategory::Real, 16> RTNAME(SetExponent16)(
824 CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) {
825 return SetExponent(x, p);
827 #endif
829 CppTypeFor<TypeCategory::Real, 4> RTNAME(Scale4)(
830 CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) {
831 return Scale(x, p);
833 CppTypeFor<TypeCategory::Real, 8> RTNAME(Scale8)(
834 CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) {
835 return Scale(x, p);
837 #if LDBL_MANT_DIG == 64
838 CppTypeFor<TypeCategory::Real, 10> RTNAME(Scale10)(
839 CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) {
840 return Scale(x, p);
842 #elif LDBL_MANT_DIG == 113
843 CppTypeFor<TypeCategory::Real, 16> RTNAME(Scale16)(
844 CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) {
845 return Scale(x, p);
847 #endif
849 // SELECTED_INT_KIND
850 CppTypeFor<TypeCategory::Integer, 4> RTNAME(SelectedIntKind)(
851 const char *source, int line, void *x, int xKind) {
852 #ifdef __SIZEOF_INT128__
853 CppTypeFor<TypeCategory::Integer, 16> r =
854 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
855 source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 16);
856 #else
857 std::int64_t r = getIntArgValue<std::int64_t>(
858 source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 8);
859 #endif
860 return SelectedIntKind(r);
863 // SELECTED_REAL_KIND
864 CppTypeFor<TypeCategory::Integer, 4> RTNAME(SelectedRealKind)(
865 const char *source, int line, void *precision, int pKind, void *range,
866 int rKind, void *radix, int dKind) {
867 #ifdef __SIZEOF_INT128__
868 CppTypeFor<TypeCategory::Integer, 16> p =
869 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
870 source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 16);
871 CppTypeFor<TypeCategory::Integer, 16> r =
872 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
873 source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 16);
874 CppTypeFor<TypeCategory::Integer, 16> d =
875 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
876 source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 16);
877 #else
878 std::int64_t p = getIntArgValue<std::int64_t>(
879 source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 8);
880 std::int64_t r = getIntArgValue<std::int64_t>(
881 source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 8);
882 std::int64_t d = getIntArgValue<std::int64_t>(
883 source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 8);
884 #endif
885 return SelectedRealKind(p, r, d);
888 CppTypeFor<TypeCategory::Real, 4> RTNAME(Spacing4)(
889 CppTypeFor<TypeCategory::Real, 4> x) {
890 return Spacing<24>(x);
892 CppTypeFor<TypeCategory::Real, 8> RTNAME(Spacing8)(
893 CppTypeFor<TypeCategory::Real, 8> x) {
894 return Spacing<53>(x);
896 #if LDBL_MANT_DIG == 64
897 CppTypeFor<TypeCategory::Real, 10> RTNAME(Spacing10)(
898 CppTypeFor<TypeCategory::Real, 10> x) {
899 return Spacing<64>(x);
901 #elif LDBL_MANT_DIG == 113
902 CppTypeFor<TypeCategory::Real, 16> RTNAME(Spacing16)(
903 CppTypeFor<TypeCategory::Real, 16> x) {
904 return Spacing<113>(x);
906 #endif
908 CppTypeFor<TypeCategory::Real, 4> RTNAME(FPow4i)(
909 CppTypeFor<TypeCategory::Real, 4> b,
910 CppTypeFor<TypeCategory::Integer, 4> e) {
911 return FPowI(b, e);
913 CppTypeFor<TypeCategory::Real, 8> RTNAME(FPow8i)(
914 CppTypeFor<TypeCategory::Real, 8> b,
915 CppTypeFor<TypeCategory::Integer, 4> e) {
916 return FPowI(b, e);
918 #if LDBL_MANT_DIG == 64
919 CppTypeFor<TypeCategory::Real, 10> RTNAME(FPow10i)(
920 CppTypeFor<TypeCategory::Real, 10> b,
921 CppTypeFor<TypeCategory::Integer, 4> e) {
922 return FPowI(b, e);
924 #endif
925 #if LDBL_MANT_DIG == 113 || HAS_FLOAT128
926 CppTypeFor<TypeCategory::Real, 16> RTNAME(FPow16i)(
927 CppTypeFor<TypeCategory::Real, 16> b,
928 CppTypeFor<TypeCategory::Integer, 4> e) {
929 return FPowI(b, e);
931 #endif
933 CppTypeFor<TypeCategory::Real, 4> RTNAME(FPow4k)(
934 CppTypeFor<TypeCategory::Real, 4> b,
935 CppTypeFor<TypeCategory::Integer, 8> e) {
936 return FPowI(b, e);
938 CppTypeFor<TypeCategory::Real, 8> RTNAME(FPow8k)(
939 CppTypeFor<TypeCategory::Real, 8> b,
940 CppTypeFor<TypeCategory::Integer, 8> e) {
941 return FPowI(b, e);
943 #if LDBL_MANT_DIG == 64
944 CppTypeFor<TypeCategory::Real, 10> RTNAME(FPow10k)(
945 CppTypeFor<TypeCategory::Real, 10> b,
946 CppTypeFor<TypeCategory::Integer, 8> e) {
947 return FPowI(b, e);
949 #endif
950 #if LDBL_MANT_DIG == 113 || HAS_FLOAT128
951 CppTypeFor<TypeCategory::Real, 16> RTNAME(FPow16k)(
952 CppTypeFor<TypeCategory::Real, 16> b,
953 CppTypeFor<TypeCategory::Integer, 8> e) {
954 return FPowI(b, e);
956 #endif
957 } // extern "C"
958 } // namespace Fortran::runtime