1 // Copyright (c) 2017-2020, The rav1e contributors. All rights reserved
2 //
3 // This source code is subject to the terms of the BSD 2 Clause License and
4 // the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
5 // was not distributed with this source code in the LICENSE file, you can
6 // obtain it at www.aomedia.org/license/software. If the Alliance for Open
7 // Media Patent License 1.0 was not distributed with this source code in the
8 // PATENTS file, you can obtain it at www.aomedia.org/license/patent.
9 
10 use num_traits::PrimInt;
11 use std::mem::size_of;
12 
13 pub trait Fixed {
floor_log2(&self, n: usize) -> usize14   fn floor_log2(&self, n: usize) -> usize;
ceil_log2(&self, n: usize) -> usize15   fn ceil_log2(&self, n: usize) -> usize;
align_power_of_two(&self, n: usize) -> usize16   fn align_power_of_two(&self, n: usize) -> usize;
align_power_of_two_and_shift(&self, n: usize) -> usize17   fn align_power_of_two_and_shift(&self, n: usize) -> usize;
18 }
19 
20 impl Fixed for usize {
21   #[inline]
floor_log2(&self, n: usize) -> usize22   fn floor_log2(&self, n: usize) -> usize {
23     self & !((1 << n) - 1)
24   }
25   #[inline]
ceil_log2(&self, n: usize) -> usize26   fn ceil_log2(&self, n: usize) -> usize {
27     (self + (1 << n) - 1).floor_log2(n)
28   }
29   #[inline]
align_power_of_two(&self, n: usize) -> usize30   fn align_power_of_two(&self, n: usize) -> usize {
31     self.ceil_log2(n)
32   }
33   #[inline]
align_power_of_two_and_shift(&self, n: usize) -> usize34   fn align_power_of_two_and_shift(&self, n: usize) -> usize {
35     (self + (1 << n) - 1) >> n
36   }
37 }
38 
clamp<T: PartialOrd>(input: T, min: T, max: T) -> T39 pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
40   if input < min {
41     min
42   } else if input > max {
43     max
44   } else {
45     input
46   }
47 }
48 
49 pub trait ILog: PrimInt {
50   // Integer binary logarithm of an integer value.
51   // Returns floor(log2(self)) + 1, or 0 if self == 0.
52   // This is the number of bits that would be required to represent self in two's
53   //  complement notation with all of the leading zeros stripped.
54   // TODO: Mark const once trait functions can be constant
ilog(self) -> usize55   fn ilog(self) -> usize {
56     size_of::<Self>() * 8 - self.leading_zeros() as usize
57   }
58 }
59 
60 impl<T> ILog for T where T: PrimInt {}
61 
62 #[inline(always)]
msb(x: i32) -> i3263 pub fn msb(x: i32) -> i32 {
64   debug_assert!(x > 0);
65   31 ^ (x.leading_zeros() as i32)
66 }
67 
68 #[inline(always)]
round_shift(value: i32, bit: usize) -> i3269 pub const fn round_shift(value: i32, bit: usize) -> i32 {
70   (value + (1 << bit >> 1)) >> bit
71 }
72