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*/;
19 IEEE 754 32-bit binary float format:
20 bits 0..22: mantissa (fractional part, without implied 1, unless the exponent is zero) (23 bits)
21 bits 23..30: exponent (biased, to get the real signed exponent, subtract 127) (8 bits)
22 bit 31: sign (1 means negative)
24 mask for mantissa: 0x7fffffu
27 0: zero or denormal (zero if mantissa is zero, otherwise denormal)
28 255: nan or infinity (infinity if mantissa is zero, otherwise nan)
30 signaling nan has bit 22 reset (NOT set!). i.e. it is "is quiet" flag.
32 denormals has exponent of -126, and the implied first binary digit is 0.
33 fun fact: this way, zero is just a kind of denormal.
37 IEEE 754 64-bit binary float format:
38 bits 0..51: mantissa (fractional part, without implied 1, unless the exponent is zero) (52 bits)
39 bits 52..62: exponent (biased, to get the real signed exponent, subtract 1023) (11 bits)
40 bit 63: sign (1 means negative)
43 0: zero or denormal (zero if mantissa is zero, otherwise denormal)
44 0x7ff (2047): nan or infinity (infinity if mantissa is zero, otherwise nan)
46 signaling nan has bit 51 reset (NOT set!). i.e. it is "is quiet" flag.
48 denormals has exponent of -1022, and the implied first binary digit is 0.
49 fun fact: this way, zero is just a kind of denormal.
53 enum MinSignedNanPay
= -0x7_ffff_ffff_ffffL
; // 51 bits
54 enum MaxSignedNanPay
= +0x7_ffff_ffff_ffffL
; // 51 bits
56 enum MinUnsignedNanPay
= 0UL;
57 enum MaxUnsignedNanPay
= 0x7_ffff_ffff_ffffUL
; // 51 bits
60 enum MinSignedNanPayF
= -0x3f_ffff
; // 22 bits
61 enum MaxSignedNanPayF
= +0x3f_ffff
; // 22 bits
63 enum MinUnsignedNanPayF
= 0U;
64 enum MaxUnsignedNanPayF
= 0x3f_ffffU
; // 22 bits
67 // ////////////////////////////////////////////////////////////////////////// //
68 /// is `v` finite (i.e. not a nan and not an infinity)?
69 bool isFinite (in double v
) pure nothrow @trusted @nogc {
71 return (((*cast(const(ulong)*)&v
)&0x7ff0_0000_0000_0000UL) != 0x7ff0_0000_0000_0000UL);
75 /// is `v` finite (i.e. not a nan and not an infinity)?
76 bool isFiniteF (in float v
) pure nothrow @trusted @nogc {
78 return (((*cast(const(uint)*)&v
)&0x7f80_0000U) != 0x7f80_0000U);
83 bool isNan (in double v
) pure nothrow @trusted @nogc {
85 return (((*cast(const(ulong)*)&v
)<<1) > 0xffe0_0000_0000_0000UL);
90 bool isNanF (in float v
) pure nothrow @trusted @nogc {
92 return (((*cast(const(uint)*)&v
)<<1) > 0xff_00_00_00U);
96 /// is `v` represents infinity (not nan)?
97 bool isInfinity (in double v
) pure nothrow @trusted @nogc {
99 return (((*cast(const(ulong)*)&v
)<<1) == 0xffe0_0000_0000_0000UL);
103 /// is `v` represents infinity (not nan)?
104 bool isInfinityF (in float v
) pure nothrow @trusted @nogc {
105 pragma(inline
, true);
106 return (((*cast(const(uint)*)&v
)<<1) == 0xff_00_00_00U);
110 // ////////////////////////////////////////////////////////////////////////// //
112 * Create a NaN, storing an integer inside the payload.
114 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
115 * One bit is reserved to not turn nans into infinity.
116 * But sign bit can be used to store sign, which allows to store signed values.
117 * IDC about quiet and signaling nans: check your numbers!
119 double makeNanPay(bool doChecking
=false) (long pay
) pure nothrow @trusted @nogc {
120 pragma(inline
, true);
121 static if (doChecking
) {
122 if (pay
< MinSignedNanPay || pay
> MaxSignedNanPay
) assert(0, "invalid payload");
124 pay
&= 0x8007_ffff_ffff_ffffUL
; // left only bits we are interested in
125 pay |
= 0x7ff8_0000_0000_0000UL; // set highest mantissa bit to ensure nan, and exponent to nan/inf
127 return *cast(double*)&pay
;
131 /// (rough) check if the given double contains "good nan" with payload.
132 bool hasNanPay (in double v
) pure nothrow @trusted @nogc {
133 pragma(inline
, true);
134 return (((*cast(const(ulong)*)&v
)&0x7ff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL);
139 * Extract an integral payload from a NaN.
142 * the integer payload as a long.
144 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
145 * One bit is reserved to not turn nans into infinity.
146 * But sign bit can be used to store sign, which allows to store signed values.
147 * Check if your number is "good nan" before extracting!
149 long getNanPay (in double v
) pure nothrow @trusted @nogc {
150 pragma(inline
, true);
151 long pay
= (*cast(const(long)*)&v
)&0x8007_ffff_ffff_ffffUL
; // remove exponent
152 // this bitors the missing "1" bits for negative numbers
153 // shift either by 16 (effectively removing the mask) or by 0
154 pay |
= 0xfff8_0000_0000_0000UL<<(((pay
>>59)&0x10)^
0x10);
160 * Extract an integral payload from a NaN.
163 * the integer payload as a long or default value if NaN has no payload.
165 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
166 * One bit is reserved to not turn nans into infinity.
167 * But sign bit can be used to store sign, which allows to store signed values.
168 * Check if your number is "good nan" before extracting!
170 long getNanPayDef (in double v
, long def
) pure nothrow @trusted @nogc {
171 pragma(inline
, true);
172 if (((*cast(const(ulong)*)&v
)&0x7ff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL) {
173 long pay
= (*cast(const(long)*)&v
)&0x8007_ffff_ffff_ffffUL
; // remove exponent
174 // this bitors the missing "1" bits for negative numbers
175 // shift either by 16 (effectively removing the mask) or by 0
176 pay |
= 0xfff8_0000_0000_0000UL<<(((pay
>>59)&0x10)^
0x10);
184 // ////////////////////////////////////////////////////////////////////////// //
186 * Create a NaN, storing an integer inside the payload.
188 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
189 * One bit is reserved to not turn nans into infinity.
190 * Sign bit is unused, and should be zero.
191 * IDC about quiet and signaling nans: check your numbers!
193 double makeNanPayU(bool doChecking
=false) (ulong pay
) pure nothrow @trusted @nogc {
194 pragma(inline
, true);
195 static if (doChecking
) {
196 if (pay
> MaxUnsignedNanPay
) assert(0, "invalid payload");
198 pay
&= 0x0007_ffff_ffff_ffffUL
; // left only bits we are interested in
199 pay |
= 0x7ff8_0000_0000_0000UL; // set highest mantissa bit to ensure nan, and exponent to nan/inf
201 return *cast(double*)&pay
;
205 /// (rough) check if the given double contains "good nan" with payload. sign bit should not be set.
206 bool hasNanPayU (in double v
) pure nothrow @trusted @nogc {
207 pragma(inline
, true);
208 return (((*cast(const(ulong)*)&v
)&0xfff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL);
213 * Extract an integral payload from a NaN.
216 * the integer payload as a long or default value if NaN has no payload.
218 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
219 * One bit is reserved to not turn nans into infinity.
220 * Sign bit is unused, and should be zero.
221 * Check if your number is "good nan" before extracting!
223 ulong getNanPayU (in double v
) pure nothrow @trusted @nogc {
224 pragma(inline
, true);
225 return (*cast(const(ulong)*)&v
)&0x0007_ffff_ffff_ffffUL
; // remove exponent
230 * Extract an integral payload from a NaN.
233 * the integer payload as a long or default value if NaN has no payload.
235 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
236 * One bit is reserved to not turn nans into infinity.
237 * Sign bit is unused, and should be zero.
238 * Check if your number is "good nan" before extracting!
240 ulong getNanPayUDef (in double v
, ulong def
) pure nothrow @trusted @nogc {
241 pragma(inline
, true);
242 return (((*cast(const(ulong)*)&v
)&0xfff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL ?
243 (*cast(const(ulong)*)&v
)&0x0007_ffff_ffff_ffffUL
: def
);
247 // ////////////////////////////////////////////////////////////////////////// //
248 // return 0, something <0, or something >0
249 int getDoubleXSign (in double v
) pure nothrow @trusted @nogc {
250 pragma(inline
, true);
251 version(LittleEndian
) {
252 return ((*cast(const(ulong)*)&v
)&(0x7fff_ffff_ffff_ffffUL
) ?
*((cast(const(int)*)&v
)+1) : 0);
254 static assert(0, "unimplemented arch");
259 // ////////////////////////////////////////////////////////////////////////// //
261 * Create a NaN, storing an integer inside the payload.
263 * The largest possible payload is 0x3f_ffff (22 bits).
264 * One bit is reserved to not turn nans into infinity.
265 * But sign bit can be used to store sign, which allows to store signed values.
266 * IDC about quiet and signaling nans: check your numbers!
268 float makeNanPayF(bool doChecking
=false) (int pay
) pure nothrow @trusted @nogc {
269 pragma(inline
, true);
270 static if (doChecking
) {
271 if (pay
< MinSignedNanPayF || pay
> MaxSignedNanPayF
) assert(0, "invalid payload");
273 pay
&= 0x803f_ffffU
; // left only bits we are interested in
274 pay |
= 0x7fc0_0000U; // set highest mantissa bit to ensure nan, and exponent to nan/inf
276 return *cast(float*)&pay
;
280 /// (rough) check if the given float contains "good nan" with payload.
281 bool hasNanPayF (in float v
) pure nothrow @trusted @nogc {
282 pragma(inline
, true);
283 return (((*cast(const(uint)*)&v
)&0x7fc0_0000U) == 0x7fc0_0000U);
288 * Extract an integral payload from a NaN.
291 * the integer payload as a int.
293 * The largest possible payload is 0x3f_ffff (22 bits).
294 * One bit is reserved to not turn nans into infinity.
295 * But sign bit can be used to store sign, which allows to store signed values.
296 * Check if your number is "good nan" before extracting!
298 int getNanPayF (in float v
) pure nothrow @trusted @nogc {
299 pragma(inline
, true);
300 int pay
= (*cast(const(int)*)&v
)&0x803f_ffffU
; // remove exponent
301 // this bitors the missing "1" bits for negative numbers
302 // shift either by 8 (effectively removing the mask) or by 0
303 pay |
= 0xfc00_0000U<<(((pay
>>28)&0x08)^
0x08);
309 * Extract an integral payload from a NaN.
312 * the integer payload as a int or default value if NaN has no payload.
314 * The largest possible payload is 0x3f_ffff (22 bits).
315 * One bit is reserved to not turn nans into infinity.
316 * But sign bit can be used to store sign, which allows to store signed values.
317 * Check if your number is "good nan" before extracting!
319 int getNanPayFDef (in float v
, int def
) pure nothrow @trusted @nogc {
320 pragma(inline
, true);
321 if (((*cast(const(uint)*)&v
)&0x7fc0_0000U) == 0x7fc0_0000U) {
322 int pay
= (*cast(const(int)*)&v
)&0x803f_ffffU
; // remove exponent
323 // this bitors the missing "1" bits for negative numbers
324 // shift either by 8 (effectively removing the mask) or by 0
325 pay |
= 0xfc00_0000U<<(((pay
>>28)&0x08)^
0x08);
333 // ////////////////////////////////////////////////////////////////////////// //
335 * Create a NaN, storing an integer inside the payload.
337 * The largest possible payload is 0x3f_ffff (22 bits).
338 * One bit is reserved to not turn nans into infinity.
339 * Sign bit is unused, and should be zero.
340 * IDC about quiet and signaling nans: check your numbers!
342 float makeNanPayUF(bool doChecking
=false) (uint pay
) pure nothrow @trusted @nogc {
343 pragma(inline
, true);
344 static if (doChecking
) {
345 if (pay
> MaxUnsignedNanPayF
) assert(0, "invalid payload");
347 pay
&= 0x003f_ffffU
; // left only bits we are interested in
348 pay |
= 0x7fc0_0000U; // set highest mantissa bit to ensure nan, and exponent to nan/inf
350 return *cast(float*)&pay
;
354 /// (rough) check if the given float contains "good nan" with payload. sign bit should not be set.
355 bool hasNanPayUF (in float v
) pure nothrow @trusted @nogc {
356 pragma(inline
, true);
357 return (((*cast(const(uint)*)&v
)&0xffc0_0000U) == 0x7fc0_0000U);
362 * Extract an integral payload from a NaN.
365 * the integer payload as a uint.
367 * The largest possible payload is 0x3f_ffff (22 bits).
368 * One bit is reserved to not turn nans into infinity.
369 * Sign bit is unused, and should be zero.
370 * Check if your number is "good nan" before extracting!
372 uint getNanPayUF (in float v
) pure nothrow @trusted @nogc {
373 pragma(inline
, true);
374 return (*cast(const(uint)*)&v
)&0x003f_ffffU
; // remove exponent
379 * Extract an integral payload from a NaN.
382 * the integer payload as a uint or default value if NaN has no payload.
384 * The largest possible payload is 0x3f_ffff (22 bits).
385 * One bit is reserved to not turn nans into infinity.
386 * Sign bit is unused, and should be zero.
387 * Check if your number is "good nan" before extracting!
389 uint getNanPayUFDef (in float v
, uint def
) pure nothrow @trusted @nogc {
390 pragma(inline
, true);
391 return (((*cast(const(uint)*)&v
)&0xffc0_0000U) == 0x7fc0_0000U ?
392 (*cast(const(uint)*)&v
)&0x003f_ffffU
: def
);
396 // ////////////////////////////////////////////////////////////////////////// //
397 // return 0, something <0, or something >0
398 int getFloatXSign (in float v
) pure nothrow @trusted @nogc {
399 pragma(inline
, true);
400 version(LittleEndian
) {
401 return ((*cast(const(uint)*)&v
)&0x7fff_ffffU ?
*(cast(const(int)*)&v
) : 0);
403 static assert(0, "unimplemented arch");