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