softposit/pxe1/
convert.rs1use super::PxE1;
2use crate::{u32_with_sign, u64_with_sign};
3use core::f64;
4
5impl<const N: u32> From<PxE1<{ N }>> for f32 {
6 #[inline]
7 fn from(a: PxE1<{ N }>) -> Self {
8 a.to_f32()
9 }
10}
11
12impl<const N: u32> From<PxE1<{ N }>> for f64 {
13 #[inline]
14 fn from(p_a: PxE1<{ N }>) -> Self {
15 p_a.to_f64()
16 }
17}
18
19impl<const N: u32> From<f32> for PxE1<{ N }> {
20 #[inline]
21 fn from(float: f32) -> Self {
22 Self::from_f32(float)
23 }
24}
25
26impl<const N: u32> From<f64> for PxE1<{ N }> {
27 #[inline]
28 fn from(float: f64) -> Self {
29 Self::from_f64(float)
30 }
31}
32
33impl<const N: u32> From<PxE1<{ N }>> for i32 {
34 #[inline]
35 fn from(p_a: PxE1<{ N }>) -> Self {
36 p_a.to_i32()
37 }
38}
39
40impl<const N: u32> From<PxE1<{ N }>> for u32 {
41 #[inline]
42 fn from(p_a: PxE1<{ N }>) -> Self {
43 p_a.to_u32()
44 }
45}
46
47impl<const N: u32> From<PxE1<{ N }>> for i64 {
48 #[inline]
49 fn from(p_a: PxE1<{ N }>) -> Self {
50 p_a.to_i64()
51 }
52}
53
54impl<const N: u32> From<PxE1<{ N }>> for u64 {
55 #[inline]
56 fn from(p_a: PxE1<{ N }>) -> Self {
57 p_a.to_u64()
58 }
59}
60
61impl<const N: u32> From<u64> for PxE1<{ N }> {
62 #[inline]
63 fn from(a: u64) -> Self {
64 Self::from_u64(a)
65 }
66}
67
68impl<const N: u32> From<i64> for PxE1<{ N }> {
69 #[inline]
70 fn from(a: i64) -> Self {
71 Self::from_i64(a)
72 }
73}
74
75impl<const N: u32> From<u32> for PxE1<{ N }> {
76 #[inline]
77 fn from(a: u32) -> Self {
78 Self::from_u32(a)
79 }
80}
81
82impl<const N: u32> From<i32> for PxE1<{ N }> {
83 #[inline]
84 fn from(a: i32) -> Self {
85 Self::from_i32(a)
86 }
87}
88
89impl<const N: u32> PxE1<{ N }> {
90 #[inline]
91 pub fn to_f32(self) -> f32 {
92 self.to_f64() as f32
93 }
94
95 pub fn to_f64(self) -> f64 {
96 let mut ui_a = self.to_bits();
97
98 if self.is_zero() {
99 0.
100 } else if self.is_nar() {
101 f64::NAN
102 } else {
103 let sign_a = ui_a & 0x_8000_0000;
104 if sign_a != 0 {
105 ui_a = ui_a.wrapping_neg();
106 }
107 let (k_a, tmp) = PxE1::<{ N }>::separate_bits_tmp(ui_a);
108
109 let frac_a = ((tmp << 2) as u64) << 20;
110 let exp_a = (((k_a as u64) << 1) + ((tmp >> 30) as u64)).wrapping_add(1023) << 52;
111
112 f64::from_bits(exp_a + frac_a + ((sign_a as u64) << 32))
113 }
114 }
115
116 #[inline]
117 pub fn from_f32(float: f32) -> Self {
118 Self::from_f64(float as f64)
119 }
120
121 #[allow(clippy::cognitive_complexity)]
122 pub fn from_f64(mut float: f64) -> Self {
123 let mut reg: u32;
124 let mut frac = 0_u32;
125 let mut exp = 0_i32;
126 let mut bit_n_plus_one = false;
127 let mut bits_more = false;
128
129 if float == 0. {
130 return Self::ZERO;
131 } else if !float.is_finite() {
132 return Self::NAR;
133 }
134
135 let sign = float < 0.;
136
137 let u_z: u32 = if float == 1. {
138 0x4000_0000
139 } else if float == -1. {
140 0xC000_0000
141 } else if !(-1. ..=1.).contains(&float) {
142 if sign {
143 float = -float;
145 }
146
147 let reg_s = true;
148 reg = 1; if (N == 2) && (float <= 8.673_617_379_884_035_e-19) {
151 1
152 } else {
153 while float >= 4. {
155 float *= 0.25; reg += 1;
157 }
158 if float >= 2. {
159 float *= 0.5;
160 exp += 1;
161 }
162 let frac_length = (N - 3) as isize - (reg as isize);
163 if frac_length < 0 {
164 if reg == N - 2 {
165 bit_n_plus_one = exp != 0;
166 exp = 0;
167 }
168 if float > 1. {
169 bits_more = true;
170 }
171 } else {
172 frac = crate::convert_fraction_p32(
173 float,
174 frac_length as u16,
175 &mut bit_n_plus_one,
176 &mut bits_more,
177 );
178 }
179
180 if (reg == 30) && (frac > 0) {
181 bits_more = true;
182 frac = 0;
183 }
184
185 u32_with_sign(
186 if reg > (N - 2) {
187 if reg_s {
188 0x_7FFF_FFFF & Self::mask()
189 } else {
190 0x1 << (32 - N)
191 }
192 } else {
193 let regime = if reg_s { ((1 << reg) - 1) << 1 } else { 1_u32 };
196
197 let mut u_z = (regime << (30 - reg))
198 + ((exp as u32) << (29 - reg))
199 + ((frac << (32 - N)) as u32);
200 if (u_z == 0) && (frac > 0) {
202 u_z = 0x1 << (32 - N);
203 }
204 if bit_n_plus_one {
205 u_z += (((u_z >> (32 - N)) & 0x1) | (bits_more as u32)) << (32 - N);
206 }
207 u_z
208 },
209 sign,
210 )
211 }
212 } else if (float < 1.) || (float > -1.) {
213 if sign {
214 float = -float;
216 }
217
218 let reg_s = false;
219 reg = 0;
220
221 while float < 1. {
223 float *= 4.;
224 reg += 1;
225 }
226
227 if float >= 2. {
228 float *= 0.5;
229 exp += 1;
230 }
231
232 let frac_length = (N - 3) as isize - (reg as isize);
233 if frac_length < 0 {
234 if reg == N - 2 {
235 bit_n_plus_one = exp != 0;
236 exp = 0;
237 }
238
239 if float > 1. {
240 bits_more = true;
241 }
242 } else {
243 frac = crate::convert_fraction_p32(
244 float,
245 frac_length as u16,
246 &mut bit_n_plus_one,
247 &mut bits_more,
248 );
249 }
250
251 if (reg == 30) && (frac > 0) {
252 bits_more = true;
253 frac = 0;
254 }
255
256 u32_with_sign(
257 if reg > (N - 2) {
258 if reg_s {
259 0x_7FFF_FFFF & Self::mask()
260 } else {
261 0x1 << (32 - N)
262 }
263 } else {
264 let regime = if reg_s { ((1 << reg) - 1) << 1 } else { 1_u32 };
267
268 let mut u_z = (regime << (30 - reg))
269 + ((exp as u32) << (29 - reg))
270 + ((frac << (32 - N)) as u32);
271 if (u_z == 0) && (frac > 0) {
273 u_z = 0x1 << (32 - N);
274 }
275
276 if bit_n_plus_one {
277 u_z += (((u_z >> (32 - N)) & 0x1) | (bits_more as u32)) << (32 - N);
278 }
279 u_z
280 },
281 sign,
282 )
283 } else {
284 0x8000_0000
286 };
287 Self::from_bits(u_z)
288 }
289
290 pub const fn to_i32(self) -> i32 {
291 if self.is_nar() {
293 return i32::min_value();
294 }
295
296 let mut ui_a = self.to_bits();
297
298 let sign = ui_a > 0x_8000_0000; if sign {
301 ui_a = ui_a.wrapping_neg(); }
303
304 let i_z = convert_px1bits_to_u32(ui_a);
305 u32_with_sign(i_z, sign) as i32
306 }
307
308 pub const fn to_u32(self) -> u32 {
309 let ui_a = self.to_bits();
310 if ui_a >= 0x_8000_0000 {
312 0
313 } else {
314 convert_px1bits_to_u32(ui_a)
315 }
316 }
317
318 pub const fn to_i64(self) -> i64 {
319 if self.is_nar() {
321 return i64::min_value();
322 }
323
324 let mut ui_a = self.to_bits();
325
326 let sign = ui_a > 0x_8000_0000; if sign {
329 ui_a = ui_a.wrapping_neg(); }
331
332 let i_z = convert_px1bits_to_u64(ui_a);
333
334 u64_with_sign(i_z, sign) as i64
335 }
336
337 pub const fn to_u64(self) -> u64 {
338 let ui_a = self.to_bits();
339 if ui_a >= 0x_8000_0000 {
341 0
342 } else {
343 convert_px1bits_to_u64(ui_a)
344 }
345 }
346
347 pub const fn from_u64(a: u64) -> Self {
348 let ui_a = if a == 0x_8000_0000_0000_0000 {
349 0x_8000_0000
350 } else if N == 2 {
351 if a > 0 {
352 0x_4000_0000
353 } else {
354 0
355 }
356 } else if a > 0x_8000_0000_0000_0000 {
357 0x_7FFF_FFFF & ((0x_8000_0000_u64 >> (N - 1)) as u32) } else {
360 convert_u64_to_px1bits::<{ N }>(a)
361 };
362 Self::from_bits(ui_a)
363 }
364
365 pub const fn from_i64(_a: i64) -> Self {
366 todo!()
367 }
368
369 pub const fn from_i32(a: i32) -> Self {
370 let mut log2 = 31_i8; let mut ui_a = 0u32;
373 let mask = 0x80000000_u32;
374
375 let sign = a >> 31 != 0;
376 let a = if sign { -a as u32 } else { a as u32 };
377
378 if a == 0x80000000 {
380 ui_a = 0x80000000;
381 } else if N == 2 {
382 if a > 0 {
383 ui_a = 0x40000000;
384 }
385 } else if a > 2147418111 {
386 ui_a = 0x7FFF9FFF; } else if a < 0x2 {
389 ui_a = (a << 30) as u32;
390 } else {
391 let mut frac_a = a;
392 while (frac_a & mask) == 0 {
393 log2 -= 1;
394 frac_a <<= 1;
395 }
396 let k = (log2 >> 1) as u32;
397 let exp_a = ((log2 & 0x1) as u32) << (28 - k);
398 frac_a ^= mask;
399
400 if k >= (N - 2) {
401 ui_a = 0x7FFFFFFF & Self::mask();
403 } else if k == (N - 3) {
404 ui_a = 0x7FFFFFFF ^ (0x3FFFFFFF >> k);
406 if (exp_a & 0x2) != 0 && ((exp_a & 0x1) | frac_a) != 0 {
407 ui_a |= 0x80000000_u32 >> (N - 1);
409 }
410 } else if k == (N - 4) {
411 ui_a = (0x7FFFFFFF ^ (0x3FFFFFFF >> k)) | ((exp_a & 0x2) << (27 - k));
412 if exp_a & 0x1 != 0 && (((0x80000000_u32 >> (N - 1)) & ui_a) | frac_a) != 0 {
413 ui_a += 0x80000000_u32 >> (N - 1);
414 }
415 } else if k == (N - 5) {
416 ui_a = (0x7FFFFFFF ^ (0x3FFFFFFF >> k)) | (exp_a << (27 - k));
417 let mask = 0x8 << (k - N);
418 if (mask & frac_a) != 0 {
419 if (((mask - 1) & frac_a) | (exp_a & 0x1)) != 0 {
421 ui_a += 0x80000000_u32 >> (N - 1);
422 }
423 }
424 } else {
425 ui_a =
426 ((0x7FFFFFFFu32 ^ (0x3FFFFFFF >> k)) | (exp_a << (27 - k)) | frac_a >> (k + 4))
427 & Self::mask();
428 let mask = 0x8 << (k - N); if (mask & frac_a) != 0 && (((mask - 1) & frac_a) | ((mask << 1) & frac_a)) != 0 {
430 ui_a += 0x80000000_u32 >> (N - 1);
431 }
432 }
433 }
434 Self::from_bits(if sign { ui_a.wrapping_neg() } else { ui_a })
435 }
436
437 pub const fn from_u32(_a: u32) -> Self {
438 todo!()
439 }
440}
441
442#[inline]
443const fn calculate_scale(mut bits: u32) -> (u32, u32) {
444 let mut scale = 0_u32;
446
447 bits -= 0x_4000_0000; while (0x_2000_0000 & bits) != 0 {
449 scale += 2; bits = (bits - 0x_2000_0000) << 1; }
453 bits <<= 1; if (0x_2000_0000 & bits) != 0 {
455 scale += 1;
456 } (scale, bits)
459}
460
461const fn convert_px1bits_to_u32(ui_a: u32) -> u32 {
462 if ui_a <= 0x_3000_0000 {
463 0
465 } else if ui_a < 0x_4800_0000 {
466 1
468 } else if ui_a <= 0x_5400_0000 {
469 2
471 } else if ui_a > 0x_7FFF_BFFF {
472 4_294_967_295
474 } else {
475 let (scale, bits) = calculate_scale(ui_a);
476
477 let mut i_z64 = ((bits | 0x_2000_0000) as u64) << 33; let mut mask = 0x4000_0000_0000_0000_u64 >> scale; let bit_last = i_z64 & mask; mask >>= 1;
483 let mut tmp = i_z64 & mask;
484 let bit_n_plus_one = tmp != 0; i_z64 ^= tmp; tmp = i_z64 & (mask - 1); i_z64 ^= tmp; if bit_n_plus_one {
490 if (bit_last | tmp) != 0 {
492 i_z64 += mask << 1;
493 }
494 }
495
496 (i_z64 >> (62 - scale)) as u32 }
498}
499
500const fn convert_px1bits_to_u64(ui_a: u32) -> u64 {
501 if ui_a <= 0x_3000_0000 {
502 0
504 } else if ui_a < 0x_4800_0000 {
505 1
507 } else if ui_a <= 0x_5400_0000 {
508 2
510 } else {
511 let (scale, bits) = calculate_scale(ui_a);
512
513 let mut i_z = ((bits | 0x_2000_0000) as u64) << 33; let mut mask = 0x_4000_0000_0000_0000 >> scale; let bit_last = i_z & mask; mask >>= 1;
518 let mut tmp = i_z & mask;
519 let bit_n_plus_one = tmp != 0; i_z ^= tmp; tmp = i_z & (mask - 1); i_z ^= tmp; if bit_n_plus_one {
525 if (bit_last | tmp) != 0 {
527 i_z += mask << 1;
528 }
529 }
530
531 i_z >> (62 - scale) }
533}
534
535const fn convert_u64_to_px1bits<const N: u32>(a: u64) -> u32 {
536 let mut log2 = 63_i8; let mut mask = 0x_8000_0000_0000_0000_u64;
538 if a < 0x2 {
539 (a as u32) << 30
540 } else {
541 let mut frac64_a = a;
542 while (frac64_a & mask) == 0 {
543 log2 -= 1;
544 frac64_a <<= 1;
545 }
546
547 let k = (log2 >> 1) as u32;
548
549 let exp_a = (log2 & 0x1) as u32;
550 frac64_a ^= mask;
551 frac64_a <<= 1;
552
553 let mut ui_a: u32;
554 if k >= (N - 2) {
555 ui_a = 0x_7FFF_FFFF & PxE1::<{ N }>::mask();
557 } else if k == (N - 3) {
558 ui_a = 0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k);
560 if ((exp_a & 0x1) != 0) && (frac64_a != 0) {
561 ui_a |= 0x_8000_0000_u32 >> (N - 1);
563 }
564 } else if k == (N - 4) {
565 ui_a = (0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k)) | (exp_a << (28 - k));
567 mask = 0x_0008_0000_0000_u64 << (k + 32 - N);
568 if (mask & frac64_a) != 0 {
569 if (((mask - 1) & frac64_a) | ((exp_a & 0x1) as u64)) != 0 {
571 ui_a += 0x_8000_0000_u32 >> (N - 1);
572 }
573 }
574 } else {
575 ui_a = (0x_7FFF_FFFF ^ (0x_3FFF_FFFF >> k))
576 | (exp_a << (28 - k))
577 | (((frac64_a >> (k + 36)) as u32) & PxE1::<{ N }>::mask());
578 mask = 0x_0008_0000_0000_u64 << (k + 32 - N); if ((mask & frac64_a) != 0)
580 && ((((mask - 1) & frac64_a) | ((mask << 1) & frac64_a)) != 0)
581 {
582 ui_a += 0x_8000_0000_u32 >> (N - 1);
583 }
584 }
585 ui_a
586 }
587}