1#[cfg(feature = "custom")]
33pub mod normalizer;
34#[cfg(feature = "custom")]
35pub mod ranges;
36
37pub const MAX_CSS_Z: i32 = 2_147_483_647;
38pub const MANTISSA: i32 = 8_388_608;
39
40pub const RANGE_UPPER_U: i32 = MAX_CSS_Z;
41pub const RANGE_UPPER_L: i32 = MAX_CSS_Z - MANTISSA + 1;
42
43pub const RANGE_MIDDLE_U: i32 = MANTISSA / 2;
44pub const RANGE_MIDDLE_L: i32 = -MANTISSA / 2 + 1;
45
46pub const RANGE_LOWER_U: i32 = -MAX_CSS_Z + MANTISSA;
47pub const RANGE_LOWER_L: i32 = -MAX_CSS_Z;
48
49pub fn normalize(z: i32) -> Option<f32> {
62 fn helper(z_: i32, upper_bound: i32, exp_offset: i32) -> Option<f32> {
63 let z = upper_bound - z_;
64 let quo = z / MANTISSA;
65 let rem = z % MANTISSA;
66 let normal = 2f32.powi(-quo - exp_offset);
67
68 Some(f32::from_bits(normal.to_bits() - rem as u32))
70 }
71
72 match z {
73 RANGE_LOWER_L => Some(0.0),
74 RANGE_UPPER_U => Some(1.0),
75 RANGE_LOWER_L..=RANGE_LOWER_U => helper(z, RANGE_LOWER_U, 2),
76 RANGE_MIDDLE_L..=RANGE_MIDDLE_U => helper(z, RANGE_MIDDLE_U, 1),
77 RANGE_UPPER_L..=RANGE_UPPER_U => helper(z, RANGE_UPPER_U, 0),
78 _ => None,
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn test_unsupported_z1() {
88 assert!(normalize(RANGE_UPPER_L - 1).is_none());
89 }
90 #[test]
91 fn test_unsupported_z2() {
92 assert!(normalize(RANGE_MIDDLE_U + 1).is_none());
93 }
94 #[test]
95 fn test_unsupported_z3() {
96 assert!(normalize(RANGE_MIDDLE_L - 1).is_none());
97 }
98 #[test]
99 fn test_unsupported_z4() {
100 assert!(normalize(RANGE_LOWER_L - 1).is_none());
101 }
102 #[test]
103 fn test_unsupported_z5() {
104 assert!(normalize(RANGE_LOWER_U + 1).is_none());
105 }
106
107 #[test]
108 fn test_supported_z1() {
109 assert!(normalize(RANGE_UPPER_U).is_some());
110 }
111 #[test]
112 fn test_supported_z2() {
113 assert!(normalize(RANGE_UPPER_L).is_some());
114 }
115 #[test]
116 fn test_supported_z3() {
117 assert!(normalize(RANGE_MIDDLE_L).is_some());
118 }
119 #[test]
120 fn test_supported_z4() {
121 assert!(normalize(RANGE_MIDDLE_U).is_some());
122 }
123 #[test]
124 fn test_supported_z5() {
125 assert!(normalize(RANGE_LOWER_L).is_some());
126 }
127 #[test]
128 fn test_supported_z6() {
129 assert!(normalize(RANGE_LOWER_U).is_some());
130 }
131
132 #[ignore]
133 #[test]
134 fn test_normalize_upper() {
135 let mut prev = -1.0;
136 let mut count = 0;
137 for i in RANGE_UPPER_L..=RANGE_UPPER_U {
138 count += 1;
139 let curr = normalize(i).unwrap();
140 assert!(curr > prev, "{i}: {} < {}", curr, prev);
141 prev = curr;
142 }
143 eprintln!("{count}");
144 }
145
146 #[ignore]
147 #[test]
148 fn test_normalize_middle() {
149 let mut prev = -1.0;
150 let mut count = 0;
151 for i in RANGE_MIDDLE_L..=RANGE_MIDDLE_U {
152 count += 1;
153 let curr = normalize(i).unwrap();
154 assert!(curr > prev, "{i}: {} < {}", curr, prev);
155 prev = curr;
156 }
157 eprintln!("{count}");
158 }
159
160 #[ignore]
161 #[test]
162 fn test_normalize_lower() {
163 let mut prev = -1.0;
164 let mut count = 0;
165 for i in RANGE_LOWER_L..=RANGE_LOWER_U {
166 count += 1;
167 let curr = normalize(i).unwrap();
168 assert!(curr > prev, "{i}: {} < {}", curr, prev);
169 prev = curr;
170 }
171 eprintln!("{count}");
172 }
173
174 #[ignore]
175 #[test]
176 fn test_continuity() {
177 let mut prev = -1.0;
178 let curr = normalize(RANGE_LOWER_U).unwrap();
179 assert!(curr > prev, "{}: {} > {}", RANGE_LOWER_U, curr, prev);
180 eprintln!("(LU): {curr} : {}", RANGE_LOWER_U);
181 prev = curr;
182 let curr = normalize(RANGE_MIDDLE_L).unwrap();
183 assert!(curr > prev, "{}: {} > {}", RANGE_MIDDLE_L, curr, prev);
184 eprintln!("(ML): {curr} : {}", RANGE_MIDDLE_L);
185 prev = curr;
186 let curr = normalize(RANGE_MIDDLE_U).unwrap();
187 assert!(curr > prev, "{}: {} > {}", RANGE_MIDDLE_U, curr, prev);
188 eprintln!("(MU): {curr} : {}", RANGE_MIDDLE_U);
189 prev = curr;
190 let curr = normalize(RANGE_UPPER_L).unwrap();
191 assert!(curr > prev, "{}: {} > {}", RANGE_UPPER_L, curr, prev);
192 eprintln!("(UL): {curr} : {}", RANGE_UPPER_L);
193 }
194
195 #[test]
196 fn test_normalize_all() {
197 test_normalize_lower();
198 test_normalize_middle();
199 test_normalize_upper();
200 test_continuity();
201 }
202}