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 "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> 16 17 namespace Fortran::runtime { 18 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"); 41 } 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"); 47 } 48 return res; 49 } 50 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}); 57 } 58 } 59 60 // CEILING & FLOOR (16.9.43, .79) 61 template <typename RESULT, typename ARG> inline RESULT Ceiling(ARG x) { 62 return std::ceil(x); 63 } 64 template <typename RESULT, typename ARG> inline RESULT Floor(ARG x) { 65 return std::floor(x); 66 } 67 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; 76 } 77 } 78 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); 90 } 91 } 92 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"); 99 } 100 auto mod{x - (x / p) * p}; 101 if (IS_MODULO && (x > 0) != (p > 0)) { 102 mod += p; 103 } 104 return mod; 105 } 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"); 111 } 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); 117 } 118 T toInt{IS_MODULO ? std::floor(quotient) : std::trunc(quotient)}; 119 return a - toInt * p; 120 } 121 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)); 132 } 133 } 134 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(); 141 } 142 return std::ldexp(x, p); // x*2**p 143 } 144 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 160 } 161 return -1; 162 } 163 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; 169 } 170 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; 190 } 191 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; 207 } 208 209 return error ? error : kind; 210 } 211 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(); 226 } 227 return std::ldexp(x, ip); // x*2**(p-e) 228 } 229 } 230 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) 244 } 245 } 246 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; 255 } 256 } 257 258 extern "C" { 259 260 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling4_1)( 261 CppTypeFor<TypeCategory::Real, 4> x) { 262 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x); 263 } 264 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling4_2)( 265 CppTypeFor<TypeCategory::Real, 4> x) { 266 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x); 267 } 268 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling4_4)( 269 CppTypeFor<TypeCategory::Real, 4> x) { 270 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x); 271 } 272 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling4_8)( 273 CppTypeFor<TypeCategory::Real, 4> x) { 274 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x); 275 } 276 #ifdef __SIZEOF_INT128__ 277 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling4_16)( 278 CppTypeFor<TypeCategory::Real, 4> x) { 279 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x); 280 } 281 #endif 282 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling8_1)( 283 CppTypeFor<TypeCategory::Real, 8> x) { 284 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x); 285 } 286 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling8_2)( 287 CppTypeFor<TypeCategory::Real, 8> x) { 288 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x); 289 } 290 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling8_4)( 291 CppTypeFor<TypeCategory::Real, 8> x) { 292 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x); 293 } 294 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling8_8)( 295 CppTypeFor<TypeCategory::Real, 8> x) { 296 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x); 297 } 298 #ifdef __SIZEOF_INT128__ 299 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling8_16)( 300 CppTypeFor<TypeCategory::Real, 8> x) { 301 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x); 302 } 303 #endif 304 #if LDBL_MANT_DIG == 64 305 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling10_1)( 306 CppTypeFor<TypeCategory::Real, 10> x) { 307 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x); 308 } 309 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling10_2)( 310 CppTypeFor<TypeCategory::Real, 10> x) { 311 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x); 312 } 313 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling10_4)( 314 CppTypeFor<TypeCategory::Real, 10> x) { 315 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x); 316 } 317 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling10_8)( 318 CppTypeFor<TypeCategory::Real, 10> x) { 319 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x); 320 } 321 #ifdef __SIZEOF_INT128__ 322 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling10_16)( 323 CppTypeFor<TypeCategory::Real, 10> x) { 324 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x); 325 } 326 #endif 327 #elif LDBL_MANT_DIG == 113 328 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling16_1)( 329 CppTypeFor<TypeCategory::Real, 16> x) { 330 return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x); 331 } 332 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling16_2)( 333 CppTypeFor<TypeCategory::Real, 16> x) { 334 return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x); 335 } 336 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling16_4)( 337 CppTypeFor<TypeCategory::Real, 16> x) { 338 return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x); 339 } 340 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling16_8)( 341 CppTypeFor<TypeCategory::Real, 16> x) { 342 return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x); 343 } 344 #ifdef __SIZEOF_INT128__ 345 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling16_16)( 346 CppTypeFor<TypeCategory::Real, 16> x) { 347 return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x); 348 } 349 #endif 350 #endif 351 352 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent4_4)( 353 CppTypeFor<TypeCategory::Real, 4> x) { 354 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x); 355 } 356 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent4_8)( 357 CppTypeFor<TypeCategory::Real, 4> x) { 358 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x); 359 } 360 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent8_4)( 361 CppTypeFor<TypeCategory::Real, 8> x) { 362 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x); 363 } 364 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent8_8)( 365 CppTypeFor<TypeCategory::Real, 8> x) { 366 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x); 367 } 368 #if LDBL_MANT_DIG == 64 369 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent10_4)( 370 CppTypeFor<TypeCategory::Real, 10> x) { 371 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x); 372 } 373 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent10_8)( 374 CppTypeFor<TypeCategory::Real, 10> x) { 375 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x); 376 } 377 #elif LDBL_MANT_DIG == 113 378 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent16_4)( 379 CppTypeFor<TypeCategory::Real, 16> x) { 380 return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x); 381 } 382 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent16_8)( 383 CppTypeFor<TypeCategory::Real, 16> x) { 384 return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x); 385 } 386 #endif 387 388 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor4_1)( 389 CppTypeFor<TypeCategory::Real, 4> x) { 390 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x); 391 } 392 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor4_2)( 393 CppTypeFor<TypeCategory::Real, 4> x) { 394 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x); 395 } 396 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor4_4)( 397 CppTypeFor<TypeCategory::Real, 4> x) { 398 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x); 399 } 400 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor4_8)( 401 CppTypeFor<TypeCategory::Real, 4> x) { 402 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x); 403 } 404 #ifdef __SIZEOF_INT128__ 405 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor4_16)( 406 CppTypeFor<TypeCategory::Real, 4> x) { 407 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x); 408 } 409 #endif 410 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor8_1)( 411 CppTypeFor<TypeCategory::Real, 8> x) { 412 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x); 413 } 414 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor8_2)( 415 CppTypeFor<TypeCategory::Real, 8> x) { 416 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x); 417 } 418 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor8_4)( 419 CppTypeFor<TypeCategory::Real, 8> x) { 420 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x); 421 } 422 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor8_8)( 423 CppTypeFor<TypeCategory::Real, 8> x) { 424 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x); 425 } 426 #ifdef __SIZEOF_INT128__ 427 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor8_16)( 428 CppTypeFor<TypeCategory::Real, 8> x) { 429 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x); 430 } 431 #endif 432 #if LDBL_MANT_DIG == 64 433 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor10_1)( 434 CppTypeFor<TypeCategory::Real, 10> x) { 435 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x); 436 } 437 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor10_2)( 438 CppTypeFor<TypeCategory::Real, 10> x) { 439 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x); 440 } 441 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor10_4)( 442 CppTypeFor<TypeCategory::Real, 10> x) { 443 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x); 444 } 445 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor10_8)( 446 CppTypeFor<TypeCategory::Real, 10> x) { 447 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x); 448 } 449 #ifdef __SIZEOF_INT128__ 450 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor10_16)( 451 CppTypeFor<TypeCategory::Real, 10> x) { 452 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x); 453 } 454 #endif 455 #elif LDBL_MANT_DIG == 113 456 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor16_1)( 457 CppTypeFor<TypeCategory::Real, 16> x) { 458 return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x); 459 } 460 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor16_2)( 461 CppTypeFor<TypeCategory::Real, 16> x) { 462 return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x); 463 } 464 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor16_4)( 465 CppTypeFor<TypeCategory::Real, 16> x) { 466 return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x); 467 } 468 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor16_8)( 469 CppTypeFor<TypeCategory::Real, 16> x) { 470 return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x); 471 } 472 #ifdef __SIZEOF_INT128__ 473 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor16_16)( 474 CppTypeFor<TypeCategory::Real, 16> x) { 475 return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x); 476 } 477 #endif 478 #endif 479 480 CppTypeFor<TypeCategory::Real, 4> RTNAME(Fraction4)( 481 CppTypeFor<TypeCategory::Real, 4> x) { 482 return Fraction(x); 483 } 484 CppTypeFor<TypeCategory::Real, 8> RTNAME(Fraction8)( 485 CppTypeFor<TypeCategory::Real, 8> x) { 486 return Fraction(x); 487 } 488 #if LDBL_MANT_DIG == 64 489 CppTypeFor<TypeCategory::Real, 10> RTNAME(Fraction10)( 490 CppTypeFor<TypeCategory::Real, 10> x) { 491 return Fraction(x); 492 } 493 #elif LDBL_MANT_DIG == 113 494 CppTypeFor<TypeCategory::Real, 16> RTNAME(Fraction16)( 495 CppTypeFor<TypeCategory::Real, 16> x) { 496 return Fraction(x); 497 } 498 #endif 499 500 bool RTNAME(IsFinite4)(CppTypeFor<TypeCategory::Real, 4> x) { 501 return std::isfinite(x); 502 } 503 bool RTNAME(IsFinite8)(CppTypeFor<TypeCategory::Real, 8> x) { 504 return std::isfinite(x); 505 } 506 #if LDBL_MANT_DIG == 64 507 bool RTNAME(IsFinite10)(CppTypeFor<TypeCategory::Real, 10> x) { 508 return std::isfinite(x); 509 } 510 #elif LDBL_MANT_DIG == 113 511 bool RTNAME(IsFinite16)(CppTypeFor<TypeCategory::Real, 16> x) { 512 return std::isfinite(x); 513 } 514 #endif 515 516 bool RTNAME(IsNaN4)(CppTypeFor<TypeCategory::Real, 4> x) { 517 return std::isnan(x); 518 } 519 bool RTNAME(IsNaN8)(CppTypeFor<TypeCategory::Real, 8> x) { 520 return std::isnan(x); 521 } 522 #if LDBL_MANT_DIG == 64 523 bool RTNAME(IsNaN10)(CppTypeFor<TypeCategory::Real, 10> x) { 524 return std::isnan(x); 525 } 526 #elif LDBL_MANT_DIG == 113 527 bool RTNAME(IsNaN16)(CppTypeFor<TypeCategory::Real, 16> x) { 528 return std::isnan(x); 529 } 530 #endif 531 532 CppTypeFor<TypeCategory::Integer, 1> RTNAME(ModInteger1)( 533 CppTypeFor<TypeCategory::Integer, 1> x, 534 CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile, 535 int sourceLine) { 536 return IntMod<false>(x, p, sourceFile, sourceLine); 537 } 538 CppTypeFor<TypeCategory::Integer, 2> RTNAME(ModInteger2)( 539 CppTypeFor<TypeCategory::Integer, 2> x, 540 CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile, 541 int sourceLine) { 542 return IntMod<false>(x, p, sourceFile, sourceLine); 543 } 544 CppTypeFor<TypeCategory::Integer, 4> RTNAME(ModInteger4)( 545 CppTypeFor<TypeCategory::Integer, 4> x, 546 CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile, 547 int sourceLine) { 548 return IntMod<false>(x, p, sourceFile, sourceLine); 549 } 550 CppTypeFor<TypeCategory::Integer, 8> RTNAME(ModInteger8)( 551 CppTypeFor<TypeCategory::Integer, 8> x, 552 CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile, 553 int sourceLine) { 554 return IntMod<false>(x, p, sourceFile, sourceLine); 555 } 556 #ifdef __SIZEOF_INT128__ 557 CppTypeFor<TypeCategory::Integer, 16> RTNAME(ModInteger16)( 558 CppTypeFor<TypeCategory::Integer, 16> x, 559 CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile, 560 int sourceLine) { 561 return IntMod<false>(x, p, sourceFile, sourceLine); 562 } 563 #endif 564 CppTypeFor<TypeCategory::Real, 4> RTNAME(ModReal4)( 565 CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p, 566 const char *sourceFile, int sourceLine) { 567 return RealMod<false>(x, p, sourceFile, sourceLine); 568 } 569 CppTypeFor<TypeCategory::Real, 8> RTNAME(ModReal8)( 570 CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p, 571 const char *sourceFile, int sourceLine) { 572 return RealMod<false>(x, p, sourceFile, sourceLine); 573 } 574 #if LDBL_MANT_DIG == 64 575 CppTypeFor<TypeCategory::Real, 10> RTNAME(ModReal10)( 576 CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p, 577 const char *sourceFile, int sourceLine) { 578 return RealMod<false>(x, p, sourceFile, sourceLine); 579 } 580 #elif LDBL_MANT_DIG == 113 581 CppTypeFor<TypeCategory::Real, 16> RTNAME(ModReal16)( 582 CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p, 583 const char *sourceFile, int sourceLine) { 584 return RealMod<false>(x, p, sourceFile, sourceLine); 585 } 586 #endif 587 588 CppTypeFor<TypeCategory::Integer, 1> RTNAME(ModuloInteger1)( 589 CppTypeFor<TypeCategory::Integer, 1> x, 590 CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile, 591 int sourceLine) { 592 return IntMod<true>(x, p, sourceFile, sourceLine); 593 } 594 CppTypeFor<TypeCategory::Integer, 2> RTNAME(ModuloInteger2)( 595 CppTypeFor<TypeCategory::Integer, 2> x, 596 CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile, 597 int sourceLine) { 598 return IntMod<true>(x, p, sourceFile, sourceLine); 599 } 600 CppTypeFor<TypeCategory::Integer, 4> RTNAME(ModuloInteger4)( 601 CppTypeFor<TypeCategory::Integer, 4> x, 602 CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile, 603 int sourceLine) { 604 return IntMod<true>(x, p, sourceFile, sourceLine); 605 } 606 CppTypeFor<TypeCategory::Integer, 8> RTNAME(ModuloInteger8)( 607 CppTypeFor<TypeCategory::Integer, 8> x, 608 CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile, 609 int sourceLine) { 610 return IntMod<true>(x, p, sourceFile, sourceLine); 611 } 612 #ifdef __SIZEOF_INT128__ 613 CppTypeFor<TypeCategory::Integer, 16> RTNAME(ModuloInteger16)( 614 CppTypeFor<TypeCategory::Integer, 16> x, 615 CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile, 616 int sourceLine) { 617 return IntMod<true>(x, p, sourceFile, sourceLine); 618 } 619 #endif 620 CppTypeFor<TypeCategory::Real, 4> RTNAME(ModuloReal4)( 621 CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p, 622 const char *sourceFile, int sourceLine) { 623 return RealMod<true>(x, p, sourceFile, sourceLine); 624 } 625 CppTypeFor<TypeCategory::Real, 8> RTNAME(ModuloReal8)( 626 CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p, 627 const char *sourceFile, int sourceLine) { 628 return RealMod<true>(x, p, sourceFile, sourceLine); 629 } 630 #if LDBL_MANT_DIG == 64 631 CppTypeFor<TypeCategory::Real, 10> RTNAME(ModuloReal10)( 632 CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p, 633 const char *sourceFile, int sourceLine) { 634 return RealMod<true>(x, p, sourceFile, sourceLine); 635 } 636 #elif LDBL_MANT_DIG == 113 637 CppTypeFor<TypeCategory::Real, 16> RTNAME(ModuloReal16)( 638 CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p, 639 const char *sourceFile, int sourceLine) { 640 return RealMod<true>(x, p, sourceFile, sourceLine); 641 } 642 #endif 643 644 CppTypeFor<TypeCategory::Real, 4> RTNAME(Nearest4)( 645 CppTypeFor<TypeCategory::Real, 4> x, bool positive) { 646 return Nearest<24>(x, positive); 647 } 648 CppTypeFor<TypeCategory::Real, 8> RTNAME(Nearest8)( 649 CppTypeFor<TypeCategory::Real, 8> x, bool positive) { 650 return Nearest<53>(x, positive); 651 } 652 #if LDBL_MANT_DIG == 64 653 CppTypeFor<TypeCategory::Real, 10> RTNAME(Nearest10)( 654 CppTypeFor<TypeCategory::Real, 10> x, bool positive) { 655 return Nearest<64>(x, positive); 656 } 657 #elif LDBL_MANT_DIG == 113 658 CppTypeFor<TypeCategory::Real, 16> RTNAME(Nearest16)( 659 CppTypeFor<TypeCategory::Real, 16> x, bool positive) { 660 return Nearest<113>(x, positive); 661 } 662 #endif 663 664 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint4_1)( 665 CppTypeFor<TypeCategory::Real, 4> x) { 666 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x); 667 } 668 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint4_2)( 669 CppTypeFor<TypeCategory::Real, 4> x) { 670 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x); 671 } 672 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint4_4)( 673 CppTypeFor<TypeCategory::Real, 4> x) { 674 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x); 675 } 676 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint4_8)( 677 CppTypeFor<TypeCategory::Real, 4> x) { 678 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x); 679 } 680 #ifdef __SIZEOF_INT128__ 681 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint4_16)( 682 CppTypeFor<TypeCategory::Real, 4> x) { 683 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x); 684 } 685 #endif 686 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint8_1)( 687 CppTypeFor<TypeCategory::Real, 8> x) { 688 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x); 689 } 690 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint8_2)( 691 CppTypeFor<TypeCategory::Real, 8> x) { 692 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x); 693 } 694 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint8_4)( 695 CppTypeFor<TypeCategory::Real, 8> x) { 696 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x); 697 } 698 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint8_8)( 699 CppTypeFor<TypeCategory::Real, 8> x) { 700 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x); 701 } 702 #ifdef __SIZEOF_INT128__ 703 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint8_16)( 704 CppTypeFor<TypeCategory::Real, 8> x) { 705 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x); 706 } 707 #endif 708 #if LDBL_MANT_DIG == 64 709 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint10_1)( 710 CppTypeFor<TypeCategory::Real, 10> x) { 711 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x); 712 } 713 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint10_2)( 714 CppTypeFor<TypeCategory::Real, 10> x) { 715 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x); 716 } 717 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint10_4)( 718 CppTypeFor<TypeCategory::Real, 10> x) { 719 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x); 720 } 721 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint10_8)( 722 CppTypeFor<TypeCategory::Real, 10> x) { 723 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x); 724 } 725 #ifdef __SIZEOF_INT128__ 726 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint10_16)( 727 CppTypeFor<TypeCategory::Real, 10> x) { 728 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x); 729 } 730 #endif 731 #elif LDBL_MANT_DIG == 113 732 CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint16_1)( 733 CppTypeFor<TypeCategory::Real, 16> x) { 734 return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x); 735 } 736 CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint16_2)( 737 CppTypeFor<TypeCategory::Real, 16> x) { 738 return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x); 739 } 740 CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint16_4)( 741 CppTypeFor<TypeCategory::Real, 16> x) { 742 return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x); 743 } 744 CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint16_8)( 745 CppTypeFor<TypeCategory::Real, 16> x) { 746 return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x); 747 } 748 #ifdef __SIZEOF_INT128__ 749 CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint16_16)( 750 CppTypeFor<TypeCategory::Real, 16> x) { 751 return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x); 752 } 753 #endif 754 #endif 755 756 CppTypeFor<TypeCategory::Real, 4> RTNAME(RRSpacing4)( 757 CppTypeFor<TypeCategory::Real, 4> x) { 758 return RRSpacing<24>(x); 759 } 760 CppTypeFor<TypeCategory::Real, 8> RTNAME(RRSpacing8)( 761 CppTypeFor<TypeCategory::Real, 8> x) { 762 return RRSpacing<53>(x); 763 } 764 #if LDBL_MANT_DIG == 64 765 CppTypeFor<TypeCategory::Real, 10> RTNAME(RRSpacing10)( 766 CppTypeFor<TypeCategory::Real, 10> x) { 767 return RRSpacing<64>(x); 768 } 769 #elif LDBL_MANT_DIG == 113 770 CppTypeFor<TypeCategory::Real, 16> RTNAME(RRSpacing16)( 771 CppTypeFor<TypeCategory::Real, 16> x) { 772 return RRSpacing<113>(x); 773 } 774 #endif 775 776 CppTypeFor<TypeCategory::Real, 4> RTNAME(SetExponent4)( 777 CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) { 778 return SetExponent(x, p); 779 } 780 CppTypeFor<TypeCategory::Real, 8> RTNAME(SetExponent8)( 781 CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) { 782 return SetExponent(x, p); 783 } 784 #if LDBL_MANT_DIG == 64 785 CppTypeFor<TypeCategory::Real, 10> RTNAME(SetExponent10)( 786 CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) { 787 return SetExponent(x, p); 788 } 789 #elif LDBL_MANT_DIG == 113 790 CppTypeFor<TypeCategory::Real, 16> RTNAME(SetExponent16)( 791 CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) { 792 return SetExponent(x, p); 793 } 794 #endif 795 796 CppTypeFor<TypeCategory::Real, 4> RTNAME(Scale4)( 797 CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) { 798 return Scale(x, p); 799 } 800 CppTypeFor<TypeCategory::Real, 8> RTNAME(Scale8)( 801 CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) { 802 return Scale(x, p); 803 } 804 #if LDBL_MANT_DIG == 64 805 CppTypeFor<TypeCategory::Real, 10> RTNAME(Scale10)( 806 CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) { 807 return Scale(x, p); 808 } 809 #elif LDBL_MANT_DIG == 113 810 CppTypeFor<TypeCategory::Real, 16> RTNAME(Scale16)( 811 CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) { 812 return Scale(x, p); 813 } 814 #endif 815 816 // SELECTED_INT_KIND 817 CppTypeFor<TypeCategory::Integer, 4> RTNAME(SelectedIntKind)( 818 const char *source, int line, void *x, int xKind) { 819 #ifdef __SIZEOF_INT128__ 820 CppTypeFor<TypeCategory::Integer, 16> r = 821 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>( 822 source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 16); 823 #else 824 std::int64_t r = getIntArgValue<std::int64_t>( 825 source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 8); 826 #endif 827 return SelectedIntKind(r); 828 } 829 830 // SELECTED_REAL_KIND 831 CppTypeFor<TypeCategory::Integer, 4> RTNAME(SelectedRealKind)( 832 const char *source, int line, void *precision, int pKind, void *range, 833 int rKind, void *radix, int dKind) { 834 #ifdef __SIZEOF_INT128__ 835 CppTypeFor<TypeCategory::Integer, 16> p = 836 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>( 837 source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 16); 838 CppTypeFor<TypeCategory::Integer, 16> r = 839 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>( 840 source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 16); 841 CppTypeFor<TypeCategory::Integer, 16> d = 842 getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>( 843 source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 16); 844 #else 845 std::int64_t p = getIntArgValue<std::int64_t>( 846 source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 8); 847 std::int64_t r = getIntArgValue<std::int64_t>( 848 source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 8); 849 std::int64_t d = getIntArgValue<std::int64_t>( 850 source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 8); 851 #endif 852 return SelectedRealKind(p, r, d); 853 } 854 855 CppTypeFor<TypeCategory::Real, 4> RTNAME(Spacing4)( 856 CppTypeFor<TypeCategory::Real, 4> x) { 857 return Spacing<24>(x); 858 } 859 CppTypeFor<TypeCategory::Real, 8> RTNAME(Spacing8)( 860 CppTypeFor<TypeCategory::Real, 8> x) { 861 return Spacing<53>(x); 862 } 863 #if LDBL_MANT_DIG == 64 864 CppTypeFor<TypeCategory::Real, 10> RTNAME(Spacing10)( 865 CppTypeFor<TypeCategory::Real, 10> x) { 866 return Spacing<64>(x); 867 } 868 #elif LDBL_MANT_DIG == 113 869 CppTypeFor<TypeCategory::Real, 16> RTNAME(Spacing16)( 870 CppTypeFor<TypeCategory::Real, 16> x) { 871 return Spacing<113>(x); 872 } 873 #endif 874 } // extern "C" 875 } // namespace Fortran::runtime 876