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