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