some updates
[iv.d.git] / nanpay.d
blob08782d6426ef5593c373a74d11efcda4973a1775
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
26 special exponents:
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)
42 special exponents:
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.
52 // doubles
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
59 // floats
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 {
70 pragma(inline, true);
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 {
77 pragma(inline, true);
78 return (((*cast(const(uint)*)&v)&0x7f80_0000U) != 0x7f80_0000U);
82 /// is `v` nan?
83 bool isNan (in double v) pure nothrow @trusted @nogc {
84 pragma(inline, true);
85 return (((*cast(const(ulong)*)&v)<<1) > 0xffe0_0000_0000_0000UL);
89 /// is `v` nan?
90 bool isNanF (in float v) pure nothrow @trusted @nogc {
91 pragma(inline, true);
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 {
98 pragma(inline, true);
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
126 // create double
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.
141 * Returns:
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);
155 return pay;
160 * Extract an integral payload from a NaN.
162 * Returns:
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);
177 return pay;
178 } else {
179 return def;
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
200 // create double
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.
215 * Returns:
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.
232 * Returns:
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);
253 } else {
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
275 // create float
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.
290 * Returns:
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);
304 return pay;
309 * Extract an integral payload from a NaN.
311 * Returns:
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);
326 return pay;
327 } else {
328 return def;
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
349 // create float
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.
364 * Returns:
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.
381 * Returns:
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);
402 } else {
403 static assert(0, "unimplemented arch");