boa/builtins/number/
conversions.rs1#[inline]
5#[allow(clippy::float_cmp)]
6pub(crate) fn f64_to_int32(number: f64) -> i32 {
7 const SIGN_MASK: u64 = 0x8000000000000000;
8 const EXPONENT_MASK: u64 = 0x7FF0000000000000;
9 const SIGNIFICAND_MASK: u64 = 0x000FFFFFFFFFFFFF;
10 const HIDDEN_BIT: u64 = 0x0010000000000000;
11 const PHYSICAL_SIGNIFICAND_SIZE: i32 = 52; const SIGNIFICAND_SIZE: i32 = 53;
13
14 const EXPONENT_BIAS: i32 = 0x3FF + PHYSICAL_SIGNIFICAND_SIZE;
15 const DENORMAL_EXPONENT: i32 = -EXPONENT_BIAS + 1;
16
17 #[inline]
18 fn is_denormal(number: f64) -> bool {
19 (number.to_bits() & EXPONENT_MASK) == 0
20 }
21
22 #[inline]
23 fn exponent(number: f64) -> i32 {
24 if is_denormal(number) {
25 return DENORMAL_EXPONENT;
26 }
27
28 let d64 = number.to_bits();
29 let biased_e = ((d64 & EXPONENT_MASK) >> PHYSICAL_SIGNIFICAND_SIZE) as i32;
30
31 biased_e - EXPONENT_BIAS
32 }
33
34 #[inline]
35 fn significand(number: f64) -> u64 {
36 let d64 = number.to_bits();
37 let significand = d64 & SIGNIFICAND_MASK;
38
39 if !is_denormal(number) {
40 significand + HIDDEN_BIT
41 } else {
42 significand
43 }
44 }
45
46 #[inline]
47 fn sign(number: f64) -> i64 {
48 if (number.to_bits() & SIGN_MASK) == 0 {
49 1
50 } else {
51 -1
52 }
53 }
54
55 if number.is_finite() && number <= f64::from(i32::MAX) && number >= f64::from(i32::MIN) {
56 let i = number as i32;
57 if f64::from(i) == number {
58 return i;
59 }
60 }
61
62 let exponent = exponent(number);
63 let bits = if exponent < 0 {
64 if exponent <= -SIGNIFICAND_SIZE {
65 return 0;
66 }
67
68 significand(number) >> -exponent
69 } else {
70 if exponent > 31 {
71 return 0;
72 }
73
74 (significand(number) << exponent) & 0xFFFFFFFF
75 };
76
77 (sign(number) * (bits as i64)) as i32
78}
79
80#[inline]
84pub(crate) fn f64_to_uint32(number: f64) -> u32 {
85 f64_to_int32(number) as u32
86}