1+ #if !(NET5_0_OR_GREATER)
2+
3+ using System.Runtime.CompilerServices;
4+
5+ namespace System;
6+
7+
8+ // C# 14 static extension members on the *type* itself.
9+ // Usage on old TFMs: Double.IsFinite(x), Double.IsIntegral(x), Single.IsFinite(x), ...
10+ static class FloatCompat
11+ {
12+ // ---- Double ----
13+ extension(double)
14+ {
15+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
16+ public static bool IsFinite(double x)
17+ {
18+ var bits = (ulong)BitConverter.DoubleToInt64Bits(x);
19+ return (bits & 0x7FF0_0000_0000_0000UL) != 0x7FF0_0000_0000_0000UL;
20+ }
21+
22+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
23+ public static bool IsIntegral(double x)
24+ {
25+ if (!IsFinite(x)) return false;
26+ return x == Math.Truncate(x);
27+ }
28+
29+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
30+ public static bool IsInfinityFast(double x)
31+ {
32+ var bits = (ulong)BitConverter.DoubleToInt64Bits(x);
33+ return (bits & 0x7FFF_FFFF_FFFF_FFFFUL) == 0x7FF0_0000_0000_0000UL;
34+ }
35+
36+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
37+ public static bool IsNaNFast(double x)
38+ {
39+ var bits = (ulong)BitConverter.DoubleToInt64Bits(x);
40+ return (bits & 0x7FF0_0000_0000_0000UL) == 0x7FF0_0000_0000_0000UL
41+ && (bits & 0x000F_FFFF_FFFF_FFFFUL) != 0;
42+ }
43+
44+
45+ }
46+
47+ // ---- float ----
48+ extension(float)
49+ {
50+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
51+ public static bool IsFinite(float x)
52+ {
53+ // netstandard2.0 / net48: fastest is unsafe bit-cast
54+ unsafe { var bits = *(uint*)&x; return (bits & 0x7F80_0000u) != 0x7F80_0000u; }
55+ }
56+
57+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
58+ public static bool IsIntegral(float x)
59+ {
60+ if (!IsFinite(x)) return false;
61+ return x == Math.Truncate(x);
62+ }
63+
64+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
65+ public static bool IsInfinityFast(float x)
66+ {
67+ unsafe { var bits = *(uint*)&x; return (bits & 0x7FFF_FFFFu) == 0x7F80_0000u; }
68+ }
69+
70+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
71+ public static bool IsNaNFast(float x)
72+ {
73+ unsafe
74+ {
75+ var bits = *(uint*)&x;
76+ var isExpAllOnes = (bits & 0x7F80_0000u) == 0x7F80_0000u;
77+ var hasMantissa = (bits & 0x007F_FFFFu) != 0;
78+ return isExpAllOnes && hasMantissa;
79+ }
80+ }
81+ }
82+ }
83+ #endif
0 commit comments