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/Common/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 RT_API_ATTRS RES getIntArgValue(const char *source, int line, void *arg, |
21 | int kind, 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> |
53 | inline RT_API_ATTRS RESULT Nint(ARG x) { |
54 | if (x >= 0) { |
55 | return std::trunc(x + ARG{0.5}); |
56 | } else { |
57 | return std::trunc(x - ARG{0.5}); |
58 | } |
59 | } |
60 | |
61 | // CEILING & FLOOR (16.9.43, .79) |
62 | template <typename RESULT, typename ARG> |
63 | inline RT_API_ATTRS RESULT Ceiling(ARG x) { |
64 | return std::ceil(x); |
65 | } |
66 | template <typename RESULT, typename ARG> |
67 | inline RT_API_ATTRS RESULT Floor(ARG x) { |
68 | return std::floor(x); |
69 | } |
70 | |
71 | // EXPONENT (16.9.75) |
72 | template <typename RESULT, typename ARG> |
73 | inline RT_API_ATTRS RESULT Exponent(ARG x) { |
74 | if (std::isinf(x) || std::isnan(x)) { |
75 | return std::numeric_limits<RESULT>::max(); // +/-Inf, NaN -> HUGE(0) |
76 | } else if (x == 0) { |
77 | return 0; // 0 -> 0 |
78 | } else { |
79 | return std::ilogb(x) + 1; |
80 | } |
81 | } |
82 | |
83 | // Suppress the warnings about calling __host__-only std::frexp, |
84 | // defined in C++ STD header files, from __device__ code. |
85 | RT_DIAG_PUSH |
86 | RT_DIAG_DISABLE_CALL_HOST_FROM_DEVICE_WARN |
87 | |
88 | // FRACTION (16.9.80) |
89 | template <typename T> inline RT_API_ATTRS T Fraction(T x) { |
90 | if (std::isnan(x)) { |
91 | return x; // NaN -> same NaN |
92 | } else if (std::isinf(x)) { |
93 | return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN |
94 | } else if (x == 0) { |
95 | return x; // 0 -> same 0 |
96 | } else { |
97 | int ignoredExp; |
98 | return std::frexp(x, &ignoredExp); |
99 | } |
100 | } |
101 | |
102 | RT_DIAG_POP |
103 | |
104 | // SET_EXPONENT (16.9.171) |
105 | template <typename T> inline RT_API_ATTRS T SetExponent(T x, std::int64_t p) { |
106 | if (std::isnan(x)) { |
107 | return x; // NaN -> same NaN |
108 | } else if (std::isinf(x)) { |
109 | return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN |
110 | } else if (x == 0) { |
111 | return x; // return negative zero if x is negative zero |
112 | } else { |
113 | int expo{std::ilogb(x) + 1}; |
114 | auto ip{static_cast<int>(p - expo)}; |
115 | if (ip != p - expo) { |
116 | ip = p < 0 ? std::numeric_limits<int>::min() |
117 | : std::numeric_limits<int>::max(); |
118 | } |
119 | return std::ldexp(x, ip); // x*2**(p-e) |
120 | } |
121 | } |
122 | |
123 | // MOD & MODULO (16.9.135, .136) |
124 | template <bool IS_MODULO, typename T> |
125 | inline RT_API_ATTRS T IntMod(T x, T p, const char *sourceFile, int sourceLine) { |
126 | if (p == 0) { |
127 | Terminator{sourceFile, sourceLine}.Crash( |
128 | IS_MODULO ? "MODULO with P==0" : "MOD with P==0" ); |
129 | } |
130 | auto mod{x - (x / p) * p}; |
131 | if (IS_MODULO && (x > 0) != (p > 0)) { |
132 | mod += p; |
133 | } |
134 | return mod; |
135 | } |
136 | template <bool IS_MODULO, typename T> |
137 | inline RT_API_ATTRS T RealMod( |
138 | T a, T p, const char *sourceFile, int sourceLine) { |
139 | if (p == 0) { |
140 | Terminator{sourceFile, sourceLine}.Crash( |
141 | IS_MODULO ? "MODULO with P==0" : "MOD with P==0" ); |
142 | } |
143 | if (std::isnan(a) || std::isnan(p) || std::isinf(a)) { |
144 | return std::numeric_limits<T>::quiet_NaN(); |
145 | } else if (std::isinf(p)) { |
146 | return a; |
147 | } |
148 | T aAbs{std::abs(a)}; |
149 | T pAbs{std::abs(p)}; |
150 | if (aAbs <= static_cast<T>(std::numeric_limits<std::int64_t>::max()) && |
151 | pAbs <= static_cast<T>(std::numeric_limits<std::int64_t>::max())) { |
152 | if (auto aInt{static_cast<std::int64_t>(a)}; a == aInt) { |
153 | if (auto pInt{static_cast<std::int64_t>(p)}; p == pInt) { |
154 | // Fast exact case for integer operands |
155 | auto mod{aInt - (aInt / pInt) * pInt}; |
156 | if (IS_MODULO && (aInt > 0) != (pInt > 0)) { |
157 | mod += pInt; |
158 | } |
159 | return static_cast<T>(mod); |
160 | } |
161 | } |
162 | } |
163 | if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double> || |
164 | std::is_same_v<T, long double>) { |
165 | // std::fmod() semantics on signed operands seems to match |
166 | // the requirements of MOD(). MODULO() needs adjustment. |
167 | T result{std::fmod(a, p)}; |
168 | if constexpr (IS_MODULO) { |
169 | if ((a < 0) != (p < 0)) { |
170 | if (result == 0.) { |
171 | result = -result; |
172 | } else { |
173 | result += p; |
174 | } |
175 | } |
176 | } |
177 | return result; |
178 | } else { |
179 | // The standard defines MOD(a,p)=a-AINT(a/p)*p and |
180 | // MODULO(a,p)=a-FLOOR(a/p)*p, but those definitions lose |
181 | // precision badly due to cancellation when ABS(a) is |
182 | // much larger than ABS(p). |
183 | // Insights: |
184 | // - MOD(a,p)=MOD(a-n*p,p) when a>0, p>0, integer n>0, and a>=n*p |
185 | // - when n is a power of two, n*p is exact |
186 | // - as a>=n*p, a-n*p does not round. |
187 | // So repeatedly reduce a by all n*p in decreasing order of n; |
188 | // what's left is the desired remainder. This is basically |
189 | // the same algorithm as arbitrary precision binary long division, |
190 | // discarding the quotient. |
191 | T tmp{aAbs}; |
192 | for (T adj{SetExponent(pAbs, Exponent<int>(aAbs))}; tmp >= pAbs; adj /= 2) { |
193 | if (tmp >= adj) { |
194 | tmp -= adj; |
195 | if (tmp == 0) { |
196 | break; |
197 | } |
198 | } |
199 | } |
200 | if (a < 0) { |
201 | tmp = -tmp; |
202 | } |
203 | if constexpr (IS_MODULO) { |
204 | if ((a < 0) != (p < 0)) { |
205 | tmp += p; |
206 | } |
207 | } |
208 | return tmp; |
209 | } |
210 | } |
211 | |
212 | // RRSPACING (16.9.164) |
213 | template <int PREC, typename T> inline RT_API_ATTRS T RRSpacing(T x) { |
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 0; // 0 -> 0 |
220 | } else { |
221 | return std::ldexp(std::abs(x), PREC - (std::ilogb(x) + 1)); |
222 | } |
223 | } |
224 | |
225 | // SCALE (16.9.166) |
226 | template <typename T> inline RT_API_ATTRS T Scale(T x, std::int64_t p) { |
227 | auto ip{static_cast<int>(p)}; |
228 | if (ip != p) { |
229 | ip = p < 0 ? std::numeric_limits<int>::min() |
230 | : std::numeric_limits<int>::max(); |
231 | } |
232 | return std::ldexp(x, p); // x*2**p |
233 | } |
234 | |
235 | // SELECTED_INT_KIND (16.9.169) |
236 | template <typename T> |
237 | inline RT_API_ATTRS CppTypeFor<TypeCategory::Integer, 4> SelectedIntKind(T x) { |
238 | if (x <= 2) { |
239 | return 1; |
240 | } else if (x <= 4) { |
241 | return 2; |
242 | } else if (x <= 9) { |
243 | return 4; |
244 | } else if (x <= 18) { |
245 | return 8; |
246 | #ifdef __SIZEOF_INT128__ |
247 | } else if (x <= 38) { |
248 | return 16; |
249 | #endif |
250 | } |
251 | return -1; |
252 | } |
253 | |
254 | // SELECTED_REAL_KIND (16.9.170) |
255 | template <typename P, typename R, typename D> |
256 | inline RT_API_ATTRS CppTypeFor<TypeCategory::Integer, 4> SelectedRealKind( |
257 | P p, R r, D d) { |
258 | if (d != 2) { |
259 | return -5; |
260 | } |
261 | |
262 | int error{0}; |
263 | int kind{0}; |
264 | if (p <= 3) { |
265 | kind = 2; |
266 | } else if (p <= 6) { |
267 | kind = 4; |
268 | } else if (p <= 15) { |
269 | kind = 8; |
270 | #if LDBL_MANT_DIG == 64 |
271 | } else if (p <= 18) { |
272 | kind = 10; |
273 | } else if (p <= 33) { |
274 | kind = 16; |
275 | #elif LDBL_MANT_DIG == 113 |
276 | } else if (p <= 33) { |
277 | kind = 16; |
278 | #endif |
279 | } else { |
280 | error -= 1; |
281 | } |
282 | |
283 | if (r <= 4) { |
284 | kind = kind < 2 ? 2 : kind; |
285 | } else if (r <= 37) { |
286 | kind = kind < 3 ? (p == 3 ? 4 : 3) : kind; |
287 | } else if (r <= 307) { |
288 | kind = kind < 8 ? 8 : kind; |
289 | #if LDBL_MANT_DIG == 64 |
290 | } else if (r <= 4931) { |
291 | kind = kind < 10 ? 10 : kind; |
292 | #elif LDBL_MANT_DIG == 113 |
293 | } else if (r <= 4931) { |
294 | kind = kind < 16 ? 16 : kind; |
295 | #endif |
296 | } else { |
297 | error -= 2; |
298 | } |
299 | |
300 | return error ? error : kind; |
301 | } |
302 | |
303 | // SPACING (16.9.180) |
304 | template <int PREC, typename T> inline RT_API_ATTRS T Spacing(T x) { |
305 | if (std::isnan(x)) { |
306 | return x; // NaN -> same NaN |
307 | } else if (std::isinf(x)) { |
308 | return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN |
309 | } else if (x == 0) { |
310 | // The standard-mandated behavior seems broken, since TINY() can't be |
311 | // subnormal. |
312 | return std::numeric_limits<T>::min(); // 0 -> TINY(x) |
313 | } else { |
314 | T result{ |
315 | std::ldexp(static_cast<T>(1.0), std::ilogb(x) + 1 - PREC)}; // 2**(e-p) |
316 | return result == 0 ? /*TINY(x)*/ std::numeric_limits<T>::min() : result; |
317 | } |
318 | } |
319 | |
320 | // NEAREST (16.9.139) |
321 | template <int PREC, typename T> |
322 | inline RT_API_ATTRS T Nearest(T x, bool positive) { |
323 | if (positive) { |
324 | return std::nextafter(x, std::numeric_limits<T>::infinity()); |
325 | } else { |
326 | return std::nextafter(x, -std::numeric_limits<T>::infinity()); |
327 | } |
328 | } |
329 | |
330 | // Exponentiation operator for (Real ** Integer) cases (10.1.5.2.1). |
331 | template <typename BTy, typename ETy> |
332 | RT_API_ATTRS BTy FPowI(BTy base, ETy exp) { |
333 | if (exp == ETy{0}) |
334 | return BTy{1}; |
335 | bool isNegativePower{exp < ETy{0}}; |
336 | bool isMinPower{exp == std::numeric_limits<ETy>::min()}; |
337 | if (isMinPower) { |
338 | exp = std::numeric_limits<ETy>::max(); |
339 | } else if (isNegativePower) { |
340 | exp = -exp; |
341 | } |
342 | BTy result{1}; |
343 | BTy origBase{base}; |
344 | while (true) { |
345 | if (exp & ETy{1}) { |
346 | result *= base; |
347 | } |
348 | exp >>= 1; |
349 | if (exp == ETy{0}) { |
350 | break; |
351 | } |
352 | base *= base; |
353 | } |
354 | if (isMinPower) { |
355 | result *= origBase; |
356 | } |
357 | if (isNegativePower) { |
358 | result = BTy{1} / result; |
359 | } |
360 | return result; |
361 | } |
362 | |
363 | extern "C" { |
364 | RT_EXT_API_GROUP_BEGIN |
365 | |
366 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Ceiling4_1)( |
367 | CppTypeFor<TypeCategory::Real, 4> x) { |
368 | return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x); |
369 | } |
370 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Ceiling4_2)( |
371 | CppTypeFor<TypeCategory::Real, 4> x) { |
372 | return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x); |
373 | } |
374 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Ceiling4_4)( |
375 | CppTypeFor<TypeCategory::Real, 4> x) { |
376 | return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x); |
377 | } |
378 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Ceiling4_8)( |
379 | CppTypeFor<TypeCategory::Real, 4> x) { |
380 | return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x); |
381 | } |
382 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
383 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Ceiling4_16)( |
384 | CppTypeFor<TypeCategory::Real, 4> x) { |
385 | return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x); |
386 | } |
387 | #endif |
388 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Ceiling8_1)( |
389 | CppTypeFor<TypeCategory::Real, 8> x) { |
390 | return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x); |
391 | } |
392 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Ceiling8_2)( |
393 | CppTypeFor<TypeCategory::Real, 8> x) { |
394 | return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x); |
395 | } |
396 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Ceiling8_4)( |
397 | CppTypeFor<TypeCategory::Real, 8> x) { |
398 | return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x); |
399 | } |
400 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Ceiling8_8)( |
401 | CppTypeFor<TypeCategory::Real, 8> x) { |
402 | return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x); |
403 | } |
404 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
405 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Ceiling8_16)( |
406 | CppTypeFor<TypeCategory::Real, 8> x) { |
407 | return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x); |
408 | } |
409 | #endif |
410 | #if LDBL_MANT_DIG == 64 |
411 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Ceiling10_1)( |
412 | CppTypeFor<TypeCategory::Real, 10> x) { |
413 | return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x); |
414 | } |
415 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Ceiling10_2)( |
416 | CppTypeFor<TypeCategory::Real, 10> x) { |
417 | return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x); |
418 | } |
419 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Ceiling10_4)( |
420 | CppTypeFor<TypeCategory::Real, 10> x) { |
421 | return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x); |
422 | } |
423 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Ceiling10_8)( |
424 | CppTypeFor<TypeCategory::Real, 10> x) { |
425 | return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x); |
426 | } |
427 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
428 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Ceiling10_16)( |
429 | CppTypeFor<TypeCategory::Real, 10> x) { |
430 | return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x); |
431 | } |
432 | #endif |
433 | #elif LDBL_MANT_DIG == 113 |
434 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Ceiling16_1)( |
435 | CppTypeFor<TypeCategory::Real, 16> x) { |
436 | return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x); |
437 | } |
438 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Ceiling16_2)( |
439 | CppTypeFor<TypeCategory::Real, 16> x) { |
440 | return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x); |
441 | } |
442 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Ceiling16_4)( |
443 | CppTypeFor<TypeCategory::Real, 16> x) { |
444 | return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x); |
445 | } |
446 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Ceiling16_8)( |
447 | CppTypeFor<TypeCategory::Real, 16> x) { |
448 | return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x); |
449 | } |
450 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
451 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Ceiling16_16)( |
452 | CppTypeFor<TypeCategory::Real, 16> x) { |
453 | return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x); |
454 | } |
455 | #endif |
456 | #endif |
457 | |
458 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Exponent4_4)( |
459 | CppTypeFor<TypeCategory::Real, 4> x) { |
460 | return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x); |
461 | } |
462 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Exponent4_8)( |
463 | CppTypeFor<TypeCategory::Real, 4> x) { |
464 | return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x); |
465 | } |
466 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Exponent8_4)( |
467 | CppTypeFor<TypeCategory::Real, 8> x) { |
468 | return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x); |
469 | } |
470 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Exponent8_8)( |
471 | CppTypeFor<TypeCategory::Real, 8> x) { |
472 | return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x); |
473 | } |
474 | #if LDBL_MANT_DIG == 64 |
475 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Exponent10_4)( |
476 | CppTypeFor<TypeCategory::Real, 10> x) { |
477 | return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x); |
478 | } |
479 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Exponent10_8)( |
480 | CppTypeFor<TypeCategory::Real, 10> x) { |
481 | return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x); |
482 | } |
483 | #elif LDBL_MANT_DIG == 113 |
484 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Exponent16_4)( |
485 | CppTypeFor<TypeCategory::Real, 16> x) { |
486 | return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x); |
487 | } |
488 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Exponent16_8)( |
489 | CppTypeFor<TypeCategory::Real, 16> x) { |
490 | return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x); |
491 | } |
492 | #endif |
493 | |
494 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Floor4_1)( |
495 | CppTypeFor<TypeCategory::Real, 4> x) { |
496 | return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x); |
497 | } |
498 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Floor4_2)( |
499 | CppTypeFor<TypeCategory::Real, 4> x) { |
500 | return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x); |
501 | } |
502 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Floor4_4)( |
503 | CppTypeFor<TypeCategory::Real, 4> x) { |
504 | return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x); |
505 | } |
506 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Floor4_8)( |
507 | CppTypeFor<TypeCategory::Real, 4> x) { |
508 | return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x); |
509 | } |
510 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
511 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Floor4_16)( |
512 | CppTypeFor<TypeCategory::Real, 4> x) { |
513 | return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x); |
514 | } |
515 | #endif |
516 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Floor8_1)( |
517 | CppTypeFor<TypeCategory::Real, 8> x) { |
518 | return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x); |
519 | } |
520 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Floor8_2)( |
521 | CppTypeFor<TypeCategory::Real, 8> x) { |
522 | return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x); |
523 | } |
524 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Floor8_4)( |
525 | CppTypeFor<TypeCategory::Real, 8> x) { |
526 | return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x); |
527 | } |
528 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Floor8_8)( |
529 | CppTypeFor<TypeCategory::Real, 8> x) { |
530 | return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x); |
531 | } |
532 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
533 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Floor8_16)( |
534 | CppTypeFor<TypeCategory::Real, 8> x) { |
535 | return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x); |
536 | } |
537 | #endif |
538 | #if LDBL_MANT_DIG == 64 |
539 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Floor10_1)( |
540 | CppTypeFor<TypeCategory::Real, 10> x) { |
541 | return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x); |
542 | } |
543 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Floor10_2)( |
544 | CppTypeFor<TypeCategory::Real, 10> x) { |
545 | return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x); |
546 | } |
547 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Floor10_4)( |
548 | CppTypeFor<TypeCategory::Real, 10> x) { |
549 | return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x); |
550 | } |
551 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Floor10_8)( |
552 | CppTypeFor<TypeCategory::Real, 10> x) { |
553 | return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x); |
554 | } |
555 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
556 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Floor10_16)( |
557 | CppTypeFor<TypeCategory::Real, 10> x) { |
558 | return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x); |
559 | } |
560 | #endif |
561 | #elif LDBL_MANT_DIG == 113 |
562 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Floor16_1)( |
563 | CppTypeFor<TypeCategory::Real, 16> x) { |
564 | return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x); |
565 | } |
566 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Floor16_2)( |
567 | CppTypeFor<TypeCategory::Real, 16> x) { |
568 | return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x); |
569 | } |
570 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Floor16_4)( |
571 | CppTypeFor<TypeCategory::Real, 16> x) { |
572 | return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x); |
573 | } |
574 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Floor16_8)( |
575 | CppTypeFor<TypeCategory::Real, 16> x) { |
576 | return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x); |
577 | } |
578 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
579 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Floor16_16)( |
580 | CppTypeFor<TypeCategory::Real, 16> x) { |
581 | return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x); |
582 | } |
583 | #endif |
584 | #endif |
585 | |
586 | CppTypeFor<TypeCategory::Real, 4> RTDEF(Fraction4)( |
587 | CppTypeFor<TypeCategory::Real, 4> x) { |
588 | return Fraction(x); |
589 | } |
590 | CppTypeFor<TypeCategory::Real, 8> RTDEF(Fraction8)( |
591 | CppTypeFor<TypeCategory::Real, 8> x) { |
592 | return Fraction(x); |
593 | } |
594 | #if LDBL_MANT_DIG == 64 |
595 | CppTypeFor<TypeCategory::Real, 10> RTDEF(Fraction10)( |
596 | CppTypeFor<TypeCategory::Real, 10> x) { |
597 | return Fraction(x); |
598 | } |
599 | #elif LDBL_MANT_DIG == 113 |
600 | CppTypeFor<TypeCategory::Real, 16> RTDEF(Fraction16)( |
601 | CppTypeFor<TypeCategory::Real, 16> x) { |
602 | return Fraction(x); |
603 | } |
604 | #endif |
605 | |
606 | bool RTDEF(IsFinite4)(CppTypeFor<TypeCategory::Real, 4> x) { |
607 | return std::isfinite(x); |
608 | } |
609 | bool RTDEF(IsFinite8)(CppTypeFor<TypeCategory::Real, 8> x) { |
610 | return std::isfinite(x); |
611 | } |
612 | #if LDBL_MANT_DIG == 64 |
613 | bool RTDEF(IsFinite10)(CppTypeFor<TypeCategory::Real, 10> x) { |
614 | return std::isfinite(x); |
615 | } |
616 | #elif LDBL_MANT_DIG == 113 |
617 | bool RTDEF(IsFinite16)(CppTypeFor<TypeCategory::Real, 16> x) { |
618 | return std::isfinite(x); |
619 | } |
620 | #endif |
621 | |
622 | bool RTDEF(IsNaN4)(CppTypeFor<TypeCategory::Real, 4> x) { |
623 | return std::isnan(x); |
624 | } |
625 | bool RTDEF(IsNaN8)(CppTypeFor<TypeCategory::Real, 8> x) { |
626 | return std::isnan(x); |
627 | } |
628 | #if LDBL_MANT_DIG == 64 |
629 | bool RTDEF(IsNaN10)(CppTypeFor<TypeCategory::Real, 10> x) { |
630 | return std::isnan(x); |
631 | } |
632 | #elif LDBL_MANT_DIG == 113 |
633 | bool RTDEF(IsNaN16)(CppTypeFor<TypeCategory::Real, 16> x) { |
634 | return std::isnan(x); |
635 | } |
636 | #endif |
637 | |
638 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(ModInteger1)( |
639 | CppTypeFor<TypeCategory::Integer, 1> x, |
640 | CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile, |
641 | int sourceLine) { |
642 | return IntMod<false>(x, p, sourceFile, sourceLine); |
643 | } |
644 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(ModInteger2)( |
645 | CppTypeFor<TypeCategory::Integer, 2> x, |
646 | CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile, |
647 | int sourceLine) { |
648 | return IntMod<false>(x, p, sourceFile, sourceLine); |
649 | } |
650 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(ModInteger4)( |
651 | CppTypeFor<TypeCategory::Integer, 4> x, |
652 | CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile, |
653 | int sourceLine) { |
654 | return IntMod<false>(x, p, sourceFile, sourceLine); |
655 | } |
656 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(ModInteger8)( |
657 | CppTypeFor<TypeCategory::Integer, 8> x, |
658 | CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile, |
659 | int sourceLine) { |
660 | return IntMod<false>(x, p, sourceFile, sourceLine); |
661 | } |
662 | #ifdef __SIZEOF_INT128__ |
663 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(ModInteger16)( |
664 | CppTypeFor<TypeCategory::Integer, 16> x, |
665 | CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile, |
666 | int sourceLine) { |
667 | return IntMod<false>(x, p, sourceFile, sourceLine); |
668 | } |
669 | #endif |
670 | CppTypeFor<TypeCategory::Real, 4> RTDEF(ModReal4)( |
671 | CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p, |
672 | const char *sourceFile, int sourceLine) { |
673 | return RealMod<false>(x, p, sourceFile, sourceLine); |
674 | } |
675 | CppTypeFor<TypeCategory::Real, 8> RTDEF(ModReal8)( |
676 | CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p, |
677 | const char *sourceFile, int sourceLine) { |
678 | return RealMod<false>(x, p, sourceFile, sourceLine); |
679 | } |
680 | #if LDBL_MANT_DIG == 64 |
681 | CppTypeFor<TypeCategory::Real, 10> RTDEF(ModReal10)( |
682 | CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p, |
683 | const char *sourceFile, int sourceLine) { |
684 | return RealMod<false>(x, p, sourceFile, sourceLine); |
685 | } |
686 | #elif LDBL_MANT_DIG == 113 |
687 | CppTypeFor<TypeCategory::Real, 16> RTDEF(ModReal16)( |
688 | CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p, |
689 | const char *sourceFile, int sourceLine) { |
690 | return RealMod<false>(x, p, sourceFile, sourceLine); |
691 | } |
692 | #endif |
693 | |
694 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(ModuloInteger1)( |
695 | CppTypeFor<TypeCategory::Integer, 1> x, |
696 | CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile, |
697 | int sourceLine) { |
698 | return IntMod<true>(x, p, sourceFile, sourceLine); |
699 | } |
700 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(ModuloInteger2)( |
701 | CppTypeFor<TypeCategory::Integer, 2> x, |
702 | CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile, |
703 | int sourceLine) { |
704 | return IntMod<true>(x, p, sourceFile, sourceLine); |
705 | } |
706 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(ModuloInteger4)( |
707 | CppTypeFor<TypeCategory::Integer, 4> x, |
708 | CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile, |
709 | int sourceLine) { |
710 | return IntMod<true>(x, p, sourceFile, sourceLine); |
711 | } |
712 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(ModuloInteger8)( |
713 | CppTypeFor<TypeCategory::Integer, 8> x, |
714 | CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile, |
715 | int sourceLine) { |
716 | return IntMod<true>(x, p, sourceFile, sourceLine); |
717 | } |
718 | #ifdef __SIZEOF_INT128__ |
719 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(ModuloInteger16)( |
720 | CppTypeFor<TypeCategory::Integer, 16> x, |
721 | CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile, |
722 | int sourceLine) { |
723 | return IntMod<true>(x, p, sourceFile, sourceLine); |
724 | } |
725 | #endif |
726 | CppTypeFor<TypeCategory::Real, 4> RTDEF(ModuloReal4)( |
727 | CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p, |
728 | const char *sourceFile, int sourceLine) { |
729 | return RealMod<true>(x, p, sourceFile, sourceLine); |
730 | } |
731 | CppTypeFor<TypeCategory::Real, 8> RTDEF(ModuloReal8)( |
732 | CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p, |
733 | const char *sourceFile, int sourceLine) { |
734 | return RealMod<true>(x, p, sourceFile, sourceLine); |
735 | } |
736 | #if LDBL_MANT_DIG == 64 |
737 | CppTypeFor<TypeCategory::Real, 10> RTDEF(ModuloReal10)( |
738 | CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p, |
739 | const char *sourceFile, int sourceLine) { |
740 | return RealMod<true>(x, p, sourceFile, sourceLine); |
741 | } |
742 | #elif LDBL_MANT_DIG == 113 |
743 | CppTypeFor<TypeCategory::Real, 16> RTDEF(ModuloReal16)( |
744 | CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p, |
745 | const char *sourceFile, int sourceLine) { |
746 | return RealMod<true>(x, p, sourceFile, sourceLine); |
747 | } |
748 | #endif |
749 | |
750 | CppTypeFor<TypeCategory::Real, 4> RTDEF(Nearest4)( |
751 | CppTypeFor<TypeCategory::Real, 4> x, bool positive) { |
752 | return Nearest<24>(x, positive); |
753 | } |
754 | CppTypeFor<TypeCategory::Real, 8> RTDEF(Nearest8)( |
755 | CppTypeFor<TypeCategory::Real, 8> x, bool positive) { |
756 | return Nearest<53>(x, positive); |
757 | } |
758 | #if LDBL_MANT_DIG == 64 |
759 | CppTypeFor<TypeCategory::Real, 10> RTDEF(Nearest10)( |
760 | CppTypeFor<TypeCategory::Real, 10> x, bool positive) { |
761 | return Nearest<64>(x, positive); |
762 | } |
763 | #elif LDBL_MANT_DIG == 113 |
764 | CppTypeFor<TypeCategory::Real, 16> RTDEF(Nearest16)( |
765 | CppTypeFor<TypeCategory::Real, 16> x, bool positive) { |
766 | return Nearest<113>(x, positive); |
767 | } |
768 | #endif |
769 | |
770 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Nint4_1)( |
771 | CppTypeFor<TypeCategory::Real, 4> x) { |
772 | return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x); |
773 | } |
774 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Nint4_2)( |
775 | CppTypeFor<TypeCategory::Real, 4> x) { |
776 | return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x); |
777 | } |
778 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Nint4_4)( |
779 | CppTypeFor<TypeCategory::Real, 4> x) { |
780 | return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x); |
781 | } |
782 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Nint4_8)( |
783 | CppTypeFor<TypeCategory::Real, 4> x) { |
784 | return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x); |
785 | } |
786 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
787 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Nint4_16)( |
788 | CppTypeFor<TypeCategory::Real, 4> x) { |
789 | return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x); |
790 | } |
791 | #endif |
792 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Nint8_1)( |
793 | CppTypeFor<TypeCategory::Real, 8> x) { |
794 | return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x); |
795 | } |
796 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Nint8_2)( |
797 | CppTypeFor<TypeCategory::Real, 8> x) { |
798 | return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x); |
799 | } |
800 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Nint8_4)( |
801 | CppTypeFor<TypeCategory::Real, 8> x) { |
802 | return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x); |
803 | } |
804 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Nint8_8)( |
805 | CppTypeFor<TypeCategory::Real, 8> x) { |
806 | return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x); |
807 | } |
808 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
809 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Nint8_16)( |
810 | CppTypeFor<TypeCategory::Real, 8> x) { |
811 | return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x); |
812 | } |
813 | #endif |
814 | #if LDBL_MANT_DIG == 64 |
815 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Nint10_1)( |
816 | CppTypeFor<TypeCategory::Real, 10> x) { |
817 | return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x); |
818 | } |
819 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Nint10_2)( |
820 | CppTypeFor<TypeCategory::Real, 10> x) { |
821 | return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x); |
822 | } |
823 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Nint10_4)( |
824 | CppTypeFor<TypeCategory::Real, 10> x) { |
825 | return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x); |
826 | } |
827 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Nint10_8)( |
828 | CppTypeFor<TypeCategory::Real, 10> x) { |
829 | return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x); |
830 | } |
831 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
832 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Nint10_16)( |
833 | CppTypeFor<TypeCategory::Real, 10> x) { |
834 | return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x); |
835 | } |
836 | #endif |
837 | #elif LDBL_MANT_DIG == 113 |
838 | CppTypeFor<TypeCategory::Integer, 1> RTDEF(Nint16_1)( |
839 | CppTypeFor<TypeCategory::Real, 16> x) { |
840 | return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x); |
841 | } |
842 | CppTypeFor<TypeCategory::Integer, 2> RTDEF(Nint16_2)( |
843 | CppTypeFor<TypeCategory::Real, 16> x) { |
844 | return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x); |
845 | } |
846 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(Nint16_4)( |
847 | CppTypeFor<TypeCategory::Real, 16> x) { |
848 | return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x); |
849 | } |
850 | CppTypeFor<TypeCategory::Integer, 8> RTDEF(Nint16_8)( |
851 | CppTypeFor<TypeCategory::Real, 16> x) { |
852 | return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x); |
853 | } |
854 | #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T |
855 | CppTypeFor<TypeCategory::Integer, 16> RTDEF(Nint16_16)( |
856 | CppTypeFor<TypeCategory::Real, 16> x) { |
857 | return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x); |
858 | } |
859 | #endif |
860 | #endif |
861 | |
862 | CppTypeFor<TypeCategory::Real, 4> RTDEF(RRSpacing4)( |
863 | CppTypeFor<TypeCategory::Real, 4> x) { |
864 | return RRSpacing<24>(x); |
865 | } |
866 | CppTypeFor<TypeCategory::Real, 8> RTDEF(RRSpacing8)( |
867 | CppTypeFor<TypeCategory::Real, 8> x) { |
868 | return RRSpacing<53>(x); |
869 | } |
870 | #if LDBL_MANT_DIG == 64 |
871 | CppTypeFor<TypeCategory::Real, 10> RTDEF(RRSpacing10)( |
872 | CppTypeFor<TypeCategory::Real, 10> x) { |
873 | return RRSpacing<64>(x); |
874 | } |
875 | #elif LDBL_MANT_DIG == 113 |
876 | CppTypeFor<TypeCategory::Real, 16> RTDEF(RRSpacing16)( |
877 | CppTypeFor<TypeCategory::Real, 16> x) { |
878 | return RRSpacing<113>(x); |
879 | } |
880 | #endif |
881 | |
882 | CppTypeFor<TypeCategory::Real, 4> RTDEF(SetExponent4)( |
883 | CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) { |
884 | return SetExponent(x, p); |
885 | } |
886 | CppTypeFor<TypeCategory::Real, 8> RTDEF(SetExponent8)( |
887 | CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) { |
888 | return SetExponent(x, p); |
889 | } |
890 | #if LDBL_MANT_DIG == 64 |
891 | CppTypeFor<TypeCategory::Real, 10> RTDEF(SetExponent10)( |
892 | CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) { |
893 | return SetExponent(x, p); |
894 | } |
895 | #elif LDBL_MANT_DIG == 113 |
896 | CppTypeFor<TypeCategory::Real, 16> RTDEF(SetExponent16)( |
897 | CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) { |
898 | return SetExponent(x, p); |
899 | } |
900 | #endif |
901 | |
902 | CppTypeFor<TypeCategory::Real, 4> RTDEF(Scale4)( |
903 | CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) { |
904 | return Scale(x, p); |
905 | } |
906 | CppTypeFor<TypeCategory::Real, 8> RTDEF(Scale8)( |
907 | CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) { |
908 | return Scale(x, p); |
909 | } |
910 | #if LDBL_MANT_DIG == 64 |
911 | CppTypeFor<TypeCategory::Real, 10> RTDEF(Scale10)( |
912 | CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) { |
913 | return Scale(x, p); |
914 | } |
915 | #elif LDBL_MANT_DIG == 113 |
916 | CppTypeFor<TypeCategory::Real, 16> RTDEF(Scale16)( |
917 | CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) { |
918 | return Scale(x, p); |
919 | } |
920 | #endif |
921 | |
922 | // SELECTED_INT_KIND |
923 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(SelectedIntKind)( |
924 | const char *source, int line, void *x, int xKind) { |
925 | #ifdef __SIZEOF_INT128__ |
926 | CppTypeFor<TypeCategory::Integer, 16> r = |
927 | getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>( |
928 | source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 16); |
929 | #else |
930 | std::int64_t r = getIntArgValue<std::int64_t>( |
931 | source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 8); |
932 | #endif |
933 | return SelectedIntKind(r); |
934 | } |
935 | |
936 | // SELECTED_REAL_KIND |
937 | CppTypeFor<TypeCategory::Integer, 4> RTDEF(SelectedRealKind)(const char *source, |
938 | int line, void *precision, int pKind, void *range, int rKind, void *radix, |
939 | int dKind) { |
940 | #ifdef __SIZEOF_INT128__ |
941 | CppTypeFor<TypeCategory::Integer, 16> p = |
942 | getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>( |
943 | source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 16); |
944 | CppTypeFor<TypeCategory::Integer, 16> r = |
945 | getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>( |
946 | source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 16); |
947 | CppTypeFor<TypeCategory::Integer, 16> d = |
948 | getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>( |
949 | source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 16); |
950 | #else |
951 | std::int64_t p = getIntArgValue<std::int64_t>( |
952 | source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 8); |
953 | std::int64_t r = getIntArgValue<std::int64_t>( |
954 | source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 8); |
955 | std::int64_t d = getIntArgValue<std::int64_t>( |
956 | source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 8); |
957 | #endif |
958 | return SelectedRealKind(p, r, d); |
959 | } |
960 | |
961 | CppTypeFor<TypeCategory::Real, 4> RTDEF(Spacing4)( |
962 | CppTypeFor<TypeCategory::Real, 4> x) { |
963 | return Spacing<24>(x); |
964 | } |
965 | CppTypeFor<TypeCategory::Real, 8> RTDEF(Spacing8)( |
966 | CppTypeFor<TypeCategory::Real, 8> x) { |
967 | return Spacing<53>(x); |
968 | } |
969 | #if LDBL_MANT_DIG == 64 |
970 | CppTypeFor<TypeCategory::Real, 10> RTDEF(Spacing10)( |
971 | CppTypeFor<TypeCategory::Real, 10> x) { |
972 | return Spacing<64>(x); |
973 | } |
974 | #elif LDBL_MANT_DIG == 113 |
975 | CppTypeFor<TypeCategory::Real, 16> RTDEF(Spacing16)( |
976 | CppTypeFor<TypeCategory::Real, 16> x) { |
977 | return Spacing<113>(x); |
978 | } |
979 | #endif |
980 | |
981 | CppTypeFor<TypeCategory::Real, 4> RTDEF(FPow4i)( |
982 | CppTypeFor<TypeCategory::Real, 4> b, |
983 | CppTypeFor<TypeCategory::Integer, 4> e) { |
984 | return FPowI(b, e); |
985 | } |
986 | CppTypeFor<TypeCategory::Real, 8> RTDEF(FPow8i)( |
987 | CppTypeFor<TypeCategory::Real, 8> b, |
988 | CppTypeFor<TypeCategory::Integer, 4> e) { |
989 | return FPowI(b, e); |
990 | } |
991 | #if LDBL_MANT_DIG == 64 |
992 | CppTypeFor<TypeCategory::Real, 10> RTDEF(FPow10i)( |
993 | CppTypeFor<TypeCategory::Real, 10> b, |
994 | CppTypeFor<TypeCategory::Integer, 4> e) { |
995 | return FPowI(b, e); |
996 | } |
997 | #endif |
998 | #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 |
999 | CppTypeFor<TypeCategory::Real, 16> RTDEF(FPow16i)( |
1000 | CppTypeFor<TypeCategory::Real, 16> b, |
1001 | CppTypeFor<TypeCategory::Integer, 4> e) { |
1002 | return FPowI(b, e); |
1003 | } |
1004 | #endif |
1005 | |
1006 | CppTypeFor<TypeCategory::Real, 4> RTDEF(FPow4k)( |
1007 | CppTypeFor<TypeCategory::Real, 4> b, |
1008 | CppTypeFor<TypeCategory::Integer, 8> e) { |
1009 | return FPowI(b, e); |
1010 | } |
1011 | CppTypeFor<TypeCategory::Real, 8> RTDEF(FPow8k)( |
1012 | CppTypeFor<TypeCategory::Real, 8> b, |
1013 | CppTypeFor<TypeCategory::Integer, 8> e) { |
1014 | return FPowI(b, e); |
1015 | } |
1016 | #if LDBL_MANT_DIG == 64 |
1017 | CppTypeFor<TypeCategory::Real, 10> RTDEF(FPow10k)( |
1018 | CppTypeFor<TypeCategory::Real, 10> b, |
1019 | CppTypeFor<TypeCategory::Integer, 8> e) { |
1020 | return FPowI(b, e); |
1021 | } |
1022 | #endif |
1023 | #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 |
1024 | CppTypeFor<TypeCategory::Real, 16> RTDEF(FPow16k)( |
1025 | CppTypeFor<TypeCategory::Real, 16> b, |
1026 | CppTypeFor<TypeCategory::Integer, 8> e) { |
1027 | return FPowI(b, e); |
1028 | } |
1029 | #endif |
1030 | |
1031 | RT_EXT_API_GROUP_END |
1032 | } // extern "C" |
1033 | } // namespace Fortran::runtime |
1034 | |