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