1 /* coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License ONLY.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 module iv
.nanpay
/*is aliced*/;
20 enum MinSignedNanPay
= -0x7_ffff_ffff_ffffL
; // 51 bits
21 enum MaxSignedNanPay
= +0x7_ffff_ffff_ffffL
; // 51 bits
23 enum MinUnsignedNanPay
= 0UL;
24 enum MaxUnsignedNanPay
= 0x7_ffff_ffff_ffffUL
; // 51 bits
27 enum MinSignedNanPayF
= -0x3f_ffff
; // 22 bits
28 enum MaxSignedNanPayF
= +0x3f_ffff
; // 22 bits
30 enum MinUnsignedNanPayF
= 0U;
31 enum MaxUnsignedNanPayF
= 0x3f_ffffU
; // 22 bits
34 // ////////////////////////////////////////////////////////////////////////// //
35 /// is `v` finite (i.e. not a nan and not an infinity)?
36 bool isFinite (in double v
) pure nothrow @trusted @nogc {
38 return (((*cast(const(ulong)*)&v
)&0x7ff0_0000_0000_0000UL) != 0x7ff0_0000_0000_0000UL);
42 /// is `v` finite (i.e. not a nan and not an infinity)?
43 bool isFiniteF (in float v
) pure nothrow @trusted @nogc {
45 return (((*cast(const(uint)*)&v
)&0x7f80_0000U) != 0x7f80_0000U);
49 // ////////////////////////////////////////////////////////////////////////// //
51 * Create a NaN, storing an integer inside the payload.
53 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
54 * One bit is reserved to not turn nans into infinity.
55 * But sign bit can be used to store sign, which allows to store signed values.
56 * IDC about quiet and signaling nans: check your numbers!
58 double makeNanPay(bool doChecking
=false) (long pay
) pure nothrow @trusted @nogc {
60 static if (doChecking
) {
61 if (pay
< MinSignedNanPay || pay
> MaxSignedNanPay
) assert(0, "invalid payload");
63 pay
&= 0x8007_ffff_ffff_ffffUL
; // left only bits we are interested in
64 pay |
= 0x7ff8_0000_0000_0000UL; // set highest mantissa bit to ensure nan, and exponent to nan/inf
66 return *cast(double*)&pay
;
70 /// (rough) check if the given double contains "good nan" with payload.
71 bool hasNanPay (in double v
) pure nothrow @trusted @nogc {
73 return (((*cast(const(ulong)*)&v
)&0x7ff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL);
78 * Extract an integral payload from a NaN.
81 * the integer payload as a long.
83 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
84 * One bit is reserved to not turn nans into infinity.
85 * But sign bit can be used to store sign, which allows to store signed values.
86 * Check if your number is "good nan" before extracting!
88 long getNanPay (in double v
) pure nothrow @trusted @nogc {
90 long pay
= (*cast(const(long)*)&v
)&0x8007_ffff_ffff_ffffUL
; // remove exponent
91 // this bitors the missing "1" bits for negative numbers
92 // shift either by 16 (effectively removing the mask) or by 0
93 pay |
= 0xfff8_0000_0000_0000UL<<(((pay
>>59)&0x10)^
0x10);
99 * Extract an integral payload from a NaN.
102 * the integer payload as a long or default value if NaN has no payload.
104 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
105 * One bit is reserved to not turn nans into infinity.
106 * But sign bit can be used to store sign, which allows to store signed values.
107 * Check if your number is "good nan" before extracting!
109 long getNanPayDef (in double v
, long def
) pure nothrow @trusted @nogc {
110 pragma(inline
, true);
111 if (((*cast(const(ulong)*)&v
)&0x7ff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL) {
112 long pay
= (*cast(const(long)*)&v
)&0x8007_ffff_ffff_ffffUL
; // remove exponent
113 // this bitors the missing "1" bits for negative numbers
114 // shift either by 16 (effectively removing the mask) or by 0
115 pay |
= 0xfff8_0000_0000_0000UL<<(((pay
>>59)&0x10)^
0x10);
123 // ////////////////////////////////////////////////////////////////////////// //
125 * Create a NaN, storing an integer inside the payload.
127 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
128 * One bit is reserved to not turn nans into infinity.
129 * Sign bit is unused, and should be zero.
130 * IDC about quiet and signaling nans: check your numbers!
132 double makeNanPayU(bool doChecking
=false) (ulong pay
) pure nothrow @trusted @nogc {
133 pragma(inline
, true);
134 static if (doChecking
) {
135 if (pay
> MaxUnsignedNanPay
) assert(0, "invalid payload");
137 pay
&= 0x0007_ffff_ffff_ffffUL
; // left only bits we are interested in
138 pay |
= 0x7ff8_0000_0000_0000UL; // set highest mantissa bit to ensure nan, and exponent to nan/inf
140 return *cast(double*)&pay
;
144 /// (rough) check if the given double contains "good nan" with payload. sign bit should not be set.
145 bool hasNanPayU (in double v
) pure nothrow @trusted @nogc {
146 pragma(inline
, true);
147 return (((*cast(const(ulong)*)&v
)&0xfff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL);
152 * Extract an integral payload from a NaN.
155 * the integer payload as a long or default value if NaN has no payload.
157 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
158 * One bit is reserved to not turn nans into infinity.
159 * Sign bit is unused, and should be zero.
160 * Check if your number is "good nan" before extracting!
162 ulong getNanPayU (in double v
) pure nothrow @trusted @nogc {
163 pragma(inline
, true);
164 return (*cast(const(ulong)*)&v
)&0x0007_ffff_ffff_ffffUL
; // remove exponent
169 * Extract an integral payload from a NaN.
172 * the integer payload as a long or default value if NaN has no payload.
174 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
175 * One bit is reserved to not turn nans into infinity.
176 * Sign bit is unused, and should be zero.
177 * Check if your number is "good nan" before extracting!
179 ulong getNanPayUDef (in double v
, ulong def
) pure nothrow @trusted @nogc {
180 pragma(inline
, true);
181 return (((*cast(const(ulong)*)&v
)&0xfff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL ?
182 (*cast(const(ulong)*)&v
)&0x0007_ffff_ffff_ffffUL
: def
);
186 // ////////////////////////////////////////////////////////////////////////// //
187 // return 0, something <0, or something >0
188 int getDoubleXSign (in double v
) pure nothrow @trusted @nogc {
189 pragma(inline
, true);
190 version(LittleEndian
) {
191 return ((*cast(const(ulong)*)&v
)&(0x7fff_ffff_ffff_ffffUL
) ?
*((cast(const(int)*)&v
)+1) : 0);
193 static assert(0, "unimplemented arch");
198 // ////////////////////////////////////////////////////////////////////////// //
200 * Create a NaN, storing an integer inside the payload.
202 * The largest possible payload is 0x3f_ffff (22 bits).
203 * One bit is reserved to not turn nans into infinity.
204 * But sign bit can be used to store sign, which allows to store signed values.
205 * IDC about quiet and signaling nans: check your numbers!
207 float makeNanPayF(bool doChecking
=false) (int pay
) pure nothrow @trusted @nogc {
208 pragma(inline
, true);
209 static if (doChecking
) {
210 if (pay
< MinSignedNanPayF || pay
> MaxSignedNanPayF
) assert(0, "invalid payload");
212 pay
&= 0x803f_ffffU
; // left only bits we are interested in
213 pay |
= 0x7fc0_0000U; // set highest mantissa bit to ensure nan, and exponent to nan/inf
215 return *cast(float*)&pay
;
219 /// (rough) check if the given float contains "good nan" with payload.
220 bool hasNanPayF (in float v
) pure nothrow @trusted @nogc {
221 pragma(inline
, true);
222 return (((*cast(const(uint)*)&v
)&0x7fc0_0000U) == 0x7fc0_0000U);
227 * Extract an integral payload from a NaN.
230 * the integer payload as a int.
232 * The largest possible payload is 0x3f_ffff (22 bits).
233 * One bit is reserved to not turn nans into infinity.
234 * But sign bit can be used to store sign, which allows to store signed values.
235 * Check if your number is "good nan" before extracting!
237 int getNanPayF (in float v
) pure nothrow @trusted @nogc {
238 pragma(inline
, true);
239 int pay
= (*cast(const(int)*)&v
)&0x803f_ffffU
; // remove exponent
240 // this bitors the missing "1" bits for negative numbers
241 // shift either by 8 (effectively removing the mask) or by 0
242 pay |
= 0xfc00_0000U<<(((pay
>>28)&0x08)^
0x08);
248 * Extract an integral payload from a NaN.
251 * the integer payload as a int or default value if NaN has no payload.
253 * The largest possible payload is 0x3f_ffff (22 bits).
254 * One bit is reserved to not turn nans into infinity.
255 * But sign bit can be used to store sign, which allows to store signed values.
256 * Check if your number is "good nan" before extracting!
258 int getNanPayFDef (in float v
, int def
) pure nothrow @trusted @nogc {
259 pragma(inline
, true);
260 if (((*cast(const(uint)*)&v
)&0x7fc0_0000U) == 0x7fc0_0000U) {
261 int pay
= (*cast(const(int)*)&v
)&0x803f_ffffU
; // remove exponent
262 // this bitors the missing "1" bits for negative numbers
263 // shift either by 8 (effectively removing the mask) or by 0
264 pay |
= 0xfc00_0000U<<(((pay
>>28)&0x08)^
0x08);
272 // ////////////////////////////////////////////////////////////////////////// //
274 * Create a NaN, storing an integer inside the payload.
276 * The largest possible payload is 0x3f_ffff (22 bits).
277 * One bit is reserved to not turn nans into infinity.
278 * Sign bit is unused, and should be zero.
279 * IDC about quiet and signaling nans: check your numbers!
281 float makeNanPayUF(bool doChecking
=false) (uint pay
) pure nothrow @trusted @nogc {
282 pragma(inline
, true);
283 static if (doChecking
) {
284 if (pay
> MaxUnsignedNanPayF
) assert(0, "invalid payload");
286 pay
&= 0x003f_ffffU
; // left only bits we are interested in
287 pay |
= 0x7fc0_0000U; // set highest mantissa bit to ensure nan, and exponent to nan/inf
289 return *cast(float*)&pay
;
293 /// (rough) check if the given float contains "good nan" with payload. sign bit should not be set.
294 bool hasNanPayUF (in float v
) pure nothrow @trusted @nogc {
295 pragma(inline
, true);
296 return (((*cast(const(uint)*)&v
)&0xffc0_0000U) == 0x7fc0_0000U);
301 * Extract an integral payload from a NaN.
304 * the integer payload as a uint.
306 * The largest possible payload is 0x3f_ffff (22 bits).
307 * One bit is reserved to not turn nans into infinity.
308 * Sign bit is unused, and should be zero.
309 * Check if your number is "good nan" before extracting!
311 uint getNanPayUF (in float v
) pure nothrow @trusted @nogc {
312 pragma(inline
, true);
313 return (*cast(const(uint)*)&v
)&0x003f_ffffU
; // remove exponent
318 * Extract an integral payload from a NaN.
321 * the integer payload as a uint or default value if NaN has no payload.
323 * The largest possible payload is 0x3f_ffff (22 bits).
324 * One bit is reserved to not turn nans into infinity.
325 * Sign bit is unused, and should be zero.
326 * Check if your number is "good nan" before extracting!
328 uint getNanPayUFDef (in float v
, uint def
) pure nothrow @trusted @nogc {
329 pragma(inline
, true);
330 return (((*cast(const(uint)*)&v
)&0xffc0_0000U) == 0x7fc0_0000U ?
331 (*cast(const(uint)*)&v
)&0x003f_ffffU
: def
);
335 // ////////////////////////////////////////////////////////////////////////// //
336 // return 0, something <0, or something >0
337 int getFloatXSign (in float v
) pure nothrow @trusted @nogc {
338 pragma(inline
, true);
339 version(LittleEndian
) {
340 return ((*cast(const(uint)*)&v
)&0x7fff_ffffU ?
*(cast(const(int)*)&v
) : 0);
342 static assert(0, "unimplemented arch");