iv.nanovega.textlayouter: more API!
[iv.d.git] / nanpay.d
blob1e6bfe564ae9f52e1b14ea20645055b3955dee83
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, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module iv.nanpay /*is aliced*/;
20 // doubles
21 enum MinSignedNanPay = -0x7_ffff_ffff_ffffL; // 51 bits
22 enum MaxSignedNanPay = +0x7_ffff_ffff_ffffL; // 51 bits
24 enum MinUnsignedNanPay = 0UL;
25 enum MaxUnsignedNanPay = 0x7_ffff_ffff_ffffUL; // 51 bits
27 // floats
28 enum MinSignedNanPayF = -0x3f_ffff; // 22 bits
29 enum MaxSignedNanPayF = +0x3f_ffff; // 22 bits
31 enum MinUnsignedNanPayF = 0U;
32 enum MaxUnsignedNanPayF = 0x3f_ffffU; // 22 bits
35 // ////////////////////////////////////////////////////////////////////////// //
36 /// is `v` finite (i.e. not a nan and not an infinity)?
37 bool isFinite (in double v) pure nothrow @trusted @nogc {
38 pragma(inline, true);
39 return (((*cast(const(ulong)*)&v)&0x7ff0_0000_0000_0000UL) != 0x7ff0_0000_0000_0000UL);
43 /// is `v` finite (i.e. not a nan and not an infinity)?
44 bool isFiniteF (in float v) pure nothrow @trusted @nogc {
45 pragma(inline, true);
46 return (((*cast(const(uint)*)&v)&0x7f80_0000U) != 0x7f80_0000U);
50 // ////////////////////////////////////////////////////////////////////////// //
51 /**
52 * Create a NaN, storing an integer inside the payload.
54 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
55 * One bit is reserved to not turn nans into infinity.
56 * But sign bit can be used to store sign, which allows to store signed values.
57 * IDC about quiet and signaling nans: check your numbers!
59 double makeNanPay(bool doChecking=false) (long pay) pure nothrow @trusted @nogc {
60 pragma(inline, true);
61 static if (doChecking) {
62 if (pay < MinSignedNanPay || pay > MaxSignedNanPay) assert(0, "invalid payload");
64 pay &= 0x8007_ffff_ffff_ffffUL; // left only bits we are interested in
65 pay |= 0x7ff8_0000_0000_0000UL; // set highest mantissa bit to ensure nan, and exponent to nan/inf
66 // create double
67 return *cast(double*)&pay;
71 /// (rough) check if the given double contains "good nan" with payload.
72 bool hasNanPay (in double v) pure nothrow @trusted @nogc {
73 pragma(inline, true);
74 return (((*cast(const(ulong)*)&v)&0x7ff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL);
78 /**
79 * Extract an integral payload from a NaN.
81 * Returns:
82 * the integer payload as a long.
84 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
85 * One bit is reserved to not turn nans into infinity.
86 * But sign bit can be used to store sign, which allows to store signed values.
87 * Check if your number is "good nan" before extracting!
89 long getNanPay (in double v) pure nothrow @trusted @nogc {
90 pragma(inline, true);
91 long pay = (*cast(const(long)*)&v)&0x8007_ffff_ffff_ffffUL; // remove exponent
92 // this bitors the missing "1" bits for negative numbers
93 // shift either by 16 (effectively removing the mask) or by 0
94 pay |= 0xfff8_0000_0000_0000UL<<(((pay>>59)&0x10)^0x10);
95 return pay;
99 /**
100 * Extract an integral payload from a NaN.
102 * Returns:
103 * the integer payload as a long or default value if NaN has no payload.
105 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
106 * One bit is reserved to not turn nans into infinity.
107 * But sign bit can be used to store sign, which allows to store signed values.
108 * Check if your number is "good nan" before extracting!
110 long getNanPayDef (in double v, long def) pure nothrow @trusted @nogc {
111 pragma(inline, true);
112 if (((*cast(const(ulong)*)&v)&0x7ff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL) {
113 long pay = (*cast(const(long)*)&v)&0x8007_ffff_ffff_ffffUL; // remove exponent
114 // this bitors the missing "1" bits for negative numbers
115 // shift either by 16 (effectively removing the mask) or by 0
116 pay |= 0xfff8_0000_0000_0000UL<<(((pay>>59)&0x10)^0x10);
117 return pay;
118 } else {
119 return def;
124 // ////////////////////////////////////////////////////////////////////////// //
126 * Create a NaN, storing an integer inside the payload.
128 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
129 * One bit is reserved to not turn nans into infinity.
130 * Sign bit is unused, and should be zero.
131 * IDC about quiet and signaling nans: check your numbers!
133 double makeNanPayU(bool doChecking=false) (ulong pay) pure nothrow @trusted @nogc {
134 pragma(inline, true);
135 static if (doChecking) {
136 if (pay > MaxUnsignedNanPay) assert(0, "invalid payload");
138 pay &= 0x0007_ffff_ffff_ffffUL; // left only bits we are interested in
139 pay |= 0x7ff8_0000_0000_0000UL; // set highest mantissa bit to ensure nan, and exponent to nan/inf
140 // create double
141 return *cast(double*)&pay;
145 /// (rough) check if the given double contains "good nan" with payload. sign bit should not be set.
146 bool hasNanPayU (in double v) pure nothrow @trusted @nogc {
147 pragma(inline, true);
148 return (((*cast(const(ulong)*)&v)&0xfff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL);
153 * Extract an integral payload from a NaN.
155 * Returns:
156 * the integer payload as a long or default value if NaN has no payload.
158 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
159 * One bit is reserved to not turn nans into infinity.
160 * Sign bit is unused, and should be zero.
161 * Check if your number is "good nan" before extracting!
163 ulong getNanPayU (in double v) pure nothrow @trusted @nogc {
164 pragma(inline, true);
165 return (*cast(const(ulong)*)&v)&0x0007_ffff_ffff_ffffUL; // remove exponent
170 * Extract an integral payload from a NaN.
172 * Returns:
173 * the integer payload as a long or default value if NaN has no payload.
175 * The largest possible payload is 0x7_ffff_ffff_ffff (51 bits).
176 * One bit is reserved to not turn nans into infinity.
177 * Sign bit is unused, and should be zero.
178 * Check if your number is "good nan" before extracting!
180 ulong getNanPayUDef (in double v, ulong def) pure nothrow @trusted @nogc {
181 pragma(inline, true);
182 return (((*cast(const(ulong)*)&v)&0xfff8_0000_0000_0000UL) == 0x7ff8_0000_0000_0000UL ?
183 (*cast(const(ulong)*)&v)&0x0007_ffff_ffff_ffffUL : def);
187 // ////////////////////////////////////////////////////////////////////////// //
188 // return 0, something <0, or something >0
189 int getDoubleXSign (in double v) pure nothrow @trusted @nogc {
190 pragma(inline, true);
191 version(LittleEndian) {
192 return ((*cast(const(ulong)*)&v)&(0x7fff_ffff_ffff_ffffUL) ? *((cast(const(int)*)&v)+1) : 0);
193 } else {
194 static assert(0, "unimplemented arch");
199 // ////////////////////////////////////////////////////////////////////////// //
201 * Create a NaN, storing an integer inside the payload.
203 * The largest possible payload is 0x3f_ffff (22 bits).
204 * One bit is reserved to not turn nans into infinity.
205 * But sign bit can be used to store sign, which allows to store signed values.
206 * IDC about quiet and signaling nans: check your numbers!
208 float makeNanPayF(bool doChecking=false) (int pay) pure nothrow @trusted @nogc {
209 pragma(inline, true);
210 static if (doChecking) {
211 if (pay < MinSignedNanPayF || pay > MaxSignedNanPayF) assert(0, "invalid payload");
213 pay &= 0x803f_ffffU; // left only bits we are interested in
214 pay |= 0x7fc0_0000U; // set highest mantissa bit to ensure nan, and exponent to nan/inf
215 // create float
216 return *cast(float*)&pay;
220 /// (rough) check if the given float contains "good nan" with payload.
221 bool hasNanPayF (in float v) pure nothrow @trusted @nogc {
222 pragma(inline, true);
223 return (((*cast(const(uint)*)&v)&0x7fc0_0000U) == 0x7fc0_0000U);
228 * Extract an integral payload from a NaN.
230 * Returns:
231 * the integer payload as a int.
233 * The largest possible payload is 0x3f_ffff (22 bits).
234 * One bit is reserved to not turn nans into infinity.
235 * But sign bit can be used to store sign, which allows to store signed values.
236 * Check if your number is "good nan" before extracting!
238 int getNanPayF (in float v) pure nothrow @trusted @nogc {
239 pragma(inline, true);
240 int pay = (*cast(const(int)*)&v)&0x803f_ffffU; // remove exponent
241 // this bitors the missing "1" bits for negative numbers
242 // shift either by 8 (effectively removing the mask) or by 0
243 pay |= 0xfc00_0000U<<(((pay>>28)&0x08)^0x08);
244 return pay;
249 * Extract an integral payload from a NaN.
251 * Returns:
252 * the integer payload as a int or default value if NaN has no payload.
254 * The largest possible payload is 0x3f_ffff (22 bits).
255 * One bit is reserved to not turn nans into infinity.
256 * But sign bit can be used to store sign, which allows to store signed values.
257 * Check if your number is "good nan" before extracting!
259 int getNanPayFDef (in float v, int def) pure nothrow @trusted @nogc {
260 pragma(inline, true);
261 if (((*cast(const(uint)*)&v)&0x7fc0_0000U) == 0x7fc0_0000U) {
262 int pay = (*cast(const(int)*)&v)&0x803f_ffffU; // remove exponent
263 // this bitors the missing "1" bits for negative numbers
264 // shift either by 8 (effectively removing the mask) or by 0
265 pay |= 0xfc00_0000U<<(((pay>>28)&0x08)^0x08);
266 return pay;
267 } else {
268 return def;
273 // ////////////////////////////////////////////////////////////////////////// //
275 * Create a NaN, storing an integer inside the payload.
277 * The largest possible payload is 0x3f_ffff (22 bits).
278 * One bit is reserved to not turn nans into infinity.
279 * Sign bit is unused, and should be zero.
280 * IDC about quiet and signaling nans: check your numbers!
282 float makeNanPayUF(bool doChecking=false) (uint pay) pure nothrow @trusted @nogc {
283 pragma(inline, true);
284 static if (doChecking) {
285 if (pay > MaxUnsignedNanPayF) assert(0, "invalid payload");
287 pay &= 0x003f_ffffU; // left only bits we are interested in
288 pay |= 0x7fc0_0000U; // set highest mantissa bit to ensure nan, and exponent to nan/inf
289 // create float
290 return *cast(float*)&pay;
294 /// (rough) check if the given float contains "good nan" with payload. sign bit should not be set.
295 bool hasNanPayUF (in float v) pure nothrow @trusted @nogc {
296 pragma(inline, true);
297 return (((*cast(const(uint)*)&v)&0xffc0_0000U) == 0x7fc0_0000U);
302 * Extract an integral payload from a NaN.
304 * Returns:
305 * the integer payload as a uint.
307 * The largest possible payload is 0x3f_ffff (22 bits).
308 * One bit is reserved to not turn nans into infinity.
309 * Sign bit is unused, and should be zero.
310 * Check if your number is "good nan" before extracting!
312 uint getNanPayUF (in float v) pure nothrow @trusted @nogc {
313 pragma(inline, true);
314 return (*cast(const(uint)*)&v)&0x003f_ffffU; // remove exponent
319 * Extract an integral payload from a NaN.
321 * Returns:
322 * the integer payload as a uint or default value if NaN has no payload.
324 * The largest possible payload is 0x3f_ffff (22 bits).
325 * One bit is reserved to not turn nans into infinity.
326 * Sign bit is unused, and should be zero.
327 * Check if your number is "good nan" before extracting!
329 uint getNanPayUFDef (in float v, uint def) pure nothrow @trusted @nogc {
330 pragma(inline, true);
331 return (((*cast(const(uint)*)&v)&0xffc0_0000U) == 0x7fc0_0000U ?
332 (*cast(const(uint)*)&v)&0x003f_ffffU : def);
336 // ////////////////////////////////////////////////////////////////////////// //
337 // return 0, something <0, or something >0
338 int getFloatXSign (in float v) pure nothrow @trusted @nogc {
339 pragma(inline, true);
340 version(LittleEndian) {
341 return ((*cast(const(uint)*)&v)&0x7fff_ffffU ? *(cast(const(int)*)&v) : 0);
342 } else {
343 static assert(0, "unimplemented arch");