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