tract_linalg/generic/
rounding.rs

1use crate::frame::mmm::*;
2use std::hash::{Hash, Hasher};
3use std::ops::Mul;
4use tract_data::prelude::f16;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
7pub struct Scaler {
8    pub scale: f32,
9    pub mult: Option<i32>,
10    pub shift: isize,
11    pub policy: RoundingPolicy,
12}
13
14impl Eq for Scaler {}
15
16#[allow(clippy::derived_hash_with_manual_eq)]
17impl Hash for Scaler {
18    fn hash<H>(&self, state: &mut H)
19    where
20        H: Hasher,
21    {
22        Hash::hash(&self.scale.to_bits(), state)
23    }
24}
25
26impl Scaler {
27    pub fn new(scale: f32, policy: RoundingPolicy) -> Self {
28        let (mult, shift) = Self::convert_scale_to_mult_shift(scale);
29        Self { scale, mult, shift, policy }
30    }
31
32    pub fn as_fused_spec(&self) -> FusedSpec {
33        if let Some(multiplier) = self.mult {
34            FusedSpec::QScale(self.shift, self.policy, multiplier)
35        } else if self.shift > 0 {
36            FusedSpec::RoundingShiftRight(self.shift as usize, self.policy)
37        } else {
38            FusedSpec::ShiftLeft((-self.shift) as usize)
39        }
40    }
41
42    // FIXME: Only to avoid fused op breaking
43    pub fn from_fuse_params(shift: isize, policy: RoundingPolicy, mult: i32) -> Self {
44        let scale = mult as f32 * 2f32.powi(-(31 + shift as i32));
45        Self { scale, mult: Some(mult), shift, policy }
46    }
47
48    #[inline]
49    // This function convert a scale (actually a fraction of two integers Q/D)
50    // into an integer multiplier and a shift (the multiplier being 1/2D in Q0_31).
51    fn convert_scale_to_mult_shift(scale: f32) -> (Option<i32>, isize) {
52        // Zero is a special case to handle
53        if scale == 0.0 {
54            return (None, 0);
55        }
56
57        // Convert f32 to bits representation with the following pattern
58        // Bit |  31  |  30-23   |   22-0    |
59        //     | Sign | Exponent |  Fraction |
60        let scale_bits = scale.to_bits();
61
62        // Get actual value of the exponent
63        let current_exponent = (scale_bits >> 23) & 0xff;
64
65        // Extract fractional part of the float with:
66        // - 0x007fffff that represents the mask of the 23 lower bits (fractional part)
67        // (partial because it doesn't include the hidden bit (24) of the float representation)
68        let partial_frac = scale_bits & 0x007fffff;
69
70        if partial_frac == 0 {
71            let shift = 127 - current_exponent as isize;
72            (None, shift)
73        } else {
74            // We add 0x800000 that represents the hidden bit set to one.
75            // Here the frac is encoded as a Q8_23.
76            let frac = partial_frac | 0x800000;
77
78            // We rescale the result to be in Q0_31
79            // We should have shifted the result by 8 but the frac value is in [1.0, 2.0)
80            // so we cannot do that (we would need one bit for the integer).
81            // Instead we devide the frac by two to be in [0.5, 1.0) in Q0_31
82            // which lead to a shift of (8-1 = 7).
83            let half_frac = (frac << 7) as i32;
84
85            // Compute the actual value of the shift
86            // Here, we remove one as half_frac needs to be multiplied by 2.
87            let shift = 127 - current_exponent as isize - 1;
88            (Some(half_frac), shift)
89        }
90    }
91}
92
93impl Mul<f16> for Scaler {
94    type Output = f16;
95
96    #[inline]
97    fn mul(self, rhs: f16) -> Self::Output {
98        f16::from_f32(self.scale) * rhs
99    }
100}
101
102impl Mul<f32> for Scaler {
103    type Output = f32;
104
105    #[inline]
106    fn mul(self, rhs: f32) -> Self::Output {
107        self.scale * rhs
108    }
109}
110
111impl Mul<f64> for Scaler {
112    type Output = f64;
113
114    #[inline]
115    fn mul(self, rhs: f64) -> Self::Output {
116        self.scale as f64 * rhs
117    }
118}
119
120impl Mul<Scaler> for f16 {
121    type Output = f16;
122
123    #[inline]
124    fn mul(self, rhs: Scaler) -> Self::Output {
125        rhs * self
126    }
127}
128
129impl Mul<Scaler> for f32 {
130    type Output = f32;
131
132    #[inline]
133    fn mul(self, rhs: Scaler) -> Self::Output {
134        rhs * self
135    }
136}
137
138impl Mul<Scaler> for f64 {
139    type Output = f64;
140
141    #[inline]
142    fn mul(self, rhs: Scaler) -> Self::Output {
143        rhs * self
144    }
145}
146
147impl Mul<i32> for Scaler {
148    type Output = i32;
149
150    #[inline]
151    fn mul(self, rhs: i32) -> Self::Output {
152        let (val, shift) = if let Some(multiplier) = self.mult {
153            (multiplier as i64 * rhs as i64, self.shift + 31)
154        } else {
155            (rhs as i64, self.shift)
156        };
157
158        // Round according to rounding policy
159        use RoundingPolicy::*;
160        if shift > 0 {
161            let half: i64 = 1 << (shift - 1);
162            let nudge: i64 = match self.policy {
163                Zero => -1,
164                MinusInf => -((val >= 0) as i64),
165                PlusInf => -((val <= 0) as i64),
166                Away => 0,
167                Even => ((val.abs() >> shift) & 0x1) - 1,
168                Odd => -((val.abs() >> shift) & 0x1),
169                _ => panic!(),
170            };
171
172            (val.signum() * ((val.abs() + half + nudge) >> shift)) as i32
173        } else {
174            (val << -shift) as i32
175        }
176    }
177}
178
179impl Mul<Scaler> for i32 {
180    type Output = i32;
181
182    #[inline]
183    fn mul(self, rhs: Scaler) -> Self::Output {
184        rhs * self
185    }
186}
187
188pub trait ScaleShiftAndRound {
189    fn q_scale(self, scaler: Scaler) -> Self;
190    fn q_shl(self, shift: usize) -> Self;
191    fn q_shr(self, shift: usize, rp: RoundingPolicy) -> Self;
192}
193
194impl ScaleShiftAndRound for f64 {
195    fn q_scale(self, scaler: Scaler) -> Self {
196        self * scaler
197    }
198    fn q_shl(self, shift: usize) -> Self {
199        self * 2f64.powi(shift as i32)
200    }
201    fn q_shr(self, shift: usize, _rp: RoundingPolicy) -> Self {
202        self * 2f64.powi(-(shift as i32))
203    }
204}
205
206impl ScaleShiftAndRound for f32 {
207    fn q_scale(self, scaler: Scaler) -> Self {
208        self * scaler
209    }
210    fn q_shl(self, shift: usize) -> Self {
211        self * 2f32.powi(shift as i32)
212    }
213    fn q_shr(self, shift: usize, _rp: RoundingPolicy) -> Self {
214        self * 2f32.powi(-(shift as i32))
215    }
216}
217
218impl ScaleShiftAndRound for f16 {
219    fn q_scale(self, scaler: Scaler) -> Self {
220        self * scaler
221    }
222    fn q_shl(self, shift: usize) -> Self {
223        self * f16::from_f32(2f32.powi(shift as i32))
224    }
225    fn q_shr(self, shift: usize, _rp: RoundingPolicy) -> Self {
226        self * f16::from_f32(2f32.powi(-(shift as i32)))
227    }
228}
229
230impl ScaleShiftAndRound for i32 {
231    fn q_scale(self, scaler: Scaler) -> Self {
232        self * scaler
233    }
234    fn q_shr(self, shift: usize, rp: RoundingPolicy) -> Self {
235        use RoundingPolicy::*;
236        let half: i32 = 1 << (shift - 1);
237        let nudge: i32 = match rp {
238            Zero => -1,
239            MinusInf => -((self >= 0) as i32),
240            PlusInf => -((self <= 0) as i32),
241            Away => 0,
242            Even => ((self.abs() >> shift) & 0x1) - 1,
243            Odd => -((self.abs() >> shift) & 0x1),
244            _ => panic!(),
245        };
246        self.signum() * ((self.abs() + half + nudge) >> shift)
247    }
248    fn q_shl(self, shift: usize) -> Self {
249        self << shift
250    }
251}
252
253// 6 / 4 -> 1.5 -> arrondi: 2.  rien a faire
254// 2 / 4 -> 0.5 -> arrondi: 1. veut 0 -> nudge = -1
255
256#[cfg(test)]
257mod test {
258    use super::RoundingPolicy::*;
259    use super::*;
260
261    #[test]
262    fn test_scale_rounding_f32() {
263        assert_eq!(0f32.q_scale(Scaler::new(0.5, Zero)), 0.0);
264        assert_eq!(1f32.q_scale(Scaler::new(0.5, Zero)), 0.5);
265        assert_eq!(2f32.q_scale(Scaler::new(0.5, Zero)), 1.0);
266        assert_eq!(3f32.q_scale(Scaler::new(0.5, Zero)), 1.5);
267        assert_eq!((-1f32).q_scale(Scaler::new(0.5, Zero)), -0.5);
268        assert_eq!((-2f32).q_scale(Scaler::new(0.5, Zero)), -1.0);
269        assert_eq!((-3f32).q_scale(Scaler::new(0.5, Zero)), -1.5);
270    }
271
272    #[test]
273    fn test_shift_rounding_zero() {
274        assert_eq!(0i32.q_shr(1, Zero), 0);
275        assert_eq!(1i32.q_shr(1, Zero), 0);
276        assert_eq!(2i32.q_shr(1, Zero), 1);
277        assert_eq!(3i32.q_shr(1, Zero), 1);
278        assert_eq!(0i32.q_shr(2, Zero), 0);
279        assert_eq!(1i32.q_shr(2, Zero), 0);
280        assert_eq!(2i32.q_shr(2, Zero), 0);
281        assert_eq!(3i32.q_shr(2, Zero), 1);
282        assert_eq!(4i32.q_shr(2, Zero), 1);
283        assert_eq!(5i32.q_shr(2, Zero), 1);
284        assert_eq!(6i32.q_shr(2, Zero), 1);
285        assert_eq!((-1i32).q_shr(2, Zero), 0);
286        assert_eq!((-2i32).q_shr(2, Zero), 0);
287        assert_eq!((-3i32).q_shr(2, Zero), -1);
288        assert_eq!((-4i32).q_shr(2, Zero), -1);
289        assert_eq!((-5i32).q_shr(2, Zero), -1);
290        assert_eq!((-6i32).q_shr(2, Zero), -1);
291    }
292
293    #[test]
294    fn test_scale_rounding_zero() {
295        assert_eq!(0i32.q_scale(Scaler::new(0.5, Zero)), 0);
296        assert_eq!(1i32.q_scale(Scaler::new(0.5, Zero)), 0);
297        assert_eq!(2i32.q_scale(Scaler::new(0.5, Zero)), 1);
298        assert_eq!(3i32.q_scale(Scaler::new(0.5, Zero)), 1);
299        assert_eq!((-1i32).q_scale(Scaler::new(0.5, Zero)), 0);
300        assert_eq!((-2i32).q_scale(Scaler::new(0.5, Zero)), -1);
301        assert_eq!((-3i32).q_scale(Scaler::new(0.5, Zero)), -1);
302        assert_eq!(2i32.q_scale(Scaler::new(0.25, Zero)), 0);
303        assert_eq!(3i32.q_scale(Scaler::new(0.25, Zero)), 1);
304        assert_eq!(4i32.q_scale(Scaler::new(0.25, Zero)), 1);
305        assert_eq!(5i32.q_scale(Scaler::new(0.25, Zero)), 1);
306        assert_eq!(6i32.q_scale(Scaler::new(0.25, Zero)), 1);
307        assert_eq!((-2i32).q_scale(Scaler::new(0.25, Zero)), 0);
308        assert_eq!((-3i32).q_scale(Scaler::new(0.25, Zero)), -1);
309        assert_eq!((-4i32).q_scale(Scaler::new(0.25, Zero)), -1);
310        assert_eq!((-5i32).q_scale(Scaler::new(0.25, Zero)), -1);
311        assert_eq!((-6i32).q_scale(Scaler::new(0.25, Zero)), -1);
312    }
313
314    #[test]
315    fn test_shift_rounding_away() {
316        assert_eq!(0i32.q_shr(1, Away), 0);
317        assert_eq!(1i32.q_shr(1, Away), 1);
318        assert_eq!(2i32.q_shr(1, Away), 1);
319        assert_eq!(3i32.q_shr(1, Away), 2);
320        assert_eq!(0i32.q_shr(2, Away), 0);
321        assert_eq!(1i32.q_shr(2, Away), 0);
322        assert_eq!(2i32.q_shr(2, Away), 1);
323        assert_eq!(3i32.q_shr(2, Away), 1);
324        assert_eq!(4i32.q_shr(2, Away), 1);
325        assert_eq!(5i32.q_shr(2, Away), 1);
326        assert_eq!(6i32.q_shr(2, Away), 2);
327        assert_eq!((-1i32).q_shr(2, Away), 0);
328        assert_eq!((-2i32).q_shr(2, Away), -1);
329        assert_eq!((-3i32).q_shr(2, Away), -1);
330        assert_eq!((-4i32).q_shr(2, Away), -1);
331        assert_eq!((-5i32).q_shr(2, Away), -1);
332        assert_eq!((-6i32).q_shr(2, Away), -2);
333    }
334
335    #[test]
336    fn test_scale_rounding_away() {
337        assert_eq!(0i32.q_scale(Scaler::new(0.5, Away)), 0);
338        assert_eq!(1i32.q_scale(Scaler::new(0.5, Away)), 1);
339        assert_eq!(2i32.q_scale(Scaler::new(0.5, Away)), 1);
340        assert_eq!(3i32.q_scale(Scaler::new(0.5, Away)), 2);
341        assert_eq!((-1i32).q_scale(Scaler::new(0.5, Away)), -1);
342        assert_eq!((-2i32).q_scale(Scaler::new(0.5, Away)), -1);
343        assert_eq!((-3i32).q_scale(Scaler::new(0.5, Away)), -2);
344        assert_eq!(2i32.q_scale(Scaler::new(0.25, Away)), 1);
345        assert_eq!(3i32.q_scale(Scaler::new(0.25, Away)), 1);
346        assert_eq!(4i32.q_scale(Scaler::new(0.25, Away)), 1);
347        assert_eq!(5i32.q_scale(Scaler::new(0.25, Away)), 1);
348        assert_eq!(6i32.q_scale(Scaler::new(0.25, Away)), 2);
349        assert_eq!((-2i32).q_scale(Scaler::new(0.25, Away)), -1);
350        assert_eq!((-3i32).q_scale(Scaler::new(0.25, Away)), -1);
351        assert_eq!((-4i32).q_scale(Scaler::new(0.25, Away)), -1);
352        assert_eq!((-5i32).q_scale(Scaler::new(0.25, Away)), -1);
353        assert_eq!((-6i32).q_scale(Scaler::new(0.25, Away)), -2);
354    }
355
356    #[test]
357    fn test_shift_rounding_plus_inf() {
358        assert_eq!(0i32.q_shr(1, PlusInf), 0);
359        assert_eq!(1i32.q_shr(1, PlusInf), 1);
360        assert_eq!(2i32.q_shr(1, PlusInf), 1);
361        assert_eq!(3i32.q_shr(1, PlusInf), 2);
362        assert_eq!(0i32.q_shr(2, PlusInf), 0);
363        assert_eq!(1i32.q_shr(2, PlusInf), 0);
364        assert_eq!(2i32.q_shr(2, PlusInf), 1);
365        assert_eq!(3i32.q_shr(2, PlusInf), 1);
366        assert_eq!(4i32.q_shr(2, PlusInf), 1);
367        assert_eq!(5i32.q_shr(2, PlusInf), 1);
368        assert_eq!(6i32.q_shr(2, PlusInf), 2);
369        assert_eq!((-1i32).q_shr(2, PlusInf), 0);
370        assert_eq!((-2i32).q_shr(2, PlusInf), 0);
371        assert_eq!((-3i32).q_shr(2, PlusInf), -1);
372        assert_eq!((-4i32).q_shr(2, PlusInf), -1);
373        assert_eq!((-5i32).q_shr(2, PlusInf), -1);
374        assert_eq!((-6i32).q_shr(2, PlusInf), -1);
375    }
376
377    #[test]
378    fn test_scale_rounding_plus_inf() {
379        assert_eq!(0i32.q_scale(Scaler::new(0.5, PlusInf)), 0);
380        assert_eq!(1i32.q_scale(Scaler::new(0.5, PlusInf)), 1);
381        assert_eq!(2i32.q_scale(Scaler::new(0.5, PlusInf)), 1);
382        assert_eq!(3i32.q_scale(Scaler::new(0.5, PlusInf)), 2);
383        assert_eq!((-1i32).q_scale(Scaler::new(0.5, PlusInf)), 0);
384        assert_eq!((-2i32).q_scale(Scaler::new(0.5, PlusInf)), -1);
385        assert_eq!((-3i32).q_scale(Scaler::new(0.5, PlusInf)), -1);
386        assert_eq!(2i32.q_scale(Scaler::new(0.25, PlusInf)), 1);
387        assert_eq!(3i32.q_scale(Scaler::new(0.25, PlusInf)), 1);
388        assert_eq!(4i32.q_scale(Scaler::new(0.25, PlusInf)), 1);
389        assert_eq!(5i32.q_scale(Scaler::new(0.25, PlusInf)), 1);
390        assert_eq!(6i32.q_scale(Scaler::new(0.25, PlusInf)), 2);
391        assert_eq!((-2i32).q_scale(Scaler::new(0.25, PlusInf)), 0);
392        assert_eq!((-3i32).q_scale(Scaler::new(0.25, PlusInf)), -1);
393        assert_eq!((-4i32).q_scale(Scaler::new(0.25, PlusInf)), -1);
394        assert_eq!((-5i32).q_scale(Scaler::new(0.25, PlusInf)), -1);
395        assert_eq!((-6i32).q_scale(Scaler::new(0.25, PlusInf)), -1);
396    }
397
398    #[test]
399    fn test_shift_rounding_minus_inf() {
400        assert_eq!(0i32.q_shr(1, MinusInf), 0);
401        assert_eq!(1i32.q_shr(1, MinusInf), 0);
402        assert_eq!(2i32.q_shr(1, MinusInf), 1);
403        assert_eq!(3i32.q_shr(1, MinusInf), 1);
404        assert_eq!(0i32.q_shr(2, MinusInf), 0);
405        assert_eq!(1i32.q_shr(2, MinusInf), 0);
406        assert_eq!(2i32.q_shr(2, MinusInf), 0);
407        assert_eq!(3i32.q_shr(2, MinusInf), 1);
408        assert_eq!(4i32.q_shr(2, MinusInf), 1);
409        assert_eq!(5i32.q_shr(2, MinusInf), 1);
410        assert_eq!(6i32.q_shr(2, MinusInf), 1);
411        assert_eq!((-1i32).q_shr(2, MinusInf), 0);
412        assert_eq!((-2i32).q_shr(2, MinusInf), -1);
413        assert_eq!((-3i32).q_shr(2, MinusInf), -1);
414        assert_eq!((-4i32).q_shr(2, MinusInf), -1);
415        assert_eq!((-5i32).q_shr(2, MinusInf), -1);
416        assert_eq!((-6i32).q_shr(2, MinusInf), -2);
417    }
418
419    #[test]
420    fn test_scale_rounding_minus_inf() {
421        assert_eq!(0i32.q_scale(Scaler::new(0.5, MinusInf)), 0);
422        assert_eq!(1i32.q_scale(Scaler::new(0.5, MinusInf)), 0);
423        assert_eq!(2i32.q_scale(Scaler::new(0.5, MinusInf)), 1);
424        assert_eq!(3i32.q_scale(Scaler::new(0.5, MinusInf)), 1);
425        assert_eq!((-1i32).q_scale(Scaler::new(0.5, MinusInf)), -1);
426        assert_eq!((-2i32).q_scale(Scaler::new(0.5, MinusInf)), -1);
427        assert_eq!((-3i32).q_scale(Scaler::new(0.5, MinusInf)), -2);
428        assert_eq!(2i32.q_scale(Scaler::new(0.25, MinusInf)), 0);
429        assert_eq!(3i32.q_scale(Scaler::new(0.25, MinusInf)), 1);
430        assert_eq!(4i32.q_scale(Scaler::new(0.25, MinusInf)), 1);
431        assert_eq!(5i32.q_scale(Scaler::new(0.25, MinusInf)), 1);
432        assert_eq!(6i32.q_scale(Scaler::new(0.25, MinusInf)), 1);
433        assert_eq!((-2i32).q_scale(Scaler::new(0.25, MinusInf)), -1);
434        assert_eq!((-3i32).q_scale(Scaler::new(0.25, MinusInf)), -1);
435        assert_eq!((-4i32).q_scale(Scaler::new(0.25, MinusInf)), -1);
436        assert_eq!((-5i32).q_scale(Scaler::new(0.25, MinusInf)), -1);
437        assert_eq!((-6i32).q_scale(Scaler::new(0.25, MinusInf)), -2);
438        //assert_eq!((-9i32).q_scale(ONE_OVER_TWO_IN_Q0_30, 5, MinusInf), 0);
439    }
440
441    #[test]
442    fn test_shift_rounding_even() {
443        assert_eq!(0i32.q_shr(1, Even), 0);
444        assert_eq!(1i32.q_shr(1, Even), 0);
445        assert_eq!(2i32.q_shr(1, Even), 1);
446        assert_eq!(3i32.q_shr(1, Even), 2);
447        assert_eq!(0i32.q_shr(2, Even), 0);
448        assert_eq!(1i32.q_shr(2, Even), 0);
449        assert_eq!(2i32.q_shr(2, Even), 0);
450        assert_eq!(3i32.q_shr(2, Even), 1);
451        assert_eq!(4i32.q_shr(2, Even), 1);
452        assert_eq!(5i32.q_shr(2, Even), 1);
453        assert_eq!(6i32.q_shr(2, Even), 2);
454        assert_eq!((-1i32).q_shr(2, Even), 0);
455        assert_eq!((-2i32).q_shr(2, Even), 0);
456        assert_eq!((-3i32).q_shr(2, Even), -1);
457        assert_eq!((-4i32).q_shr(2, Even), -1);
458        assert_eq!((-5i32).q_shr(2, Even), -1);
459        assert_eq!((-6i32).q_shr(2, Even), -2);
460    }
461
462    #[test]
463    fn test_scale_rounding_even() {
464        assert_eq!(0i32.q_scale(Scaler::new(0.5, Even)), 0);
465        assert_eq!(1i32.q_scale(Scaler::new(0.5, Even)), 0);
466        assert_eq!(2i32.q_scale(Scaler::new(0.5, Even)), 1);
467        assert_eq!(3i32.q_scale(Scaler::new(0.5, Even)), 2);
468        assert_eq!((-1i32).q_scale(Scaler::new(0.5, Even)), 0);
469        assert_eq!((-2i32).q_scale(Scaler::new(0.5, Even)), -1);
470        assert_eq!((-3i32).q_scale(Scaler::new(0.5, Even)), -2);
471        assert_eq!(2i32.q_scale(Scaler::new(0.25, Even)), 0);
472        assert_eq!(3i32.q_scale(Scaler::new(0.25, Even)), 1);
473        assert_eq!(4i32.q_scale(Scaler::new(0.25, Even)), 1);
474        assert_eq!(5i32.q_scale(Scaler::new(0.25, Even)), 1);
475        assert_eq!(6i32.q_scale(Scaler::new(0.25, Even)), 2);
476        assert_eq!((-2i32).q_scale(Scaler::new(0.25, Even)), 0);
477        assert_eq!((-3i32).q_scale(Scaler::new(0.25, Even)), -1);
478        assert_eq!((-4i32).q_scale(Scaler::new(0.25, Even)), -1);
479        assert_eq!((-5i32).q_scale(Scaler::new(0.25, Even)), -1);
480        assert_eq!((-6i32).q_scale(Scaler::new(0.25, Even)), -2);
481    }
482
483    #[test]
484    fn test_shift_rounding_odd() {
485        assert_eq!(0i32.q_shr(1, Odd), 0);
486        assert_eq!(1i32.q_shr(1, Odd), 1);
487        assert_eq!(2i32.q_shr(1, Odd), 1);
488        assert_eq!(3i32.q_shr(1, Odd), 1);
489        assert_eq!(0i32.q_shr(2, Odd), 0);
490        assert_eq!(1i32.q_shr(2, Odd), 0);
491        assert_eq!(2i32.q_shr(2, Odd), 1);
492        assert_eq!(3i32.q_shr(2, Odd), 1);
493        assert_eq!(4i32.q_shr(2, Odd), 1);
494        assert_eq!(5i32.q_shr(2, Odd), 1);
495        assert_eq!(6i32.q_shr(2, Odd), 1);
496        assert_eq!((-1i32).q_shr(2, Odd), 0);
497        assert_eq!((-2i32).q_shr(2, Odd), -1);
498        assert_eq!((-3i32).q_shr(2, Odd), -1);
499        assert_eq!((-4i32).q_shr(2, Odd), -1);
500        assert_eq!((-5i32).q_shr(2, Odd), -1);
501        assert_eq!((-6i32).q_shr(2, Odd), -1);
502    }
503
504    #[test]
505    fn test_scale_rounding_odd() {
506        assert_eq!(0i32.q_scale(Scaler::new(0.5, Odd)), 0);
507        assert_eq!(1i32.q_scale(Scaler::new(0.5, Odd)), 1);
508        assert_eq!(2i32.q_scale(Scaler::new(0.5, Odd)), 1);
509        assert_eq!(3i32.q_scale(Scaler::new(0.5, Odd)), 1);
510        assert_eq!((-1i32).q_scale(Scaler::new(0.5, Odd)), -1);
511        assert_eq!((-2i32).q_scale(Scaler::new(0.5, Odd)), -1);
512        assert_eq!((-3i32).q_scale(Scaler::new(0.5, Odd)), -1);
513        assert_eq!(2i32.q_scale(Scaler::new(0.25, Odd)), 1);
514        assert_eq!(3i32.q_scale(Scaler::new(0.25, Odd)), 1);
515        assert_eq!(4i32.q_scale(Scaler::new(0.25, Odd)), 1);
516        assert_eq!(5i32.q_scale(Scaler::new(0.25, Odd)), 1);
517        assert_eq!(6i32.q_scale(Scaler::new(0.25, Odd)), 1);
518        assert_eq!((-2i32).q_scale(Scaler::new(0.25, Odd)), -1);
519        assert_eq!((-3i32).q_scale(Scaler::new(0.25, Odd)), -1);
520        assert_eq!((-4i32).q_scale(Scaler::new(0.25, Odd)), -1);
521        assert_eq!((-5i32).q_scale(Scaler::new(0.25, Odd)), -1);
522        assert_eq!((-6i32).q_scale(Scaler::new(0.25, Odd)), -1);
523    }
524}