[flang] Accept polymorphic component element in storage_size
[llvm-project.git] / flang / runtime / numeric.cpp
blob7afa5802db049b89edd596385911a8ff4d37c36f
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/Runtime/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 0; // 0 -> 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 return std::ldexp(
243 static_cast<T>(1.0), std::ilogb(x) + 1 - PREC); // 2**(e-p)
247 // NEAREST (16.9.139)
248 template <int PREC, typename T> inline T Nearest(T x, bool positive) {
249 auto spacing{Spacing<PREC>(x)};
250 if (x == 0) {
251 auto least{std::numeric_limits<T>::denorm_min()};
252 return positive ? least : -least;
253 } else {
254 return positive ? x + spacing : x - spacing;
258 // Exponentiation operator for (Real ** Integer) cases (10.1.5.2.1).
259 template <typename BTy, typename ETy> BTy FPowI(BTy base, ETy exp) {
260 if (exp == ETy{0})
261 return BTy{1};
262 bool isNegativePower{exp < ETy{0}};
263 bool isMinPower{exp == std::numeric_limits<ETy>::min()};
264 if (isMinPower) {
265 exp = std::numeric_limits<ETy>::max();
266 } else if (isNegativePower) {
267 exp = -exp;
269 BTy result{1};
270 BTy origBase{base};
271 while (true) {
272 if (exp & ETy{1}) {
273 result *= base;
275 exp >>= 1;
276 if (exp == ETy{0}) {
277 break;
279 base *= base;
281 if (isMinPower) {
282 result *= origBase;
284 if (isNegativePower) {
285 result = BTy{1} / result;
287 return result;
290 extern "C" {
292 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling4_1)(
293 CppTypeFor<TypeCategory::Real, 4> x) {
294 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
296 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling4_2)(
297 CppTypeFor<TypeCategory::Real, 4> x) {
298 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
300 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling4_4)(
301 CppTypeFor<TypeCategory::Real, 4> x) {
302 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
304 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling4_8)(
305 CppTypeFor<TypeCategory::Real, 4> x) {
306 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
308 #ifdef __SIZEOF_INT128__
309 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling4_16)(
310 CppTypeFor<TypeCategory::Real, 4> x) {
311 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
313 #endif
314 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling8_1)(
315 CppTypeFor<TypeCategory::Real, 8> x) {
316 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
318 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling8_2)(
319 CppTypeFor<TypeCategory::Real, 8> x) {
320 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
322 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling8_4)(
323 CppTypeFor<TypeCategory::Real, 8> x) {
324 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
326 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling8_8)(
327 CppTypeFor<TypeCategory::Real, 8> x) {
328 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
330 #ifdef __SIZEOF_INT128__
331 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling8_16)(
332 CppTypeFor<TypeCategory::Real, 8> x) {
333 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
335 #endif
336 #if LDBL_MANT_DIG == 64
337 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling10_1)(
338 CppTypeFor<TypeCategory::Real, 10> x) {
339 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
341 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling10_2)(
342 CppTypeFor<TypeCategory::Real, 10> x) {
343 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
345 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling10_4)(
346 CppTypeFor<TypeCategory::Real, 10> x) {
347 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
349 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling10_8)(
350 CppTypeFor<TypeCategory::Real, 10> x) {
351 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
353 #ifdef __SIZEOF_INT128__
354 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling10_16)(
355 CppTypeFor<TypeCategory::Real, 10> x) {
356 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
358 #endif
359 #elif LDBL_MANT_DIG == 113
360 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling16_1)(
361 CppTypeFor<TypeCategory::Real, 16> x) {
362 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
364 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling16_2)(
365 CppTypeFor<TypeCategory::Real, 16> x) {
366 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
368 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling16_4)(
369 CppTypeFor<TypeCategory::Real, 16> x) {
370 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
372 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling16_8)(
373 CppTypeFor<TypeCategory::Real, 16> x) {
374 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
376 #ifdef __SIZEOF_INT128__
377 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling16_16)(
378 CppTypeFor<TypeCategory::Real, 16> x) {
379 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
381 #endif
382 #endif
384 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent4_4)(
385 CppTypeFor<TypeCategory::Real, 4> x) {
386 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
388 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent4_8)(
389 CppTypeFor<TypeCategory::Real, 4> x) {
390 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
392 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent8_4)(
393 CppTypeFor<TypeCategory::Real, 8> x) {
394 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
396 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent8_8)(
397 CppTypeFor<TypeCategory::Real, 8> x) {
398 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
400 #if LDBL_MANT_DIG == 64
401 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent10_4)(
402 CppTypeFor<TypeCategory::Real, 10> x) {
403 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
405 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent10_8)(
406 CppTypeFor<TypeCategory::Real, 10> x) {
407 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
409 #elif LDBL_MANT_DIG == 113
410 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent16_4)(
411 CppTypeFor<TypeCategory::Real, 16> x) {
412 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
414 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent16_8)(
415 CppTypeFor<TypeCategory::Real, 16> x) {
416 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
418 #endif
420 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor4_1)(
421 CppTypeFor<TypeCategory::Real, 4> x) {
422 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
424 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor4_2)(
425 CppTypeFor<TypeCategory::Real, 4> x) {
426 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
428 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor4_4)(
429 CppTypeFor<TypeCategory::Real, 4> x) {
430 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
432 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor4_8)(
433 CppTypeFor<TypeCategory::Real, 4> x) {
434 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
436 #ifdef __SIZEOF_INT128__
437 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor4_16)(
438 CppTypeFor<TypeCategory::Real, 4> x) {
439 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
441 #endif
442 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor8_1)(
443 CppTypeFor<TypeCategory::Real, 8> x) {
444 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
446 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor8_2)(
447 CppTypeFor<TypeCategory::Real, 8> x) {
448 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
450 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor8_4)(
451 CppTypeFor<TypeCategory::Real, 8> x) {
452 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
454 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor8_8)(
455 CppTypeFor<TypeCategory::Real, 8> x) {
456 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
458 #ifdef __SIZEOF_INT128__
459 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor8_16)(
460 CppTypeFor<TypeCategory::Real, 8> x) {
461 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
463 #endif
464 #if LDBL_MANT_DIG == 64
465 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor10_1)(
466 CppTypeFor<TypeCategory::Real, 10> x) {
467 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
469 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor10_2)(
470 CppTypeFor<TypeCategory::Real, 10> x) {
471 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
473 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor10_4)(
474 CppTypeFor<TypeCategory::Real, 10> x) {
475 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
477 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor10_8)(
478 CppTypeFor<TypeCategory::Real, 10> x) {
479 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
481 #ifdef __SIZEOF_INT128__
482 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor10_16)(
483 CppTypeFor<TypeCategory::Real, 10> x) {
484 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
486 #endif
487 #elif LDBL_MANT_DIG == 113
488 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor16_1)(
489 CppTypeFor<TypeCategory::Real, 16> x) {
490 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
492 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor16_2)(
493 CppTypeFor<TypeCategory::Real, 16> x) {
494 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
496 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor16_4)(
497 CppTypeFor<TypeCategory::Real, 16> x) {
498 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
500 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor16_8)(
501 CppTypeFor<TypeCategory::Real, 16> x) {
502 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
504 #ifdef __SIZEOF_INT128__
505 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor16_16)(
506 CppTypeFor<TypeCategory::Real, 16> x) {
507 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
509 #endif
510 #endif
512 CppTypeFor<TypeCategory::Real, 4> RTNAME(Fraction4)(
513 CppTypeFor<TypeCategory::Real, 4> x) {
514 return Fraction(x);
516 CppTypeFor<TypeCategory::Real, 8> RTNAME(Fraction8)(
517 CppTypeFor<TypeCategory::Real, 8> x) {
518 return Fraction(x);
520 #if LDBL_MANT_DIG == 64
521 CppTypeFor<TypeCategory::Real, 10> RTNAME(Fraction10)(
522 CppTypeFor<TypeCategory::Real, 10> x) {
523 return Fraction(x);
525 #elif LDBL_MANT_DIG == 113
526 CppTypeFor<TypeCategory::Real, 16> RTNAME(Fraction16)(
527 CppTypeFor<TypeCategory::Real, 16> x) {
528 return Fraction(x);
530 #endif
532 bool RTNAME(IsFinite4)(CppTypeFor<TypeCategory::Real, 4> x) {
533 return std::isfinite(x);
535 bool RTNAME(IsFinite8)(CppTypeFor<TypeCategory::Real, 8> x) {
536 return std::isfinite(x);
538 #if LDBL_MANT_DIG == 64
539 bool RTNAME(IsFinite10)(CppTypeFor<TypeCategory::Real, 10> x) {
540 return std::isfinite(x);
542 #elif LDBL_MANT_DIG == 113
543 bool RTNAME(IsFinite16)(CppTypeFor<TypeCategory::Real, 16> x) {
544 return std::isfinite(x);
546 #endif
548 bool RTNAME(IsNaN4)(CppTypeFor<TypeCategory::Real, 4> x) {
549 return std::isnan(x);
551 bool RTNAME(IsNaN8)(CppTypeFor<TypeCategory::Real, 8> x) {
552 return std::isnan(x);
554 #if LDBL_MANT_DIG == 64
555 bool RTNAME(IsNaN10)(CppTypeFor<TypeCategory::Real, 10> x) {
556 return std::isnan(x);
558 #elif LDBL_MANT_DIG == 113
559 bool RTNAME(IsNaN16)(CppTypeFor<TypeCategory::Real, 16> x) {
560 return std::isnan(x);
562 #endif
564 CppTypeFor<TypeCategory::Integer, 1> RTNAME(ModInteger1)(
565 CppTypeFor<TypeCategory::Integer, 1> x,
566 CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile,
567 int sourceLine) {
568 return IntMod<false>(x, p, sourceFile, sourceLine);
570 CppTypeFor<TypeCategory::Integer, 2> RTNAME(ModInteger2)(
571 CppTypeFor<TypeCategory::Integer, 2> x,
572 CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile,
573 int sourceLine) {
574 return IntMod<false>(x, p, sourceFile, sourceLine);
576 CppTypeFor<TypeCategory::Integer, 4> RTNAME(ModInteger4)(
577 CppTypeFor<TypeCategory::Integer, 4> x,
578 CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile,
579 int sourceLine) {
580 return IntMod<false>(x, p, sourceFile, sourceLine);
582 CppTypeFor<TypeCategory::Integer, 8> RTNAME(ModInteger8)(
583 CppTypeFor<TypeCategory::Integer, 8> x,
584 CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile,
585 int sourceLine) {
586 return IntMod<false>(x, p, sourceFile, sourceLine);
588 #ifdef __SIZEOF_INT128__
589 CppTypeFor<TypeCategory::Integer, 16> RTNAME(ModInteger16)(
590 CppTypeFor<TypeCategory::Integer, 16> x,
591 CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile,
592 int sourceLine) {
593 return IntMod<false>(x, p, sourceFile, sourceLine);
595 #endif
596 CppTypeFor<TypeCategory::Real, 4> RTNAME(ModReal4)(
597 CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p,
598 const char *sourceFile, int sourceLine) {
599 return RealMod<false>(x, p, sourceFile, sourceLine);
601 CppTypeFor<TypeCategory::Real, 8> RTNAME(ModReal8)(
602 CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p,
603 const char *sourceFile, int sourceLine) {
604 return RealMod<false>(x, p, sourceFile, sourceLine);
606 #if LDBL_MANT_DIG == 64
607 CppTypeFor<TypeCategory::Real, 10> RTNAME(ModReal10)(
608 CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p,
609 const char *sourceFile, int sourceLine) {
610 return RealMod<false>(x, p, sourceFile, sourceLine);
612 #elif LDBL_MANT_DIG == 113
613 CppTypeFor<TypeCategory::Real, 16> RTNAME(ModReal16)(
614 CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p,
615 const char *sourceFile, int sourceLine) {
616 return RealMod<false>(x, p, sourceFile, sourceLine);
618 #endif
620 CppTypeFor<TypeCategory::Integer, 1> RTNAME(ModuloInteger1)(
621 CppTypeFor<TypeCategory::Integer, 1> x,
622 CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile,
623 int sourceLine) {
624 return IntMod<true>(x, p, sourceFile, sourceLine);
626 CppTypeFor<TypeCategory::Integer, 2> RTNAME(ModuloInteger2)(
627 CppTypeFor<TypeCategory::Integer, 2> x,
628 CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile,
629 int sourceLine) {
630 return IntMod<true>(x, p, sourceFile, sourceLine);
632 CppTypeFor<TypeCategory::Integer, 4> RTNAME(ModuloInteger4)(
633 CppTypeFor<TypeCategory::Integer, 4> x,
634 CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile,
635 int sourceLine) {
636 return IntMod<true>(x, p, sourceFile, sourceLine);
638 CppTypeFor<TypeCategory::Integer, 8> RTNAME(ModuloInteger8)(
639 CppTypeFor<TypeCategory::Integer, 8> x,
640 CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile,
641 int sourceLine) {
642 return IntMod<true>(x, p, sourceFile, sourceLine);
644 #ifdef __SIZEOF_INT128__
645 CppTypeFor<TypeCategory::Integer, 16> RTNAME(ModuloInteger16)(
646 CppTypeFor<TypeCategory::Integer, 16> x,
647 CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile,
648 int sourceLine) {
649 return IntMod<true>(x, p, sourceFile, sourceLine);
651 #endif
652 CppTypeFor<TypeCategory::Real, 4> RTNAME(ModuloReal4)(
653 CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p,
654 const char *sourceFile, int sourceLine) {
655 return RealMod<true>(x, p, sourceFile, sourceLine);
657 CppTypeFor<TypeCategory::Real, 8> RTNAME(ModuloReal8)(
658 CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p,
659 const char *sourceFile, int sourceLine) {
660 return RealMod<true>(x, p, sourceFile, sourceLine);
662 #if LDBL_MANT_DIG == 64
663 CppTypeFor<TypeCategory::Real, 10> RTNAME(ModuloReal10)(
664 CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p,
665 const char *sourceFile, int sourceLine) {
666 return RealMod<true>(x, p, sourceFile, sourceLine);
668 #elif LDBL_MANT_DIG == 113
669 CppTypeFor<TypeCategory::Real, 16> RTNAME(ModuloReal16)(
670 CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p,
671 const char *sourceFile, int sourceLine) {
672 return RealMod<true>(x, p, sourceFile, sourceLine);
674 #endif
676 CppTypeFor<TypeCategory::Real, 4> RTNAME(Nearest4)(
677 CppTypeFor<TypeCategory::Real, 4> x, bool positive) {
678 return Nearest<24>(x, positive);
680 CppTypeFor<TypeCategory::Real, 8> RTNAME(Nearest8)(
681 CppTypeFor<TypeCategory::Real, 8> x, bool positive) {
682 return Nearest<53>(x, positive);
684 #if LDBL_MANT_DIG == 64
685 CppTypeFor<TypeCategory::Real, 10> RTNAME(Nearest10)(
686 CppTypeFor<TypeCategory::Real, 10> x, bool positive) {
687 return Nearest<64>(x, positive);
689 #elif LDBL_MANT_DIG == 113
690 CppTypeFor<TypeCategory::Real, 16> RTNAME(Nearest16)(
691 CppTypeFor<TypeCategory::Real, 16> x, bool positive) {
692 return Nearest<113>(x, positive);
694 #endif
696 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint4_1)(
697 CppTypeFor<TypeCategory::Real, 4> x) {
698 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
700 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint4_2)(
701 CppTypeFor<TypeCategory::Real, 4> x) {
702 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
704 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint4_4)(
705 CppTypeFor<TypeCategory::Real, 4> x) {
706 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
708 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint4_8)(
709 CppTypeFor<TypeCategory::Real, 4> x) {
710 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
712 #ifdef __SIZEOF_INT128__
713 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint4_16)(
714 CppTypeFor<TypeCategory::Real, 4> x) {
715 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
717 #endif
718 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint8_1)(
719 CppTypeFor<TypeCategory::Real, 8> x) {
720 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
722 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint8_2)(
723 CppTypeFor<TypeCategory::Real, 8> x) {
724 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
726 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint8_4)(
727 CppTypeFor<TypeCategory::Real, 8> x) {
728 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
730 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint8_8)(
731 CppTypeFor<TypeCategory::Real, 8> x) {
732 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
734 #ifdef __SIZEOF_INT128__
735 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint8_16)(
736 CppTypeFor<TypeCategory::Real, 8> x) {
737 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
739 #endif
740 #if LDBL_MANT_DIG == 64
741 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint10_1)(
742 CppTypeFor<TypeCategory::Real, 10> x) {
743 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
745 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint10_2)(
746 CppTypeFor<TypeCategory::Real, 10> x) {
747 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
749 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint10_4)(
750 CppTypeFor<TypeCategory::Real, 10> x) {
751 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
753 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint10_8)(
754 CppTypeFor<TypeCategory::Real, 10> x) {
755 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
757 #ifdef __SIZEOF_INT128__
758 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint10_16)(
759 CppTypeFor<TypeCategory::Real, 10> x) {
760 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
762 #endif
763 #elif LDBL_MANT_DIG == 113
764 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint16_1)(
765 CppTypeFor<TypeCategory::Real, 16> x) {
766 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
768 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint16_2)(
769 CppTypeFor<TypeCategory::Real, 16> x) {
770 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
772 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint16_4)(
773 CppTypeFor<TypeCategory::Real, 16> x) {
774 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
776 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint16_8)(
777 CppTypeFor<TypeCategory::Real, 16> x) {
778 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
780 #ifdef __SIZEOF_INT128__
781 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint16_16)(
782 CppTypeFor<TypeCategory::Real, 16> x) {
783 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
785 #endif
786 #endif
788 CppTypeFor<TypeCategory::Real, 4> RTNAME(RRSpacing4)(
789 CppTypeFor<TypeCategory::Real, 4> x) {
790 return RRSpacing<24>(x);
792 CppTypeFor<TypeCategory::Real, 8> RTNAME(RRSpacing8)(
793 CppTypeFor<TypeCategory::Real, 8> x) {
794 return RRSpacing<53>(x);
796 #if LDBL_MANT_DIG == 64
797 CppTypeFor<TypeCategory::Real, 10> RTNAME(RRSpacing10)(
798 CppTypeFor<TypeCategory::Real, 10> x) {
799 return RRSpacing<64>(x);
801 #elif LDBL_MANT_DIG == 113
802 CppTypeFor<TypeCategory::Real, 16> RTNAME(RRSpacing16)(
803 CppTypeFor<TypeCategory::Real, 16> x) {
804 return RRSpacing<113>(x);
806 #endif
808 CppTypeFor<TypeCategory::Real, 4> RTNAME(SetExponent4)(
809 CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) {
810 return SetExponent(x, p);
812 CppTypeFor<TypeCategory::Real, 8> RTNAME(SetExponent8)(
813 CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) {
814 return SetExponent(x, p);
816 #if LDBL_MANT_DIG == 64
817 CppTypeFor<TypeCategory::Real, 10> RTNAME(SetExponent10)(
818 CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) {
819 return SetExponent(x, p);
821 #elif LDBL_MANT_DIG == 113
822 CppTypeFor<TypeCategory::Real, 16> RTNAME(SetExponent16)(
823 CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) {
824 return SetExponent(x, p);
826 #endif
828 CppTypeFor<TypeCategory::Real, 4> RTNAME(Scale4)(
829 CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) {
830 return Scale(x, p);
832 CppTypeFor<TypeCategory::Real, 8> RTNAME(Scale8)(
833 CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) {
834 return Scale(x, p);
836 #if LDBL_MANT_DIG == 64
837 CppTypeFor<TypeCategory::Real, 10> RTNAME(Scale10)(
838 CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) {
839 return Scale(x, p);
841 #elif LDBL_MANT_DIG == 113
842 CppTypeFor<TypeCategory::Real, 16> RTNAME(Scale16)(
843 CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) {
844 return Scale(x, p);
846 #endif
848 // SELECTED_INT_KIND
849 CppTypeFor<TypeCategory::Integer, 4> RTNAME(SelectedIntKind)(
850 const char *source, int line, void *x, int xKind) {
851 #ifdef __SIZEOF_INT128__
852 CppTypeFor<TypeCategory::Integer, 16> r =
853 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
854 source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 16);
855 #else
856 std::int64_t r = getIntArgValue<std::int64_t>(
857 source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 8);
858 #endif
859 return SelectedIntKind(r);
862 // SELECTED_REAL_KIND
863 CppTypeFor<TypeCategory::Integer, 4> RTNAME(SelectedRealKind)(
864 const char *source, int line, void *precision, int pKind, void *range,
865 int rKind, void *radix, int dKind) {
866 #ifdef __SIZEOF_INT128__
867 CppTypeFor<TypeCategory::Integer, 16> p =
868 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
869 source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 16);
870 CppTypeFor<TypeCategory::Integer, 16> r =
871 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
872 source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 16);
873 CppTypeFor<TypeCategory::Integer, 16> d =
874 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
875 source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 16);
876 #else
877 std::int64_t p = getIntArgValue<std::int64_t>(
878 source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 8);
879 std::int64_t r = getIntArgValue<std::int64_t>(
880 source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 8);
881 std::int64_t d = getIntArgValue<std::int64_t>(
882 source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 8);
883 #endif
884 return SelectedRealKind(p, r, d);
887 CppTypeFor<TypeCategory::Real, 4> RTNAME(Spacing4)(
888 CppTypeFor<TypeCategory::Real, 4> x) {
889 return Spacing<24>(x);
891 CppTypeFor<TypeCategory::Real, 8> RTNAME(Spacing8)(
892 CppTypeFor<TypeCategory::Real, 8> x) {
893 return Spacing<53>(x);
895 #if LDBL_MANT_DIG == 64
896 CppTypeFor<TypeCategory::Real, 10> RTNAME(Spacing10)(
897 CppTypeFor<TypeCategory::Real, 10> x) {
898 return Spacing<64>(x);
900 #elif LDBL_MANT_DIG == 113
901 CppTypeFor<TypeCategory::Real, 16> RTNAME(Spacing16)(
902 CppTypeFor<TypeCategory::Real, 16> x) {
903 return Spacing<113>(x);
905 #endif
907 CppTypeFor<TypeCategory::Real, 4> RTNAME(FPow4i)(
908 CppTypeFor<TypeCategory::Real, 4> b,
909 CppTypeFor<TypeCategory::Integer, 4> e) {
910 return FPowI(b, e);
912 CppTypeFor<TypeCategory::Real, 8> RTNAME(FPow8i)(
913 CppTypeFor<TypeCategory::Real, 8> b,
914 CppTypeFor<TypeCategory::Integer, 4> e) {
915 return FPowI(b, e);
917 #if LDBL_MANT_DIG == 64
918 CppTypeFor<TypeCategory::Real, 10> RTNAME(FPow10i)(
919 CppTypeFor<TypeCategory::Real, 10> b,
920 CppTypeFor<TypeCategory::Integer, 4> e) {
921 return FPowI(b, e);
923 #endif
924 #if LDBL_MANT_DIG == 113 || HAS_FLOAT128
925 CppTypeFor<TypeCategory::Real, 16> RTNAME(FPow16i)(
926 CppTypeFor<TypeCategory::Real, 16> b,
927 CppTypeFor<TypeCategory::Integer, 4> e) {
928 return FPowI(b, e);
930 #endif
932 CppTypeFor<TypeCategory::Real, 4> RTNAME(FPow4k)(
933 CppTypeFor<TypeCategory::Real, 4> b,
934 CppTypeFor<TypeCategory::Integer, 8> e) {
935 return FPowI(b, e);
937 CppTypeFor<TypeCategory::Real, 8> RTNAME(FPow8k)(
938 CppTypeFor<TypeCategory::Real, 8> b,
939 CppTypeFor<TypeCategory::Integer, 8> e) {
940 return FPowI(b, e);
942 #if LDBL_MANT_DIG == 64
943 CppTypeFor<TypeCategory::Real, 10> RTNAME(FPow10k)(
944 CppTypeFor<TypeCategory::Real, 10> b,
945 CppTypeFor<TypeCategory::Integer, 8> e) {
946 return FPowI(b, e);
948 #endif
949 #if LDBL_MANT_DIG == 113 || HAS_FLOAT128
950 CppTypeFor<TypeCategory::Real, 16> RTNAME(FPow16k)(
951 CppTypeFor<TypeCategory::Real, 16> b,
952 CppTypeFor<TypeCategory::Integer, 8> e) {
953 return FPowI(b, e);
955 #endif
956 } // extern "C"
957 } // namespace Fortran::runtime