egra: more strict checks before applying asm optimisations
[iv.d.git] / nanpay.d
blobbe1df8dc9bb4798a3a9f2a5f32a4d89a1e3b5cf1
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 // doubles
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
26 // floats
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 {
37 pragma(inline, true);
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 {
44 pragma(inline, true);
45 return (((*cast(const(uint)*)&v)&0x7f80_0000U) != 0x7f80_0000U);
49 // ////////////////////////////////////////////////////////////////////////// //
50 /**
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 {
59 pragma(inline, true);
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
65 // create double
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 {
72 pragma(inline, true);
73 return (((*cast(const(ulong)*)&v)&0x7ff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL);
77 /**
78 * Extract an integral payload from a NaN.
80 * Returns:
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 {
89 pragma(inline, true);
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);
94 return pay;
98 /**
99 * Extract an integral payload from a NaN.
101 * Returns:
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);
116 return pay;
117 } else {
118 return def;
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
139 // create double
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.
154 * Returns:
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.
171 * Returns:
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);
192 } else {
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
214 // create float
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.
229 * Returns:
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);
243 return pay;
248 * Extract an integral payload from a NaN.
250 * Returns:
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);
265 return pay;
266 } else {
267 return def;
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
288 // create float
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.
303 * Returns:
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.
320 * Returns:
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);
341 } else {
342 static assert(0, "unimplemented arch");